Reading a UART input while in delay

Hi. I have the following code as part of a larger code that reads inputs from UART. It is run based on what characters are received from UART.

void RCTIC_F(char output_cmdtype[], char output_cmdparam[]) { //output are messages from UART.
  for (int repeat = 0; repeat < 5; repeat++) {
    //SOME OPERATIONS THAT PROCESS THE MESSAGE
    rtnProtocols(output_cmdtype, output_cmdparam); //Custom function to return message
    delay(950); //Switch to non-blocking if possible.
  }
}

And this is the code used to receive UART.

void loop() {
  bool readyRead = true;
  int i = 0;

  if (Serial.available() > 0) {
    i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
    messageArray[27] = '\0'; // terminate the string

//Some other message processing functions

    stringFunction *rtnpointer[] = {
      RCTIC_F, SOME_OTHER_FUNCTIONS
    };

    input in = convert(input_cmdtype);  //Using the char to enum converter.

      rtnpointer[in](input_cmdtype, input_cmdparam);
    }
  }
}

input convert(char str[]) { //A char to enum converter.
  switch (str[0]) {
    case 'F':
      if (strcmp (str, "FIRMV") == 0) return FIRMV;
      else if (strcmp (str, "FCPWM") == 0) return FCPER;
      else return INVAL;
      break;
    case 'P':
      if (str[1] == 'R') {
        if (strcmp (str, "PREVC") == 0) return PREVC;
        else if (strcmp (str, "PREST") == 0) return PREST;
      }
      else if (strcmp (str, "PPFAC") == 0) return PPFAC;
      else return INVAL;
      break;
    case 'R':
      if (str[1] == 'Q') {
        if (strcmp (str, "RQSPC") == 0) return RQSPC;
        else if (strcmp (str, "RQPRE") == 0) return RQPRE;
      }
      else if (strcmp (str, "RCTIC") == 0) return RCTIC;
      else return INVAL;
      break;
    default:
      return INVAL;
  }
}

I want to be able to break out of this function if an external message is received. Something like this:

void RCTIC_F(char output_cmdtype[], char output_cmdparam[]) { //output are messages from UART.
  for (int repeat = 0; repeat < 5; repeat++) {
    //SOME OPERATIONS THAT PROCESS THE MESSAGE
    rtnProtocols(output_cmdtype, output_cmdparam); //Custom function to return message
    delay(950); //Switch to non-blocking if possible.
    if (RCBREIsTriggered == true)
        return;
  }
}
void RCBRE_F(char output_cmdtype[], char output_cmdparam[]) { //Resistance calibration test is being conducted, returns detected resistance from calibration test
  RCBREIsTriggered = true;
  rtnProtocols(output_cmdtype, output_cmdparam);
}

My issue is that with me using delay, I don't think I can read the UART inputs while delay is being run. I am wondering how I can read said input while in the function RCTIC, where there is a delay. Please let me know if more information is required.

You answered your own question

Don't use delay(), use millis().

I thought millis was only for measuring the number of milliseconds passed since the Arduino has run the current program? I can think of a few ways off the top of my head that use millis to have a delaying effect (like using a while loop until millis has increased by 950) but all of them are blocking.

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

All of the examples require having the "timer" in the loop() function. Is there a way of doing the millis thing that I can put in, say, the RCTIC_F function without using any blocking loops?

Which MCU is being used?

I'm using a Uno, if that helps.

so you want to remain in a loop doing the rtnProtocols(output_cmdtype, output_cmdparam); for 950 milli seconds and during that time you want the thing to be responsive to a received message during the wait time, correct?

Would calling the function RTIC_F once every 950 milli seconds work?

You mean calling that function in loop() once every 950 mills?
Basic representation of what I think you mean:

void loop() {
  bool readyRead = true;
  int i = 0;

  if (Serial.available() > 0) {
    i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
    messageArray[27] = '\0'; // terminate the string

//Some other message processing functions

    stringFunction *rtnpointer[] = {
      RCTIC_F, SOME_OTHER_FUNCTIONS
    };

    input in = convert(input_cmdtype);  //Using the char to enum converter.
    if(in == RCTIC_F){
      for(int i=0;i<5;i++)
        rtnpointer[in](input_cmdtype, input_cmdparam);
      }
    }
  }
}

If you are dermined to write blocking code then replace the delay() with a while loop using millis() for timing

Something like

unsigned long startTime = millis();
int period = 950;
while (millis() - startTime < period)
{
  //read the UART here
}

I don't, however, think that is the best way of achieving what you want, but it is your choice

I'm trying not to do this with blocking code (as suggested by aarg). I am just trying to determine what the options are given that I wish to do the millis thing that I can put in the RCTIC_F function without using any blocking loops.

A suggestion, do some more reading about using millis();

something like

unsigned long interval = 950;
unsigned long previoustime= millis()
int tickcount =0;
voiding looppies()
{

if( millis()-previoustime )>= interval)
{
tickcount++;
do the rtc thing
previoustime=millis()
}
if tick >=5 then
{
do the 5 ticks thing here
ticks =0;
}

}

and if the MCU was an ESP32 doing multiple things at the same time is easier.

That's good

Let loop() do the repeating and check every time through it whether the required period has elapsed by comparing the current value of millis() with that when timing started

Elsewhere in loop() read the UART with non blocking code to receive the user input

When either the timing period ends with no input, or the input is received within the period then run the appropriate code

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.