Arduino MEGA timeout not working as intended

#include "U8glib.h"
const unsigned long MESSAGE_TIMEOUT = 10UL * 1000;  // 10 seconds
int relayPin2 = 9;  //This is the Arduino Pin that will control Relay #1
int relayPin3 = 8;  //This is the Arduino Pin that will control Relay #2
int milliseconds = 0, milliseconds2 = 0;
volatile float statOne = 0, statTwo = 0;;
const byte mau = 20, numChars = 32;
char receivedChars[numChars];
char dataNumber [32] = {0};
char dataBefore [32] = {0};
boolean newData = false;
char messageFromPC [32] = {0};
char intFromPC [32] = {0};
long firstPart = 999999999; //setup value to put the LED's OFF
long secPart = 999999999; //setup value to put the LED's OFF
boolean stillChecking = true;
boolean notConnected;
unsigned long lastMessage, startMillis;
U8GLIB_ST7920_128X64_1X u8g(18, 16, 17);  // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17




void lcdSetup () {
  // flip screen, if required
  // u8g.setRot180();

  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);
  }

}

void setup()
{
  lcdSetup();
  pinMode(relayPin2, HIGH);
  pinMode(relayPin3, HIGH);
  pinMode(relayPin2, OUTPUT);
  pinMode(relayPin3, OUTPUT);
  interruptSetup();
  Serial.begin(9600); //default config is 8N1 - 1 start 1 stop 8 data bits NO Parity
}


//Setup for TIMER1 and TIMER2 :
//Prescaler at 256, CTC MODE ON, TIMER COMPARE INTERRUPT
void interruptSetup() {
  noInterrupts(); // disable all interrupts
  TCCR1A = 0; //Initialize the Timer control register A for safety
  TCCR1B = 0; //Initialize the Timer control register B for safety
  TCNT1 = 0;  // intialize counter value to 0
  OCR1A = 6249;   //100 milliseconds interrupt on 256 prescaler timer1
  TCCR1B |= (1 << WGM12);   // CTC Mode ON
  TCCR1B |= (1 << CS12);  //set prescaler to 256
  TIMSK1 |= (1 << OCIE1A); //enable timer compare interrupt

  TCCR3A = 0; //Initialize the Timer control register A for safety
  TCCR3B = 0; //Initialize the Timer control register B for safety
  TCNT3 = 0;  // intialize counter value to 0
  OCR3A = 6249;   //100 milliseconds interrupt on 256 prescaler timer1
  TCCR3B |= (1 << WGM32);   // CTC Mode ON
  TCCR3B |= (1 << CS32);  //set prescaler to 256
  TIMSK3 |= (1 << OCIE3A); //enable timer compare interrupt
  interrupts();             // enable all interrupts
  // timer1 counter = (((16000000)/(256*(1/100msec)))-1) = 6249;   // preload timer1 - if the counter has reached this value, Compare Interrupt occurs and the Interrupt happens.
}


ISR(TIMER1_COMPA_vect)
{
  milliseconds++;
  if (milliseconds >= firstPart)
  {
    milliseconds = 0;
    digitalWrite(relayPin2, LOW);
  }
}


ISR(TIMER3_COMPA_vect)
{
  milliseconds2++;
  if (milliseconds2 >= secPart)
  {
    milliseconds2 = 0;
    digitalWrite(relayPin3, LOW);
  }
}


boolean flag = false;
int lastinput = 0;
void loop() {
  lcdLoop(); //turn on and start showing the LCD data
  if (lastinput != dataBefore) //check if data has changed
  lastinput = dataBefore;
  recvWithStartEndMarkers(); //receive data
  clearBuff();
  parseData(); //parse and split data with tokens
  checkSerialCom(); //check if serial communication is established
}



void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( 0, 22, "STATUS1=" );
  u8g.setPrintPos(65, 22);
  u8g.print(firstPart);
  u8g.drawStr( 0, 50, "STATUS2=" );
  u8g.setPrintPos(65, 50);
  u8g.print(secPart);
}


void lcdLoop(void) {
  // picture loop
  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(50);
}


void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<'; //startmarker for the arduino to start reading the packet - HEADER
  char endMarker = '>'; //endmarker for the arduino to end reading the packet - FOOTER
  char rc;

  // if (Serial.available() > 0) {
  while (Serial.available() > 0 && newData == false) { //while the serial is sending data
    rc = Serial.read();// read the serial data byte
    delay(2);
    lastMessage = millis(); //get the actual time since i started to read the data
    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;
    }
  }
  strcpy(dataNumber, receivedChars);//after receiveing all the data, store at a different variable
}


