Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
8 years, 6 months ago.
Using multiple BufferedSerial on Nucleo F091RC
Hello,
I have a problem using multiple BufferedSerial on the USARTs of NUCLEO F091RC. I picked this board because it has 8 USARTs. The PC is used for debug via USB. USART4 and USART5 are connected to a sensor that sends data every 10 seconds (82 bytes each sensor). USART8 is connected to a communication device.
To be specific when more than one USART is receiving data the program stop running (freeze).
If I comment one of the sensors the code works fine. If I use the Buffered Library only in one USART (per example only in USART4) the code works but I'm not capable to receive all the 82 bytes in the normal (non Buffered) Serial USART.
Main.cpp
#include "mbed.h" #include "BufferedSerial.h" #include "custom_f.h" Serial pc(USBTX, USBRX); BufferedSerial sensor1(PC_10, PC_11); BufferedSerial sensor2(PC_12, PD_2); Serial comDevice(PC_8, PC_9); // Not used yet DigitalOut myled(LED1); int main() { pc.baud(9600); sensor1.baud(19200); sensor2.baud(19200); comDevice.baud(115200); while(1) { if (sensor1.readable()) { pc.printf("SENSOR1: "); while(sensor1.readable()) { char incoming = sensor1.getc(); pc.putc(incoming); } pc.printf("\r\n"); } myled = !myled; wait_ms(500); if (sensor2.readable()) { pc.printf("SENSOR2: "); while(sensor2.readable()) { char incoming = sensor2.getc(); pc.putc(incoming); } pc.printf("\r\n"); } myled = !myled; wait_ms(500); } }
NOTE: To simplify the debugging process, I'm not using the real function that process the data sent by the sensor. The previous code work, is a simplified version for debug. This version freeze in the same way than the complex function, I mean when more than one USART receive data; eventually the LED1 stop "blinking" and the PC USB stop showing new data.
Can you please help ?
Thank you !
2 Answers
8 years, 6 months ago.
Hello Felícito,
Since you are receiving constant size (82 bytes) packets every ten seconds, another alternative is to use your own buffers:
#include "mbed.h" const int PACKET_SIZE = 82; // Data packet size const float RX_MAXTIME = 3.0f; // Maximum time gap between two serial bytes // (must be < time gap between two packets) char sensor1RxBuf[PACKET_SIZE]; char sensor2RxBuf[PACKET_SIZE]; volatile int sensor1RxLen = 0; volatile int sensor2RxLen = 0; Serial pc(USBTX, USBRX); Serial sensor1(PC_10, PC_11); Serial sensor2(PC_12, PD_2); Serial comDevice(PC_8, PC_9); // Not used yet DigitalOut myled(LED1); Timer rx1Timer; Timer rx2Timer; // Sensor1 serial received interrupt handler: Reads data into a buffer void onSensor1Rx(void) { if(sensor1RxLen < PACKET_SIZE) { sensor1RxBuf[sensor1RxLen++] = sensor1.getc(); rx1Timer.reset(); } else sensor1.getc(); } // Sensor2 serial received interrupt handler: Reads data into a buffer void onSensor2Rx(void) { if(sensor2RxLen < PACKET_SIZE) { sensor2RxBuf[sensor2RxLen++] = sensor2.getc(); rx2Timer.reset(); } else sensor2.getc(); } int main() { pc.baud(9600); sensor1.baud(19200); sensor2.baud(19200); comDevice.baud(115200); sensor1.attach(&onSensor1Rx); sensor2.attach(&onSensor2Rx); rx1Timer.start(); rx2Timer.start(); while(1) { // Discard incomplete/corrupted packets if (rx1Timer.read() > RX_MAXTIME) sensor1RxLen = 0; if (rx2Timer.read() > RX_MAXTIME) sensor2RxLen = 0; // Process complete packets if (sensor1RxLen == PACKET_SIZE) { sensor1RxLen = 0; pc.printf("SENSOR1: "); for(int i = 0; i < PACKET_SIZE; i++) pc.printf(" %x", sensor1RxBuf[i]); pc.printf("\r\n"); } if (sensor2RxLen == PACKET_SIZE) { sensor2RxLen = 0; pc.printf("SENSOR2: "); for(int i = 0; i < PACKET_SIZE; i++) pc.printf(" %x", sensor2RxBuf[i]); pc.printf("\r\n"); } myled = !myled; wait_ms(500); } }
8 years, 6 months ago.
For a start increase the baud rate on the pc connection and take out the waits.
Each time around your loop takes about 1.15 seconds (1s of waits plus the time it takes to send 2x 84 bytes at 9600 baud from a uart with a 16 byte tx buffer.) If you sensors are sending data at 1Hz then you aren't going to keep up with them.
There is no reason at all to have those waits in there.
For every 82 bytes that show up on a sensor you are outputting 84 bytes to the PC. Since you have two sensors that means that you should set the PC uart baud rate to at a very minimum twice the sensor baud rate, ideally faster.
Thanks for your reply Andy.
I have tried changing the pc baudrate to 38400. But it does not work, the program keep freezing when both USART receive data from the sensor1 and sensor2.I kept digging and found this table. Link: http://www.st.com/content/ccc/resource/technical/document/datasheet/95/3c/2e/5b/21/09/45/a6/DM00115237.pdf/files/DM00115237.pdf/jcr:content/translations/en.DM00115237.pdf
Table 10. STM32F091xB/xC USART implementation:
USART modes/features | USART1, 2, 3 | USART 4 | USART 5, 6, 7, 8 |
Hardware flow control for modem | X | X | - |
Continuous communication using DMA | X | X | X |
Multiprocessor communication | X | X | X |
Synchronous mode | X | X | X |
Smartcard mode | X | - | - |
Single-wire half-duplex communication | X | X | X |
IrDA SIR ENDEC block | X | - | - |
LIN mode | X | - | - |
Dual clock domain and wakeup from Stop mode | X | - | - |
Receiver timeout interrupt | X | - | - |
Modbus communication | X | - | - |
Auto baud rate detection | X | - | - |
Driver Enable | X | X | X |
Where: X mean supported.
I kept the pc baudrate in 38400; but move the sensor1 to USART1 and sensor2 to USART3 (by factory the USART2 is the PC, could be change moving some jumpers in the board); keep using BufferedSerial and everything work fine :) . Also modify the wait_ms - this to gave time for the buffer to be polled, not so sure... but this allow that the entery 82 bytes recived get in a single char array.
The new code is this one:
include the mbed library with this snippet
#include "mbed.h" #include "BufferedSerial.h" // all these are optional const int BUFF_SIZE = 64; const int TX_MULTIP = 8; const char* SEN1 = "S1"; const char* SEN2 = "S2"; Serial pc(USBTX, USBRX); // USART2 BufferedSerial fuelR1(PA_9, PA_10, BUFF_SIZE, TX_MULTIP, SEN2); // USART1 BufferedSerial fuelR2(PB_10, PB_11, BUFF_SIZE, TX_MULTIP, SEN2); // USART3 DigitalOut myled(LED1); int main() { pc.baud(38400); fuelR1.baud(19200); fuelR2.baud(19200); while(1) { if (fuelR1.readable()) { wait_ms(10); pc.printf("SENSOR1: "); while(fuelR1.readable()) { char incoming = fuelR1.getc(); pc.putc(incoming); } pc.printf("\r\n"); } if (fuelR2.readable()) { wait_ms(10); pc.printf("SENSOR2: "); while(fuelR2.readable()) { char incoming = fuelR2.getc(); pc.putc(incoming); } pc.printf("\r\n"); } myled = !myled; wait_ms(10); } }
At my point of view (read: guessing), the Issue could be that the USART4, 5, 6, 7, 8 does not support Timeout Interrupt. It would be great to have another point of view to confirm.
Best regards.
posted by 01 Jun 2016