Compare commits

...

3 Commits

4 changed files with 236 additions and 82 deletions

View File

@ -1,51 +1,129 @@
#include <Arduino_MKRIoTCarrier.h>
#include <WiFiNINA.h>
#include <ArduinoMqttClient.h>
#include "motor.h"
#include "secrets.h"
#define INPUT_SIZE 4
enum state {
STATE_CONNECTING,
STATE_LOGGED_OUT,
STATE_LOGGED_IN,
STATE_INPUT_PASSCODE,
};
enum state current_state;
char input_code[INPUT_SIZE + 1];
MKRIoTCarrier carrier;
WiFiSSLClient wifi_client;
MqttClient mqtt_client(wifi_client);
// Motor pins
int motor_pin1 = 8; // Blue - 28BYJ48 pin 1
int motor_pin2 = 9; // Pink - 28BYJ48 pin 2
int motor_pin3 = 10; // Yellow - 28BYJ48 pin 3
int motor_pin4 = 11; // Orange - 28BYJ48 pin 4
// Motor variables
int motor_speed = 1200;
// Motor control variables
int motor_count = 0;
int motor_count_max = 64;
int motor_lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
uint32_t green_led_color = carrier.leds.Color(0,255,0);
uint32_t green_led_color = carrier.leds.Color(0, 255, 0);
enum state {
STATE_CONNECTING,
STATE_LOGGED_OUT,
STATE_LOGGED_IN,
STATE_INPUT_PASSCODE,
};
enum state current_state;
void setup(void)
bool is_input_empty()
{
for (int i = 0; i < INPUT_SIZE; i++) {
if (input_code[i]) return false;
}
return true;
}
bool is_input_full()
{
for (int i = 0; i < INPUT_SIZE; i++) {
if (!input_code[i]) return false;
}
return true;
}
void change_state(enum state new_state)
{
// Initialize state
switch (new_state) {
case STATE_INPUT_PASSCODE:
input_code[0] = '\0';
input_code[1] = '\0';
input_code[2] = '\0';
input_code[3] = '\0';
input_code[4] = '\0';
break;
}
current_state = new_state;
draw_state();
}
void draw_state()
{
carrier.display.fillScreen(0x000);
switch (current_state) {
case STATE_CONNECTING:
carrier.display.setCursor(20, 100);
carrier.display.setTextSize(3);
carrier.display.print("Connecting..");
break;
case STATE_LOGGED_OUT:
carrier.display.setCursor(15, 100);
carrier.display.setTextSize(2);
carrier.display.print("Press Green Button");
carrier.leds.fill(green_led_color, 2, 1);
carrier.leds.setBrightness(5);
carrier.leds.show();
break;
case STATE_INPUT_PASSCODE:
if (is_input_empty()) {
carrier.display.setCursor(50, 100);
carrier.display.setTextSize(2);
carrier.display.print("Please enter");
carrier.display.setCursor(80, 120);
carrier.display.print("passcode");
} else {
carrier.display.setCursor(50, 100);
carrier.display.setTextSize(3);
for (int i = 0; i < INPUT_SIZE; i++) {
char ch = input_code[i];
if (!ch) ch = '_';
carrier.display.print(ch);
carrier.display.print(' ');
}
}
break;
case STATE_LOGGED_IN:
carrier.display.setCursor(40, 100);
carrier.display.setTextSize(3);
carrier.display.print("Logged in");
break;
}
}
void setup()
{
current_state = STATE_CONNECTING;
Serial.begin(9600);
Serial.println("Started");
carrier.noCase();
carrier.begin();
carrier.display.init(240, 240);
motor_setup();
pinMode(TFT_BACKLIGHT, OUTPUT);
digitalWrite(TFT_BACKLIGHT, HIGH);
carrier.display.setCursor(20, 100);
carrier.display.setTextSize(3);
carrier.display.print("Connecting..");
change_state(STATE_CONNECTING);
Serial.println("Connecting to WiFi...");
@ -65,32 +143,18 @@ void setup(void)
Serial.println("Connected to MQTT");
carrier.Buzzer.beep();
mqtt_client.subscribe("dispense");
mqtt_client.subscribe("login");
carrier.display.fillScreen(0x000);
current_state = STATE_LOGGED_OUT;
carrier.display.setCursor(15, 100);
carrier.display.setTextSize(2);
carrier.display.print("Press Green Button");
carrier.leds.begin();
carrier.leds.fill(green_led_color, 2, 1);
carrier.leds.setBrightness(5);
carrier.leds.show();
carrier.Buttons.begin();
// Pinouts for motor - DO NOT ADD CODE AFTER THIS
pinMode(motor_pin1, OUTPUT);
pinMode(motor_pin2, OUTPUT);
pinMode(motor_pin3, OUTPUT);
pinMode(motor_pin4, OUTPUT);
//do NOT add code after this. DON'T DO IT.
change_state(STATE_LOGGED_OUT);
}
void loop(void)
void loop()
{
carrier.Buttons.update();
carrier.Buttons.update();
// Rotate motor if needed
if (motor_count) {
motor_clockwise();
@ -100,55 +164,71 @@ void loop(void)
// Receive MQTT messages
int message_size = mqtt_client.parseMessage();
if (message_size) {
String topic = mqtt_client.messageTopic();
Serial.print("Got message with topic: ");
Serial.println(mqtt_client.messageTopic());
Serial.println(topic);
if (mqtt_client.messageTopic() == "dispense") {
// Parse message
char *message = (char *)malloc(message_size + 1);
for (int i = 0; i < message_size && mqtt_client.available(); i++) {
message[i] = (char)mqtt_client.read();
}
message[message_size] = '\0';
Serial.print("and payload: ");
Serial.println(message);
// Check topic
if (topic == "dispense") {
Serial.println("Dispensing...");
// Start rotating motor
motor_count = motor_count_max;
} else if (topic == "login") {
Serial.println("Logged in");
int user_id;
if (sscanf(message, "%d", &user_id) > 0) {
change_state(STATE_LOGGED_IN);
} else {
change_state(STATE_INPUT_PASSCODE);
}
}
free(message);
}
switch (current_state) {
case STATE_LOGGED_OUT:
if(carrier.Buttons.onTouchDown(TOUCH2)) {
current_state = INPUT_PASSCODE;
}
break;
switch (current_state) {
case STATE_LOGGED_OUT:
if (carrier.Buttons.onTouchDown(TOUCH2)) {
change_state(STATE_INPUT_PASSCODE);
}
break;
case STATE_INPUT_PASSCODE:
touchButtons buttons[] = { TOUCH0, TOUCH1, TOUCH3, TOUCH4 };
char input_characters[] = "1234";
default:
break;
};
for (int i = 0; i < sizeof(buttons) / sizeof(buttons[0]); i++) {
if (carrier.Buttons.onTouchDown(buttons[i])) {
for (int j = 0; j < INPUT_SIZE; j++) {
if (!input_code[j]) {
input_code[j] = input_characters[i];
break;
}
}
}
if (is_input_full()) {
mqtt_client.beginMessage("login_request");
mqtt_client.print(input_code);
mqtt_client.endMessage();
}
draw_state();
break;
}
}
//motorgøgl, pls dont touch
void motor_clockwise()
{
for (int i = 7; i >= 0; i--) {
motor_set_output(i);
delayMicroseconds(motor_speed);
break;
}
}
void motor_anticlockwise()
{
for (int i = 0; i < 8; i++) {
motor_set_output(i);
delayMicroseconds(motor_speed);
}
}
void motor_set_output(int out)
{
digitalWrite(motor_pin1, bitRead(motor_lookup[out], 0));
digitalWrite(motor_pin2, bitRead(motor_lookup[out], 1));
digitalWrite(motor_pin3, bitRead(motor_lookup[out], 2));
digitalWrite(motor_pin4, bitRead(motor_lookup[out], 3));
}

2
arduino/motor.h Normal file
View File

@ -0,0 +1,2 @@
void motor_anticlockwise();
void motor_setup();

42
arduino/motor.ino Normal file
View File

@ -0,0 +1,42 @@
int motor_speed = 1200;
int motor_lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
// Motor pins
// Pins 8 and 9 conflict with the display
int motor_pin1 = 10; // Blue - 28BYJ48 pin 1
int motor_pin2 = 11; // Pink - 28BYJ48 pin 2
int motor_pin3 = 12; // Yellow - 28BYJ48 pin 3
int motor_pin4 = 13; // Orange - 28BYJ48 pin 4
void motor_setup()
{
pinMode(motor_pin1, OUTPUT);
pinMode(motor_pin2, OUTPUT);
pinMode(motor_pin3, OUTPUT);
pinMode(motor_pin4, OUTPUT);
}
void motor_clockwise()
{
for (int i = 7; i >= 0; i--) {
motor_set_output(i);
delayMicroseconds(motor_speed);
}
}
void motor_anticlockwise()
{
for (int i = 0; i < 8; i++) {
motor_set_output(i);
delayMicroseconds(motor_speed);
}
}
void motor_set_output(int out)
{
digitalWrite(motor_pin1, bitRead(motor_lookup[out], 0));
digitalWrite(motor_pin2, bitRead(motor_lookup[out], 1));
digitalWrite(motor_pin3, bitRead(motor_lookup[out], 2));
digitalWrite(motor_pin4, bitRead(motor_lookup[out], 3));
}

View File

@ -49,9 +49,39 @@ var options = new MqttClientOptionsBuilder()
await mqttClient.ConnectAsync(options, CancellationToken.None);
ApplicationState.MqttClient = mqttClient;
await mqttClient.SubscribeAsync(
new MqttFactory().CreateSubscribeOptionsBuilder().WithTopicFilter(f => f.WithTopic("login_request")).Build(),
CancellationToken.None
);
ApplicationState.DbContext = new DispenserContext();
mqttClient.ApplicationMessageReceivedAsync += delegate(MqttApplicationMessageReceivedEventArgs args) {
var payload = System.Text.Encoding.Default.GetString(args.ApplicationMessage.PayloadSegment);
switch (args.ApplicationMessage.Topic) {
case "login_request":
var user = ApplicationState.DbContext!.Users.FirstOrDefault(user => user.TouchCode == payload);
var message = new MqttApplicationMessageBuilder()
.WithTopic("login");
if (user == null) {
message.WithPayload("error");
} else {
message.WithPayload(user.Id.ToString());
}
mqttClient.PublishAsync(message.Build());
break;
}
return Task.CompletedTask;
};
ApplicationState.MqttClient = mqttClient;
Console.WriteLine("Connected");
app.Run();