Skip to content

Instantly share code, notes, and snippets.

@jasonhejna
Last active June 22, 2023 17:29
Show Gist options
  • Save jasonhejna/20e21904327408b7d437d2ec78c12df0 to your computer and use it in GitHub Desktop.
Save jasonhejna/20e21904327408b7d437d2ec78c12df0 to your computer and use it in GitHub Desktop.
/*
Digalog
{"relay1":0,"relay2":1,"UUID":"tornado-airplane","pot1":[80,985],"pot2":[50,353],"pot3":[50]}
*/
#include <ArduinoJson.h>
#include <FlashStorage_SAMD.h>
// UUID placeholder
String UUID = "tornado-airplane";
int BUTTON1 = 6;
int BUTTON2 = 5;
int button1LastState = HIGH;
int button2LastState = HIGH;
int RELAY1 = 12;
int RELAY2 = 11;
//int IN11 = 10;
//int IN21 = 9;
//float POT1 = A0; // Changed to float
float POT1_SENSOR_VALUE;
//int IN12 = A4;
//int IN22 = A5;
//float POT2 = A1; // Changed to float
float POT2_SENSOR_VALUE;
//int IN13 = MOSI;
//int IN23 = MISO;
//float POT3 = A2; // Changed to float
float POT3_SENSOR_VALUE;
int motorSpeed = 160;
// Global variables to store motor control state
int POT[3] = { A0, A1, A2 };
int IN1[3] = { 10, A4, MOSI };
int IN2[3] = { 9, A5, MISO };
int targetResistance[3];
int currentSensorValue[3];
unsigned long lastUpdateTime[3];
unsigned long updateInterval = 50; // Update interval (50 ms)
int motorDirection[3];
int targetPercent[3];
unsigned long lastCommandTime = 0; // Timestamp of the last received command
const unsigned long commandTimeout = 22000; // Timeout period in milliseconds (22 seconds)
bool motorPositionsReached = false; // Flag to indicate if all motor positions have been reached
// EEPROM addresses for storing potentiometer values and relay states
#define EEPROM_ADDR_POT1 0
#define EEPROM_ADDR_POT2 1
#define EEPROM_ADDR_POT3 2
#define EEPROM_ADDR_RELAY1 3
#define EEPROM_ADDR_RELAY2 4
int percentToResistance(int percent) {
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
if (percent <= 4) {
return 1023;
} else if (percent <= 10) {
return 1022;
} else if (percent <= 15) {
return 1019;
} else if (percent <= 20) {
return 1015;
} else if (percent <= 25) {
return 1010;
} else if (percent <= 30) {
return 1001;
} else if (percent <= 35) {
return 992;
} else if (percent <= 40) {
return 983;
} else if (percent <= 45) {
return 972;
} else if (percent <= 50) {
return 958;
} else if (percent <= 55) {
return 929;
} else if (percent <= 60) {
return 810;
} else if (percent <= 65) {
return 685;
} else if (percent <= 70) {
return 571;
} else if (percent <= 75) {
return 460;
} else if (percent <= 80) {
return 342;
} else if (percent <= 85) {
return 228;
} else if (percent <= 90) {
return 100;
} else if (percent <= 95) {
return 2;
} else {
return 1;
}
}
void setup() {
Serial.begin(9600);
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(RELAY1, OUTPUT);
pinMode(BUTTON2, INPUT_PULLUP);
pinMode(RELAY2, OUTPUT);
pinMode(IN1[0], OUTPUT);
pinMode(IN1[1], OUTPUT);
pinMode(IN1[2], OUTPUT);
pinMode(IN2[0], OUTPUT);
pinMode(IN2[1], OUTPUT);
pinMode(IN2[2], OUTPUT);
// Retrieve potentiometer values and relay states from EEPROM
targetPercent[0] = EEPROM.read(EEPROM_ADDR_POT1);
targetPercent[1] = EEPROM.read(EEPROM_ADDR_POT2);
targetPercent[2] = EEPROM.read(EEPROM_ADDR_POT3);
targetResistance[0] = percentToResistance(targetPercent[0]);
targetResistance[1] = percentToResistance(targetPercent[1]);
targetResistance[2] = percentToResistance(targetPercent[2]);
digitalWrite(RELAY1, EEPROM.read(EEPROM_ADDR_RELAY1));
digitalWrite(RELAY2, EEPROM.read(EEPROM_ADDR_RELAY2));
}
void loop() {
String rawjson;
char json[200];
if (Serial.available() > 0) {
rawjson = Serial.readStringUntil('\n');
rawjson.toCharArray(json, 200);
run_parse(json);
}
// Update motor control state for each motor
if (millis() - lastCommandTime < commandTimeout && !motorPositionsReached) {
for (int i = 0; i < 3; i++) {
if (millis() - lastUpdateTime[i] > updateInterval) {
currentSensorValue[i] = analogRead(POT[i]);
controlMotor(i, POT[i], IN1[i], IN2[i]);
lastUpdateTime[i] = millis();
}
}
} else {
stopAllMotors();
}
// Button handling for relays
int button1State = digitalRead(BUTTON1);
int button2State = digitalRead(BUTTON2);
if (button1State != button1LastState) {
digitalWrite(RELAY1, !digitalRead(RELAY1));
delay(50); // Debounce delay
}
button1LastState = button1State;
if (button2State != button2LastState) {
digitalWrite(RELAY2, !digitalRead(RELAY2));
delay(50); // Debounce delay
}
button2LastState = button2State;
}
void run_parse(char* json) {
DynamicJsonDocument doc(200);
DeserializationError error = deserializeJson(doc, json);
if (error) {
Serial.print(F("BAD JSON: "));
Serial.println(error.f_str());
return;
}
// Check if the relay values are 0 or 1
if (doc["relay1"] < 0 || doc["relay1"] > 1 || doc["relay2"] < 0 || doc["relay2"] > 1) {
Serial.println(F("Invalid relay values. Must be 0 or 1."));
return;
}
// Check if the potentiometer target percentages are within the valid range
if (doc["pot1"][0] < 0 || doc["pot1"][0] > 100 || doc["pot2"][0] < 0 || doc["pot2"][0] > 100 || doc["pot3"][0] < 0 || doc["pot3"][0] > 100) {
Serial.println(F("Invalid potentiometer values. Must be between 0 and 100 for pot1 pot2 and pot3."));
return;
}
// Check if the status value is 0 or 1
if (doc["status"] < 0 || doc["status"] > 1) {
Serial.println(F("Invalid status value. Must be 0 or 1."));
return;
}
// Return JSON representing the current state of the unit
if (doc["status"] == "1" || doc["status"] == 1 || doc["status"] == "true") {
DynamicJsonDocument responseDoc(200);
responseDoc["relay1"] = digitalRead(BUTTON1);
responseDoc["relay2"] = digitalRead(BUTTON2);
responseDoc["UUID"] = UUID; // Add UUID
responseDoc["pot1"][0] = doc["pot1"][0];
responseDoc["pot1"][1] = analogRead(POT[0]);
responseDoc["pot2"][0] = doc["pot2"][0];
responseDoc["pot2"][1] = analogRead(POT[1]);
responseDoc["pot3"][0] = doc["pot3"][0];
responseDoc["pot3"][1] = analogRead(POT[2]);
String response;
serializeJson(responseDoc, response);
Serial.println(response);
}
digitalWrite(RELAY1, doc["relay1"]);
digitalWrite(RELAY2, doc["relay2"]);
EEPROM.update(EEPROM_ADDR_RELAY1, doc["relay1"]);
EEPROM.update(EEPROM_ADDR_RELAY2, doc["relay2"]);
targetPercent[0] = doc["pot1"][0];
targetPercent[1] = doc["pot2"][0];
targetPercent[2] = doc["pot3"][0];
EEPROM.update(EEPROM_ADDR_POT1, targetPercent[0]);
EEPROM.update(EEPROM_ADDR_POT2, targetPercent[1]);
EEPROM.update(EEPROM_ADDR_POT3, targetPercent[2]);
targetResistance[0] = percentToResistance(targetPercent[0]);
targetResistance[1] = percentToResistance(targetPercent[1]);
targetResistance[2] = percentToResistance(targetPercent[2]);
// Update current sensor values
currentSensorValue[0] = analogRead(POT[0]);
currentSensorValue[1] = analogRead(POT[1]);
currentSensorValue[2] = analogRead(POT[2]);
// Update the last command time when a new command is received
lastCommandTime = millis();
// Reset the motor positions reached flag
motorPositionsReached = false;
}
void controlMotor(int motorIndex, int potPin, int in1Pin, int in2Pin) {
// Control motor based on current sensor value and target resistance
targetResistance[motorIndex] = percentToResistance(targetPercent[motorIndex]);
// Update current sensor values
currentSensorValue[motorIndex] = analogRead(POT[motorIndex]);
// Determine motor direction based on current and target positions
if (targetPercent[motorIndex] > currentSensorValue[motorIndex]) {
motorDirection[motorIndex] = 0; // Turn in one direction
} else if (targetPercent[motorIndex] < currentSensorValue[motorIndex]) {
motorDirection[motorIndex] = 1; // Turn in the other direction
}
if (abs(targetResistance[motorIndex] - currentSensorValue[motorIndex]) > 3) {
if (motorDirection[motorIndex] == 1) {
if (currentSensorValue[motorIndex] < targetResistance[motorIndex]) {
analogWrite(in1Pin, motorSpeed);
analogWrite(in2Pin, 0);
} else {
analogWrite(in1Pin, 0);
analogWrite(in2Pin, motorSpeed);
}
} else {
if (currentSensorValue[motorIndex] < targetResistance[motorIndex]) {
analogWrite(in1Pin, 0);
analogWrite(in2Pin, motorSpeed);
} else {
analogWrite(in1Pin, motorSpeed);
analogWrite(in2Pin, 0);
}
}
} else {
// Stop motor if target resistance is reached
analogWrite(in1Pin, 0);
analogWrite(in2Pin, 0);
}
// Check if the current sensor value has reached the target resistance
if (abs(targetResistance[motorIndex] - currentSensorValue[motorIndex]) <= 3) {
// If all motor positions have been reached, set the motorPositionsReached flag to true
motorPositionsReached = true;
}
}
void stopAllMotors() {
analogWrite(IN1[0], 0);
analogWrite(IN1[1], 0);
analogWrite(IN1[2], 0);
analogWrite(IN2[0], 0);
analogWrite(IN2[1], 0);
analogWrite(IN2[2], 0);
}
@jasonhejna
Copy link
Author

@akhockey21 Here's the firmware.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment