Hello,
I am attempting to upload code on an Arduino where I can receive "instruction sets" through serial communication telling the Arduino which relay to activate, when to activate it (in the form of time to wait after instruction received), and how long to keep it activated. The instructions will come in continuously, so it should not wait to finish executing an instruction before moving to the next one, rather, it should store the instructions and keep looping and execute the instructions based on the time on the board.
I originally generated the code using ChatGPT, and went through it line by line and did a fair amount of editing. I am posting the attempt at this below. Note it's got way more printing to the serial monitor than needed, because I was trying to see where the issue is.
Ultimately, what is happening is that the if statement where its supposed to be entering the code when the current time is between the activation time of the relay, and the total duration after the activation time --- that's not being entered. So it's an issue with the logic, but I just can't spot it. What is weird is that if the activation time is no delay after current time, then it enters it and runs for the duration. That is expected, but why not the same for "future activation times"?
Originally, the condition had one more condition to check to ensure that the activation time is not 0 in order to run, however, I will add that back after first figuring out what is going on here.
In terms of solutions I tried, I did the same code except declaring a unsigned long for both activation time and duration - same results, and also tried doing something simple - taking a hard coded instruction set and removing the instruction structure and seeing if I could get it to behave, I could not.
const int numRelays = 4; // Number of relays
const int relayPins[numRelays] = {2, 5, 6, 7}; // Define relay pins
const int defaultState = HIGH; // Default relay state (HIGH for negative logic)
struct RelayInstruction {
int relayPin;
float activationTime;
float duration;
};
const int maxInstructions = 10; // Maximum number of pending instructions
RelayInstruction instructions[maxInstructions]; // Array to store relay instructions
int numInstructions = 0; // Number of pending instructions
void setup() {
Serial.begin(9600); // Initialize serial communication
for (int i = 0; i < numRelays; i++) {
pinMode(relayPins[i], OUTPUT); // Set relay pins as OUTPUT
digitalWrite(relayPins[i], defaultState); // Set the default relay state
}
}
void loop() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n'); // Read data from MATLAB
processCommand(command); // Process the received command
}
// Check and execute relay instructions
unsigned long currentTime = millis();
for (int i = 0; i < numInstructions; i++) {
if (currentTime >= instructions[i].activationTime){
Serial.println("Activation time started");
}
if (currentTime < instructions[i].duration){
Serial.println("Duration ongoing");
}
if (currentTime >= instructions[i].activationTime &&
currentTime < instructions[i].duration) {
digitalWrite(instructions[i].relayPin, LOW); // Activate relay (LOW for negative logic)
Serial.println("The relay should be turn off right now");
} else {
digitalWrite(instructions[i].relayPin, HIGH); // Deactivate relay (HIGH for negative logic)
// Clear the instruction once it's completed
instructions[i].activationTime = 0;
instructions[i].duration = 0;
}
}
// Dispose of executed instructions
numInstructions = removeExecutedInstructions(instructions, numInstructions);
}
void processCommand(String command) {
// Split the command received from MATLAB
String parts[3];
int partIndex = 0;
int startIndex = 0;
for (int i = 0; i < command.length(); i++) {
if (command.charAt(i) == ',') {
parts[partIndex] = command.substring(startIndex, i);
startIndex = i + 1;
partIndex++;
}
}
parts[partIndex] = command.substring(startIndex);
if (partIndex == 2 || partIndex == 3) {
int relayPin = parts[0].toInt();
Serial.println("Relay Pin: ");
Serial.println(relayPin);
unsigned long activationTime = parts[1].toFloat();
Serial.println("Activation Time: ");
Serial.println(activationTime);
unsigned long duration = (partIndex == 3) ? parts[2].toFloat() : 0.0;
Serial.println("Duration: ");
Serial.println(duration);
if (relayPin >= 0 && relayPin < numRelays) {
// Valid instruction received, add it to the instructions array
if (numInstructions < maxInstructions) {
instructions[numInstructions].relayPin = relayPins[relayPin];
unsigned long ct = millis();
instructions[numInstructions].activationTime = (activationTime) + ct;
Serial.println("Activation Time adjusted is: ");
Serial.println(instructions[numInstructions].activationTime);
instructions[numInstructions].duration = duration + instructions[numInstructions].activationTime;
numInstructions++;
} else {
// Max instructions reached
Serial.println("Max instructions reached");
}
} else {
// Invalid relay pin received
Serial.println("Invalid relay pin received");
}
} else {
// Invalid command received
Serial.println("Invalid command received");
}
}
// Function to remove executed instructions from the array
int removeExecutedInstructions(RelayInstruction array[], int size) {
int writeIndex = 0;
for (int readIndex = 0; readIndex < size; readIndex++) {
if (array[readIndex].activationTime != 0) {
// Copy non-executed instructions to the writeIndex position
array[writeIndex] = array[readIndex];
writeIndex++;
}
}
return writeIndex;
}