Hello, I am looking for a bit of help (not sure if its hardware or software problem), but basically my code has the ability to turn on/off different relays at different time intervals.
When executing and running all seems to be working very well. But after a day or so of running it simply just stops working; I am taking a guess and assuming that the memory is being oversaturated? Not sure. Could also be power supply?
My initial solution is to disconnect the arduino USB power supply and reconnect, but hopefully there can be a more elegant solution.
Here is my code:
//////////////////////////////////////////////////////////
//Variables for Serial parse
//////////////////////////////////////////////////////////
const byte numChars = 128;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
boolean newData = false;
//////////////////////////////////////////////////////////
//Variables for selecting valves to turn ON/OFF
//////////////////////////////////////////////////////////
int valvePower[9] = {1,1,1,1,0,0,0,0};
//////////////////////////////////////////////////////////
//Variables for declaring the time ON/OFF for the valves
//////////////////////////////////////////////////////////
int timeOn[9] = {1000,500,200,1000,1000,2000,500,500}; //The amount of time the valve stays open
int timeOff[9] = {1500,1000,500,2000,2000,3000,1000,1000}; //This is the TOTAL time between an ON/OFF lopp
//if we want to have a valve0 ON 1 sec and OFF 1 sec
//then we need timeOn[0] = 1000;
//and we need timeOff[0] = 2000;
//////////////////////////////////////////////////////////
//Variable for pin declaration
//////////////////////////////////////////////////////////
const int valvePins[9] = {2,3,4,5,6,7,8,9};
//////////////////////////////////////////////////////////
//Variables for running the millis() function
//////////////////////////////////////////////////////////
byte valveStatus[9] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
unsigned long currentMillis = 0;
unsigned long previousValvesMillis[9] = {0,0,0,0,0,0,0,0};
//////////////////////////////////////////////////////////
//Main Set-up
//////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
//Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino"); // so we know what sketch is running
for (int i = 0; i <9; i++){
pinMode(valvePins[i], OUTPUT);
}
delay(2000);
}
//////////////////////////////////////////////////////////
//Main loop function
//////////////////////////////////////////////////////////
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
currentMillis = millis(); // capture the latest value of millis()
// this is equivalent to noting the time from a clock
// use the same time for all LED flashes to keep them synchronized
updateValve0();
updateValve1();
updateValve2();
updateValve3();
updateValve4();
updateValve5();
updateValve6();
updateValve7();
valveControl();
}
//////////////////////////////////////////////////////////
//Function for initializing the marker for receiving data
//////////////////////////////////////////////////////////
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//////////////////////////////////////////////////////////
//Function to parse data
//////////////////////////////////////////////////////////
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[0] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[0] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[0] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[1] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[1] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[1] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[2] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[2] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[2] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[3] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ",");
timeOn[3] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
timeOff[3] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[4] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[4] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[4] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[5] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[5] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[5] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[6] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[6] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[6] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
valvePower[7] = atoi(strtokIndx); // convert this part to an
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOn[7] = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
timeOff[7] = atoi(strtokIndx); // convert this part to an integer
}
//////////////////////////////////////////////////////////
//Function for timer of first valve
//////////////////////////////////////////////////////////
void updateValve0(){
if(valveStatus[0] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[0] >= timeOff[0]){
// time is up, so change the state to HIG
valveStatus[0] = HIGH;
// and save the time when we made the change
previousValvesMillis[0]+= timeOff[0] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[0] >= timeOn[0]){
// time is up, so change the state to LOW
valveStatus[0] = LOW;
// and save the time when we made the change
previousValvesMillis[0];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of second valve
//////////////////////////////////////////////////////////
void updateValve1(){
if(valveStatus[1] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[1] >= timeOff[1]){
// time is up, so change the state to HIG
valveStatus[1] = HIGH;
// and save the time when we made the change
previousValvesMillis[1]+= timeOff[1] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[1] >= timeOn[1]){
// time is up, so change the state to LOW
valveStatus[1] = LOW;
// and save the time when we made the change
previousValvesMillis[1];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of third valve
//////////////////////////////////////////////////////////
void updateValve2(){
if(valveStatus[2] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[2] >= timeOff[2]){
// time is up, so change the state to HIG
valveStatus[2] = HIGH;
// and save the time when we made the change
previousValvesMillis[2]+= timeOff[2] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
if(currentMillis - previousValvesMillis[2] >= timeOn[2]){
// time is up, so change the state to LOW
valveStatus[2] = LOW;
// and save the time when we made the change
previousValvesMillis[2];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of fourth valve
//////////////////////////////////////////////////////////
void updateValve3(){
if(valveStatus[3] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[3] >= timeOff[3]){
// time is up, so change the state to HIG
valveStatus[3] = HIGH;
// and save the time when we made the change
previousValvesMillis[3]+= timeOff[3] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[3] >= timeOn[3]){
// time is up, so change the state to LOW
valveStatus[3] = LOW;
// and save the time when we made the change
previousValvesMillis[3];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of fifth valve
//////////////////////////////////////////////////////////
void updateValve4(){
if(valveStatus[4] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[4] >= timeOff[4]){
// time is up, so change the state to HIG
valveStatus[4] = HIGH;
// and save the time when we made the change
previousValvesMillis[4]+= timeOff[4] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[4] >= timeOn[4]){
// time is up, so change the state to LOW
valveStatus[4] = LOW;
// and save the time when we made the change
previousValvesMillis[4];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of sixth valve
//////////////////////////////////////////////////////////
void updateValve5(){
if(valveStatus[5] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[5] >= timeOff[5]){
// time is up, so change the state to HIG
valveStatus[5] = HIGH;
// and save the time when we made the change
previousValvesMillis[5]+= timeOff[5] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[5] >= timeOn[5]){
// time is up, so change the state to LOW
valveStatus[5] = LOW;
// and save the time when we made the change
previousValvesMillis[5];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of seventh valve
//////////////////////////////////////////////////////////
void updateValve6(){
if(valveStatus[6] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[6] >= timeOff[6]){
// time is up, so change the state to HIG
valveStatus[6] = HIGH;
// and save the time when we made the change
previousValvesMillis[6]+= timeOff[6] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[6] >= timeOn[6]){
// time is up, so change the state to LOW
valveStatus[6] = LOW;
// and save the time when we made the change
previousValvesMillis[6];
}
}
}
//////////////////////////////////////////////////////////
//Function for timer of eigth valve
//////////////////////////////////////////////////////////
void updateValve7(){
if(valveStatus[7] == LOW){ // if the valve is off, we must wait for the interval to expire before turning it on
if(currentMillis - previousValvesMillis[7] >= timeOff[7]){
// time is up, so change the state to HIG
valveStatus[7] = HIGH;
// and save the time when we made the change
previousValvesMillis[7]+= timeOff[7] ;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if(currentMillis - previousValvesMillis[7] >= timeOn[7]){
// time is up, so change the state to LOW
valveStatus[7] = LOW;
// and save the time when we made the change
previousValvesMillis[7];
}
}
}
//////////////////////////////////////////////////////////
//Function to show Data
//////////////////////////////////////////////////////////
void showParsedData() {
Serial.print("Message ");
Serial.println(messageFromPC);
Serial.print("valve0 power ");
Serial.println(valvePower[0]);
Serial.print("valve0 ON ");
Serial.println(timeOn[0]);
Serial.print("valve1 OFF ");
Serial.println(timeOff[0]);
Serial.print("valve1 power ");
Serial.println(valvePower[1]);
Serial.print("valve1 ON ");
Serial.println(timeOn[1]);
Serial.print("valve1 OFF ");
Serial.println(timeOff[1]);
Serial.print("valve2 power ");
Serial.println(valvePower[2]);
Serial.print("valve2 ON ");
Serial.println(timeOn[2]);
Serial.print("valve2 OFF ");
Serial.println(timeOff[2]);
Serial.print("valve3 power ");
Serial.println(valvePower[3]);
Serial.print("valve3 ON ");
Serial.println(timeOn[3]);
Serial.print("valve3 OFF ");
Serial.println(timeOff[3]);
Serial.print("valve4 power ");
Serial.println(valvePower[4]);
Serial.print("valve4 ON ");
Serial.println(timeOn[4]);
Serial.print("valve4 OFF ");
Serial.println(timeOff[4]);
Serial.print("valve5 power ");
Serial.println(valvePower[5]);
Serial.print("valve5 ON ");
Serial.println(timeOn[5]);
Serial.print("valve5 OFF ");
Serial.println(timeOff[5]);
Serial.print("valve6 power ");
Serial.println(valvePower[6]);
Serial.print("valve6 ON ");
Serial.println(timeOn[6]);
Serial.print("valve6 OFF ");
Serial.println(timeOff[6]);
Serial.print("valve7 power ");
Serial.println(valvePower[7]);
Serial.print("valve7 ON ");
Serial.println(timeOn[7]);
Serial.print("valve7 OFF ");
Serial.println(timeOff[7]);
}
//////////////////////////////////////////////////////////
//Function to turn ON/OFF valves
//////////////////////////////////////////////////////////
void valveControl(){
if(valvePower[0] == 1){
digitalWrite(valvePins[0], valveStatus[0]);
}
if(valvePower[1] == 1){
digitalWrite(valvePins[1], valveStatus[1]);
}
if (valvePower[2] == 1){
digitalWrite(valvePins[2], valveStatus[2]);
}
if(valvePower[3] == 1){
digitalWrite(valvePins[3], valveStatus[3]);
}
if (valvePower[4] == 1){
digitalWrite(valvePins[4], valveStatus[4]);
}
if( valvePower[5] == 1){
digitalWrite(valvePins[5], valveStatus[5]);
}
if( valvePower[6] == 1){
digitalWrite(valvePins[6], valveStatus[6]);
}
if (valvePower[7] ==1){
digitalWrite(valvePins[7], valveStatus[7]);
}
}
Thanks!