Last active
June 22, 2023 17:29
-
-
Save jasonhejna/20e21904327408b7d437d2ec78c12df0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@akhockey21 Here's the firmware.