void clearBuff() {
  while (Serial.available() > 0 ) {
    Serial.read();
  }

}

void parseData() {
  // split the data into its parts
  if (newData == true) {
    char * strtokIndx; // this is used by strtok() as an index

    strcpy(dataBefore, dataNumber);

    strtokIndx = strtok(dataNumber, ":");     // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
    firstPart = atoi(messageFromPC);// convert this part from ASCII to integer

    strtokIndx = strtok(NULL, "/n");// this continues where the previous call left off
    strcpy(intFromPC, strtokIndx); //copy it to intFromPC
    secPart = atoi(intFromPC);     // convert this part from ASCII to integer
    newData = false;
    flag = true;
    // statOne = (firstPart * (1 / 10)); //will be added further on
    // statTwo = (secPart * (1 / 10));  //will be added further on
  }
}


int x;
void checkSerialCom() {
  // x = Serial.read(); //clear the buffer before checking
  // delay(100);

  clearBuff();
  // Serial.print("/");
  if (stillChecking) {
    if (millis() - lastMessage >= MESSAGE_TIMEOUT ) { //check if the time has reached timeout value
      if (!Serial.available() && flag) { //check if serial not available & the flag is raised after the parsing process
        notConnected = true; //if serial not available, serial is not conneceted
        while (1) { //if serial isn't available, enter an infinite loop
          digitalWrite (relayPin2, HIGH); //force switching off the relays
          digitalWrite (relayPin3, HIGH); //force switching off the relays
          if (Serial.available()) { //if serial connection is astablished stop the loop
            break;
          }
        }
        stillChecking = false; //flag to notify that checking has stopped
        flag = false; //
      }
    }
  }
  startMillis = lastMessage;
}

Hello, I have created a program that receives data sent from a C# GUI in WINDOWS FORMS.
I have 2 timers controlling 2 relays, I have set a counter on both so that every 100msec they count up and when the counters reach the time(the data that has been received from the GUI) set by the user, it switches the relay on - meaning that the user writes in the GUI the delay time that he prefers for the relays to start working.
I have a CLOSE button on the GUI that closes the serial. I want the Arduino to check every 10 seconds after I pressed the button if there is data in the serial and stop the relays from working(meaning put them on HIGH logic level).
I cannot understand why 10 seconds after I open the Serial and send data the Arduino does switch the relays off, but if I want to Open the serial and send data again it doesn’t work.
I will be glad if someone would help me :slight_smile:

Your code seems overly complicated. There is no need to use interrupts to count milliseconds. The Mega does that for you already. Just use the millis() function.

Also, this code

    strtokIndx = strtok(NULL, "/n");// this continues where the previous call left off

isn't doing what you think - that is not the newline char ('\n') but rather two chars '/' and 'n'

The program structure is difficult to follow but I guess if it appears to be ignoring attempts to send it Serial data, it is stuck in a loop.

You can’t use the serial console for debug messages, because you are using the USB connection to the PC for the C# interface, unless you use an external USBTTL device connected berween another mega serial port and another USB port on the PC.

You could switch a led on at the beginning of a loop and switch it off at the end, to see if that helps isolate the problem.

blh64:
Your code seems overly complicated. There is no need to use interrupts to count milliseconds. The Mega does that for you already. Just use the millis() function.

Also, this code

    strtokIndx = strtok(NULL, "/n");// this continues where the previous call left off

isn't doing what you think - that is not the newline char ('\n') but rather two chars '/' and 'n'

Will try the function and post.
And thank you I changed it.

6v6gt:
The program structure is difficult to follow but I guess if it appears to be ignoring attempts to send it Serial data, it is stuck in a loop.

You can’t use the serial console for debug messages, because you are using the USB connection to the PC for the C# interface, unless you use an external USBTTL device connected berween another mega serial port and another USB port on the PC.

You could switch a led on at the beginning of a loop and switch it off at the end, to see if that helps isolate the problem.

I have connected an LED and it seems that after the program enters the while loop in checkSerialCom(), it doesn't break.
I want to indicate the Arduino that I pressed the close button on the GUI and only then it should wait about 10secs and turn the relays off.
I'm having a problem with this indication as well. I attempted to send a letter to the Arduino before I close the serial port so that it only if it detects that letter it will close the relays but that doesn't seem to work.