Reading incorrect serial data from external program

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
oszfather
Posts: 11
Joined: Tue Jun 14, 2022 5:27 pm
Has thanked: 2 times

Reading incorrect serial data from external program

Postby oszfather » Wed Jul 06, 2022 7:03 pm

I have a seperate C++ desktop application that is able to open com port connected to the stm32. the stm32 is transmitting serial data. The serial data is "12345". The C++ program should display this with the letters S and E surrounding it (to indicate start and end of recieved data).

The code for the serial config and transmission thread :

Code: Select all

/* Serial configuration. */
static const SerialConfig myserialcfg = {
  115200,
  0,
  USART_CR2_STOP1_BITS,
  0
};

static THD_FUNCTION(ThdSerial, arg) {
  (void) arg;
  chRegSetThreadName("Serial manager");

  /* Configuring VCP related GPIO. This configuration is already
     performed at board level initialization but is here reported
     only as example of how to configure GPIO at application level. */
  palSetPadMode(GPIOA, 2U, PAL_MODE_ALTERNATE(7) | PAL_STM32_OSPEED_HIGHEST |
                           PAL_STM32_OTYPE_PUSHPULL);
  palSetPadMode(GPIOA, 3U, PAL_MODE_ALTERNATE(7) | PAL_STM32_OSPEED_HIGHEST |
                           PAL_STM32_OTYPE_PUSHPULL);

  /* Starting Serial Driver 2 with our configuration. */
  sdStart(&SD2, &myserialcfg);

  while(true) {
      chprintf(chp, "12345");
      chThdSleepMilliseconds(20);

  }
}


Main thread:

Code: Select all

int main(void) {
  halInit();
  chSysInit();
 
  palSetPadMode(GPIOA, 1, PAL_MODE_INPUT_ANALOG);
  palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(1));

  // Serial thread
  chThdCreateStatic(waThdSerial, sizeof(waThdSerial), NORMALPRIO+1, ThdSerial,NULL)

  while (true) {

    chThdSleepMilliseconds(2);
}


I've noticed the data is only being read by the C++ program correctly when the thread sleep function in the serial thread is 20ms (from trial and error) ( chThdSleepMilliseconds(20) )

When it is 5ms. The c++ application reads the data multiple times in one instance like so:

Code: Select all

 S12345123451234512345E S123451234512345E S12345123451234E S5123451234512345E S123451234512345E S123451234512345E S1234512345123451234512345E S1234512345E S123451234512345E


When it is raised to 35ms some of the incoming data is skipped like so:

Code: Select all

 SE S12345E SE S12345E SE S12345E SE S12345E SE S12345E SE S12345E SE S12345E SE SE S12345E SE S12345E SE S12345E SE S12345E SE S12345E S12345E SE


Why is this happening and how can i make it so that whatever the length of the message that needs to be sent isn't related to the delay time so both short and long messages arrive in one complete instance?

(as a note, there is no sleeping on the C++ application side. It is polling 24/7)

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Reading incorrect serial data from external program

Postby Giovanni » Wed Jul 06, 2022 8:50 pm

Hi,

If you read the data with a serial terminal emulator, do you read the correct data? if so the problem is on the desktop application side.

Note that the serial driver is buffered and does not depend on timings data is queued and the writer thread would simply wait if the buffer is full.

Giovanni

oszfather
Posts: 11
Joined: Tue Jun 14, 2022 5:27 pm
Has thanked: 2 times

Re: Reading incorrect serial data from external program

Postby oszfather » Thu Jul 07, 2022 5:18 pm

Giovanni wrote:Hi,

If you read the data with a serial terminal emulator, do you read the correct data? if so the problem is on the desktop application side.

Note that the serial driver is buffered and does not depend on timings data is queued and the writer thread would simply wait if the buffer is full.

Giovanni



Yes, the application side was where the issue was, thanks. While on the subject of serial communication. I'm trying to read info back from the desktop app. The desktop app is sending the string "message". What is the proper usage of sdRead(sdp,b,n) ?

Code: Select all

  static char str[255];

  while(true) {
    sdRead(&SD2, str,255);
    chprintf(chp, "recieved: %s \r\n", str);
    }



the sdRead function here is blocking and nothing gets printed. How should it be written instead? is it preferable to use sdGet and append each incoming character to a char[] array especially if each incoming string varies in length?
Last edited by oszfather on Thu Jul 07, 2022 7:17 pm, edited 2 times in total.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Reading incorrect serial data from external program

Postby Giovanni » Thu Jul 07, 2022 7:15 pm

Hi,

Serial communication is not that easy, you cannot assume that the 2 parties are in synch, if try to ready 6 bytes and the sender only sends 5 then the receiver is stuck indefinitely.

Some possible approaches:
- Use timeouts on receive.
- Use message delimiters, for example lines of text ended by a CR.

In general design a state machine for your serial protocol, you need to handle cases such as loss of sync, lost chars, communication errors. An ideal protocol should be able to recover from all those kind of things.

Giovanni

oszfather
Posts: 11
Joined: Tue Jun 14, 2022 5:27 pm
Has thanked: 2 times

Re: Reading incorrect serial data from external program

Postby oszfather » Thu Jul 07, 2022 7:21 pm

Giovanni wrote:Hi,

Serial communication is not that easy, you cannot assume that the 2 parties are in synch, if try to ready 6 bytes and the sender only sends 5 then the receiver is stuck indefinitely.

Some possible approaches:
- Use timeouts on receive.
- Use message delimiters, for example lines of text ended by a CR.

In general design a state machine for your serial protocol, you need to handle cases such as loss of sync, lost chars, communication errors. An ideal protocol should be able to recover from all those kind of things.

Giovanni


Thanks for the advice. I've managed to recieve the "message" string using the timeout version of the sdRead function. Lastly is there some kind of condition I can check or a function that gets called ONCE when a string arrives.

Code: Select all

 int8_t wordcount = 0;
  static char str[255];

  while(true) {

    sdReadTimeout(&SD2, str, 255, TIME_MS2I(50));
   
    if(strcmp( str,"message")==0) {
      wordcount++;
      }

    chprintf(chp, "recieved: %d £%s£ \r\n", wordcount,str);
    chprintf(chp, "ok");

    }
 


the if statement just checks is str is equal to message and increments 'wordcount' forever. Is there some method that is run once upon arrival of a string so wordcount is incremented once whenever "message" is recieved?

psyco
Posts: 21
Joined: Fri May 22, 2020 1:40 am
Been thanked: 11 times

Re: Reading incorrect serial data from external program

Postby psyco » Thu Jul 07, 2022 11:26 pm

What is happening is the sdReadTimeout call is timing out due to receiving no bytes and not modifying your buffer, leaving the "message" string from the reception untouched and still valid. You need to check the return value of sdReadTimeout (which calls iqReadTimeout) which is the number of bytes actually received by the application (similar to POSIX read, or Windows ReadFile's lpNumberOfBytesRead out value):

http://chibiforge.org/doc/21.11/hal/gro ... 01a13277d6

However, you'll likely have another issue of dropped messages. This would be due to the message not aligning with the 50 ms timeout (for example, the last byte might arrive at 51 ms after the call to sdReadTimeout, just after the timeout). You could split the reads into two, the first reading just one byte (with or without a timeout), and the second reading the rest of the bytes if the first one read a byte (this time with the timeout).

I agree with Giovanni that you should frame / packetize your data somehow so the receiver can resync to the data stream. Timing serial like that isn't extremely reliable from a computer.


Return to “ChibiOS/HAL”

Who is online

Users browsing this forum: No registered users and 14 guests