Arduino Uno executing code under if statement that is false

First of all,
Hi all - I am first time writing to the forums, although I've been scrolling here for last 2 to 3 years.

I've encountered a weird problem and I think that is related to memory overflow or my arduino board is dying.

If statement where issue happens

if (!started) {
    Serial.println(F("Start"));
    doInst = true;
    started = true;
  }

So my program is communicating with a PC. The way I set up the process is by using String messages. Messages of course get converted to bytes and then transmitted.

Variable started is a boolean type and it's there just for syncing PC and arduino at the start(duh) and after I set it to true I do not use it later in code at all. But, for some reason my arduino still sends randomly "Start" and usually halts after that happens.

I have no idea why that happens. I have two spare arduinos,uno and nano, and if I upload the same code on them, they work without any issues. I would change the, so far faulty, arduino but it is soldered with some other components on a home-made pcb board - and I don't want to replace it if I don't have to.

I use the arduino to drive 3 stepper motors and 1 relay.

Rest of the code:

#define BUFFSIZE 10
#define MOTOR_MAX_SPEED 8
#define MOTOR_MIN_SPEED 5000

//motor control variables
bool motorON[] = {0, 0, 0}; //bool for keeping data which motor is on
bool stepMotor[] = {0, 0, 0}; //bool for stepping motors
bool dirOfMotor[] = {0, 0, 0}; //
bool canStep[] = {1, 1, 1};
int motorSpeedTimingDelay[] = {1, 1, 1}; //delay between steps
int motorSpeedTimingDelay_prev[] = {1, 1, 1};
unsigned long prevStepTime[] = {0, 0, 0};

//shiftRegister1
//0_D1_S1_D2_S2_D3_S3_0 //MSBFIRST
byte toShiftReg_1 = 0;
//shiftRegister2
byte toShiftReg_2 = 1;
//disp
bool chngOfSpd = false;
byte dispDot = 0b10000000;
byte dispByte[] = {0b01001000,
                   0b00111101,
                   0b01101101,
                   0b00011001,
                   0b00110011,
                   0b01110111,
                   0b01001100,
                   0b01111111,
                   0b01101111
                  };



int shiftRegPins[] = {11, 12, 13};
//11 - data
//12 - latch
//13 - clock

//COM
bool comAvailable = false;
int buff[BUFFSIZE][3];
int buffCounter = 0;
int currentBuff = 0;
bool buffState[BUFFSIZE];
bool valueRecieved = false;
String prevMsg;
//COM-bools
bool started = false;
bool recievedPos = false;
bool setDirSpeed = false;

int timeOut = 200;
unsigned long rC;
void setup() {
  // put your setup code here, to run once:
  for (int i = 0; i < 3; i++) {
    pinMode(shiftRegPins[i], OUTPUT);
    digitalWrite(shiftRegPins[i], LOW);
  }
  Serial.begin(9600);
}
String msg = "";
String value = "";
int currValueCounter = 0;
bool doInst = true;
bool goInst = false;

String returnMsg;
//z-2 | y-1 | r-0 -->raspored motora


void loop() {
  if (buffCounter == 10) {
    buffCounter = 0;
  }
  if (currentBuff == 10) {
    currentBuff = 0;
  }
  if (!started) {
    Serial.println(F("Start"));
    doInst = true;
    started = true;
  }
  if (doInst)
    if (msg.equals("Go")) {
      doInst = false;
      goInst = true;
    }
  if (goInst) {
    if (!buffState[buffCounter]) {
      if (millis() - rC > timeOut) {
        Serial.println("send");
        rC = millis();
      }
    }


    if (buffState[currentBuff]) {
      if (!setDirSpeed) {
        setDirSpeed = true;

        for (int i = 0; i < 3; i++) {
          if (buff[currentBuff][i] >= 0)
            toShiftReg_1 ^= (-(unsigned long)0 ^ toShiftReg_1) & (1UL << (1 + 2 * i) );
          if (buff[currentBuff][i] < 0) {
            toShiftReg_1 ^= (-(unsigned long)1 ^ toShiftReg_1) & (1UL << (1 + 2 * i) );
            buff[currentBuff][i] *= -1;
          }
        }
        if (buff[currentBuff][0] >= buff[currentBuff][1] && buff[currentBuff][0] >= buff[currentBuff][2]) {
          motorSpeedTimingDelay[0] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][1] != 0)
            motorSpeedTimingDelay[1] = (int)round((1.0 * buff[currentBuff][0]) / (buff[currentBuff][1] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][2] != 0)
            motorSpeedTimingDelay[2] = (int)round((1.0 * buff[currentBuff][0]) / (buff[currentBuff][2] * 1.0)) * MOTOR_MAX_SPEED;
        }
        else if (buff[currentBuff][1] >= buff[currentBuff][0] && buff[currentBuff][1] >= buff[currentBuff][2]) {
          motorSpeedTimingDelay[1] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][0] != 0)
            motorSpeedTimingDelay[0] = (int)round((1.0 * buff[currentBuff][1]) / (buff[currentBuff][0] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][2] != 0)
            motorSpeedTimingDelay[2] = (int)round((1.0 * buff[currentBuff][1]) / (buff[currentBuff][2] * 1.0)) * MOTOR_MAX_SPEED;
        }
        else if (buff[currentBuff][2] >= buff[currentBuff][1] && buff[currentBuff][2] >= buff[currentBuff][0]) {
          motorSpeedTimingDelay[2] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][1] != 0)
            motorSpeedTimingDelay[1] = (int)round((1.0 * buff[currentBuff][2]) / (buff[currentBuff][1] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][0] != 0)
            motorSpeedTimingDelay[0] = (int)round((1.0 * buff[currentBuff][2]) / (buff[currentBuff][0] * 1.0)) * MOTOR_MAX_SPEED;
        }
      }

      for (int i = 0; i < 3; i++) {
        if (micros() - prevStepTime[i] > motorSpeedTimingDelay[i] && canStep[i])
          stepMotor[i] = true;

        if (stepMotor[i]) {
          if (buff[currentBuff][i] > 1) {
            toShiftReg_1 ^= (-(unsigned long)1 ^ toShiftReg_1) & (1UL << (2 * (i + 1)) );
            stepMotor[i] = false;
            canStep[i] = false;
            prevStepTime[i] = micros();
          }

        } else {
          if (micros() - prevStepTime[i] > motorSpeedTimingDelay[i]) {
            if (buff[currentBuff][i] > 1) {
              toShiftReg_1 ^= (-(unsigned long)0 ^ toShiftReg_1) & (1UL << (2 * (i + 1)) );
              buff[currentBuff][i]--;
            }
            canStep[i] = true;
            prevStepTime[i] = micros();
          }
        }
      }
      shiftToReg(shiftRegPins, toShiftReg_1, toShiftReg_2);

      if (buff[currentBuff][0] <= 1 && buff[currentBuff][1] <= 1 && buff[currentBuff][2] <= 1) {
        buff[currentBuff][0] = buff[currentBuff][1] = buff[currentBuff][2] = 0;
        buffState[currentBuff] = false;
        setDirSpeed = false;
        //Serial.println(F("Buff Done: "));
        //Serial.println(currentBuff);
        currentBuff++;
        msg = "";
      }
    }
  }
}
void shiftToReg(int pins[], byte data) {
  digitalWrite( pins[1], LOW);
  shiftOut(pins[0], pins[2], MSBFIRST, data);
  digitalWrite( pins[1], HIGH);
  //delayMicroseconds(100);
}

