Can I start Dash Timer within an interrupt?


#1

I am wanting to receive raw data (values 0-255) on serial port.

Because I cannot parse the data based on start and end of string terminators, I need to use a character or packet timeout function and wondering if the timer can be started from the serialEvent handler like this…

void setup(){
Dash.attachTimer(ComTimeout);
Receiving = false;
}

void ComTimeout(){
if(receiving){
receiving = false;
if(validPacket) datainRxBuf = true;
}
}

void SerialEvent(){
if(!receiving) {
dataPtr = 0;
receiving = true;
}
rx_buf[dataPtr] = Serial.read();
Dash.startTimerMS(5,0);
}

loop(){
if(dataInRxBuf){
dataInRxBuf = false;
//process packet
}
}


#2

Unfortunately the Arduino Serial class doesn’t work like that with a SerialEvent() function available. As data is received from the serial port, the internal serial port buffer is filled.

The Serial.read() function does return an int in the range 0-255, or -1 if the buffer is empty.

You can either use read() and check for -1, or poll Serial.available() in the loop().

For timing, you can certainly use the Dash hardware timer. You can also call millis() to get the current tick-time milliseconds value and do a start vs now comparison for timeouts.


#3

Thanks Eric,
So it would work better like this?

void setup(){
Dash.attachTimer(ComTimeout);
receiving = false;
dataInRxBuf = false;
dataPtr = 0;
}

void ComTimeout(){
if(receiving){
Dash.stopTimer();
receiving = false;
if(validPacket(rxBuf,dataPtr)) datainRxBuf = true;
}
}

loop(){
if(Serial.available()){
if(!receiving){
receiving = true;
dataPtr = 0;
}
rxBuf[dataPtr++] = Serial.read();
Dash.startTimerMS(5,0);
}

if(dataInRxBuf){
dataInRxBuf = false;
processPacket(rxBuf,dataPtr);
}
}


#4

When using an asynchronous timer like that I worry about race conditions. You may have an easier time using the Arduino Stream functions that the Serial object provides.

#define MAX_MESSAGE_LEN 256
uint8_t rxBuf[MAX_MESSAGE_LEN];

void processPacket(void *buff, int size) {
  
}

void setup() {
  Serial.begin();
  Serial.setTimeout(5);
}

void loop() {
  if (Serial.available()) {
    int numRead = Serial.readBytes(rxBuf, MAX_MESSAGE_LEN);
    processPacket(rxBuf, numRead);
  }
}

#5

Just a couple of questions about your example:

  1. How do we know when packet has arrived without the timer?
  2. does readBytes pop data into rxBuf as bytes are being received? If so, how can I process the unfinished packet, I only want to process after packet is received.

#6

That code was equivalent to your timer code. Serial.readBytes() will fill rxBuf until the max size is reached OR the timeout occurs. The timeout value is set using setTimeout, in this case 5ms. The Arduino docs do a pretty good job of explaining how it works.


#7

Eric,

Excellent, I did not see the serial timeout or know you could set it, that is a much more elegant solution for my project, much appreciated.

I am used to doing all the serial stuff manually, it is good to see it has been taken care of in their library.