void shiftToReg(int pins[], byte data1, byte data2) {
  digitalWrite( pins[1], LOW);
  shiftOut(pins[0], pins[2], MSBFIRST, data2);
  //delayMicroseconds(20);
  shiftOut(pins[0], pins[2], MSBFIRST, data1);
  //delayMicroseconds(20);
  digitalWrite( pins[1], HIGH);

}

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();

    // add it to the inputString:
    prevMsg += inChar;
    value += inChar;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
    if (!valueRecieved) {
      if (inChar == '|') {
        value.trim();

        value.remove(value.length() - 1, 1);
        switch (currValueCounter) {
          case 0:
            buff[buffCounter][0] = value.toInt();
            currValueCounter++;
            break;

          case 1:
            buff[buffCounter][2] = value.toInt();
            currValueCounter++;
            break;

          case 2:
            buff[buffCounter][1] = -value.toInt();
            currValueCounter = 0;
            valueRecieved = true;
            break;
        }
        value = "";
      }
    }

    // 400|200|100|
    if (inChar == '\n') {
      prevMsg.trim();
      msg = prevMsg;
      if (valueRecieved) {
        valueRecieved = false;
        /*
        Serial.print("Buffer| r: ");
        Serial.print(buff[buffCounter][0]);
        Serial.print("| y: ");
        Serial.print(buff[buffCounter][2]);
        Serial.print("| z: ");
        Serial.println(buff[buffCounter][1]);*/
        buffState[buffCounter] = true;
        buffCounter++;
        //Serial.println(msg);
        Serial.println(F("posD"));
        delay(10);
      }
      prevMsg = "";
      value = "";
    }
  }
}

Your problem is most likely due to your use of the String class. In your serialEvent() you read a char and then add it to your String variable 'prevMsg' which will eat up lots of memory and fragment it...

It looks like you copied the serialEvent tutorial sketch, but didn't copy a key part if it - In the setup() function, they pre-allocate 200 bytes so they aren't trashing memory.

My advise would be to ditch the String class and learn how to use C strings that are just char arrays that are nul terminated.

You can also use a String buffer by using String.reserve() to create the buffer, "" clears the buffer and String.concat() adds to the buffer without the issues of growing and shrinking strings mucking up memory. I start with a buffer size of 100 or 200 or 300; sBuffer.reserve(200) and then do length prints at a time when the buffer will be the most filled to get an idea of how small or large to set the value. I, typically, make the string reserve about 20ish bytes larger then the largest size noted. Works great.

blh64:
Your problem is most likely due to your use of the String class. In your serialEvent() you read a char and then add it to your String variable 'prevMsg' which will eat up lots of memory and fragment it...

It looks like you copied the serialEvent tutorial sketch, but didn't copy a key part if it - In the setup() function, they pre-allocate 200 bytes so they aren't trashing memory.

My advise would be to ditch the String class and learn how to use C strings that are just char arrays that are nul terminated.

Thank you for quick replay!

After your answer I tried using String.reserve() function but it did not solve the problem. Then I removed all of the strings and used cstrings( those are char arrays with '\0' terminators right?) and the problem stayed. Soldered arduino still halts after few messages while my spares work without any issues regardless if I use Strings(with or without reserve) or cstrings.

Here's the updated code:

#define BUFFSIZE 100
#define MOTOR_MAX_SPEED 8
#define MOTOR_MIN_SPEED 5000
#define MAX_CHAR 30
//motor control variables
bool motorON[] = {0, 0, 0}; //bool for keeping data which motor is on
bool stepMotor[] = {0, 0, 0}; //bool for stepping motors
bool dirOfMotor[] = {0, 0, 0}; //
bool canStep[] = {1, 1, 1};
int motorSpeedTimingDelay[] = {1, 1, 1}; //delay between steps
int motorSpeedTimingDelay_prev[] = {1, 1, 1};
unsigned long prevStepTime[] = {0, 0, 0};

//shiftRegister1
//0_D1_S1_D2_S2_D3_S3_0 //MSBFIRST
byte toShiftReg_1 = 0;
//shiftRegister2
byte toShiftReg_2 = 1;
//disp
bool chngOfSpd = false;
byte dispDot = 0b10000000;
byte dispByte[] = {0b01001000,
                   0b00111101,
                   0b01101101,
                   0b00011001,
                   0b00110011,
                   0b01110111,
                   0b01001100,
                   0b01111111,
                   0b01101111
                  };



int shiftRegPins[] = {11, 12, 13};
//11 - data
//12 - latch
//13 - clock

//COM
bool comAvailable = false;
int buff[BUFFSIZE][3];
int buffCounter = 0;
int currentBuff = 0;
bool buffState[BUFFSIZE];
bool valueRecieved = false;
int msgCounter = 0;
int valCounter = 0;
char c_msg[MAX_CHAR];
char c_prevMsg[MAX_CHAR];
char c_value[MAX_CHAR];
char c_go[] = "Go";

//COM-bools
bool started = false;
bool recievedPos = false;
bool setDirSpeed = false;

int timeOut = 200;
unsigned long rC;
void setup() {
  // put your setup code here, to run once:
  for (int i = 0; i < 3; i++) {
    pinMode(shiftRegPins[i], OUTPUT);
    digitalWrite(shiftRegPins[i], LOW);
  }
  Serial.begin(9600);
}


int currvalCounter = 0;
bool doInst = true;
bool goInst = false;

//z-2 | y-1 | r-0 -->raspored motora


void loop() {
  if (valueRecieved && recievedPos && started) {
    valueRecieved = false;
    recievedPos = false;
    /*
      Serial.print("Buffer| r: ");
      Serial.print(buff[buffCounter][0]);
      Serial.print("| y: ");
      Serial.print(buff[buffCounter][2]);
      Serial.print("| z: ");
      Serial.println(buff[buffCounter][1]);
      */
    buffState[buffCounter] = true;
    buffCounter++;
    //Serial.println(msg);
    Serial.println(F("posD"));
  }

  if (buffCounter == BUFFSIZE) {
    buffCounter = 0;
  }
  if (currentBuff == BUFFSIZE) {
    currentBuff = 0;
  }
  if( msgCounter == MAX_CHAR){
    msgCounter = 0;
  }
  if( valCounter == MAX_CHAR){
    valCounter = 0;
  }
  if (!started) {
    Serial.println(F("Start"));
    doInst = true;
    started = true;
  }
  if (doInst)
    if (strcmp(c_go, c_msg) == 0 && recievedPos) {
      doInst = false;
      goInst = true;
      recievedPos = false;
    }
  if (goInst) {
    if (!buffState[buffCounter]) {
      if (millis() - rC > timeOut) {
        Serial.println("send");
        rC = millis();
      }
    }


    if (buffState[currentBuff]) {
      if (!setDirSpeed) {
        setDirSpeed = true;

        for (int i = 0; i < 3; i++) {
          if (buff[currentBuff][i] >= 0)
            toShiftReg_1 ^= (-(unsigned long)0 ^ toShiftReg_1) & (1UL << (1 + 2 * i) );
          if (buff[currentBuff][i] < 0) {
            toShiftReg_1 ^= (-(unsigned long)1 ^ toShiftReg_1) & (1UL << (1 + 2 * i) );
            buff[currentBuff][i] *= -1;
          }
        }
        if (buff[currentBuff][0] >= buff[currentBuff][1] && buff[currentBuff][0] >= buff[currentBuff][2]) {
          motorSpeedTimingDelay[0] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][1] != 0)
            motorSpeedTimingDelay[1] = (int)round((1.0 * buff[currentBuff][0]) / (buff[currentBuff][1] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][2] != 0)
            motorSpeedTimingDelay[2] = (int)round((1.0 * buff[currentBuff][0]) / (buff[currentBuff][2] * 1.0)) * MOTOR_MAX_SPEED;
        }
        else if (buff[currentBuff][1] >= buff[currentBuff][0] && buff[currentBuff][1] >= buff[currentBuff][2]) {
          motorSpeedTimingDelay[1] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][0] != 0)
            motorSpeedTimingDelay[0] = (int)round((1.0 * buff[currentBuff][1]) / (buff[currentBuff][0] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][2] != 0)
            motorSpeedTimingDelay[2] = (int)round((1.0 * buff[currentBuff][1]) / (buff[currentBuff][2] * 1.0)) * MOTOR_MAX_SPEED;
        }
        else if (buff[currentBuff][2] >= buff[currentBuff][1] && buff[currentBuff][2] >= buff[currentBuff][0]) {
          motorSpeedTimingDelay[2] = MOTOR_MAX_SPEED;
          if (buff[currentBuff][1] != 0)
            motorSpeedTimingDelay[1] = (int)round((1.0 * buff[currentBuff][2]) / (buff[currentBuff][1] * 1.0)) * MOTOR_MAX_SPEED;
          if (buff[currentBuff][0] != 0)
            motorSpeedTimingDelay[0] = (int)round((1.0 * buff[currentBuff][2]) / (buff[currentBuff][0] * 1.0)) * MOTOR_MAX_SPEED;
        }
      }

      for (int i = 0; i < 3; i++) {
        if (micros() - prevStepTime[i] > motorSpeedTimingDelay[i] && canStep[i])
          stepMotor[i] = true;

        if (stepMotor[i]) {
          if (buff[currentBuff][i] > 1) {
            toShiftReg_1 ^= (-(unsigned long)1 ^ toShiftReg_1) & (1UL << (2 * (i + 1)) );
            stepMotor[i] = false;
            canStep[i] = false;
            prevStepTime[i] = micros();
          }

        } else {
          if (micros() - prevStepTime[i] > motorSpeedTimingDelay[i]) {
            if (buff[currentBuff][i] > 1) {
              toShiftReg_1 ^= (-(unsigned long)0 ^ toShiftReg_1) & (1UL << (2 * (i + 1)) );
              buff[currentBuff][i]--;
            }
            canStep[i] = true;
            prevStepTime[i] = micros();
          }
        }
      }
      shiftToReg(shiftRegPins, toShiftReg_1, toShiftReg_2);

      if (buff[currentBuff][0] <= 1 && buff[currentBuff][1] <= 1 && buff[currentBuff][2] <= 1) {
        buff[currentBuff][0] = buff[currentBuff][1] = buff[currentBuff][2] = 0;
        buffState[currentBuff] = false;
        setDirSpeed = false;
        currentBuff++;
      }
    }
  }
}
void shiftToReg(int pins[], byte data) {
  digitalWrite( pins[1], LOW);
  shiftOut(pins[0], pins[2], MSBFIRST, data);
  digitalWrite( pins[1], HIGH);
  //delayMicroseconds(100);
}

void shiftToReg(int pins[], byte data1, byte data2) {
  digitalWrite( pins[1], LOW);
  shiftOut(pins[0], pins[2], MSBFIRST, data2);
  //delayMicroseconds(20);
  shiftOut(pins[0], pins[2], MSBFIRST, data1);
  //delayMicroseconds(20);
  digitalWrite( pins[1], HIGH);

}

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();

    // add it to the inputString:
    c_prevMsg[msgCounter] = inChar;
    c_value[valCounter] = inChar;
    msgCounter++;
    valCounter++;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
    if (!valueRecieved) {
      if (inChar == '|') {
        c_value[valCounter - 1] = '\0';
        switch (currvalCounter) {
          case 0:
            sscanf(c_value, "%d", &buff[buffCounter][0]);
            currvalCounter++;
            break;

          case 1:
            sscanf(c_value, "%d", &buff[buffCounter][2]);
            currvalCounter++;
            break;

          case 2:
            sscanf(c_value, "%d", &buff[buffCounter][1]);
            buff[buffCounter][1] *= -1;
            currvalCounter = 0;
            valueRecieved = true;
            break;
        }
         valCounter = 0;
      }
    }
    // 400|200|100|
    if (inChar == '\n') {
      c_prevMsg[msgCounter-1] = '\0';
      strcpy(c_msg, c_prevMsg);
      recievedPos = true;
      msgCounter = 0;
      valCounter = 0;
    }
  }
}

What else is in the circuit? Can you draw a schematic?

Most importantly, what is sharing 5V power with the Arduino? If power drops out, the Arduino will reset.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

...R