4
\$\begingroup\$

Solved. The problem was a bad board & then appending extra "\n" in the output after reading from via "C".


I'm trying to send data via UART from the STM32F407G Discovery Board microcontroller to the Raspberry Pi 3 Model B running Ubuntu.

I was able to send data using the STM32F407G Discovery Board "C" libraries and display the output on the TeraTerm and Putty apps on Windows via a serial-USB interface wire.

My goal is to create my own simple serial port reader/writer program that displays the UART character data that will come from the STM32F407G..

Below is the relevant snippet of the transmission code on the STM32F407G side:

void print_mpu_values_to_uart(mpu6050_device *dev, UART_HandleTypeDef* huart, long print_delay_millisecs) {
 if (NULL != dev) {
 char str[120];
 char *pStr = str;
 clear_uart_message(pStr, sizeof(str));
 /* Format data */
 sprintf(str,
 "dev=%.2X,Ax=%2.4f,Ay=%2.4f,Az=%2.4f,Gx=%2.4f,Gy=%2.4f,Gz=%2.4f\r\n",
 dev->address, dev->pMpu_6050_data.Ax, dev->pMpu_6050_data.Ay,
 dev->pMpu_6050_data.Az, dev->pMpu_6050_data.Gx,
 dev->pMpu_6050_data.Gy, dev->pMpu_6050_data.Gz);
 //send label
 HAL_UART_Transmit(huart, (uint8_t*) str, sizeof(str), 1000);
 HAL_Delay(print_delay_millisecs);
 }
}

I connected STM32F407G Discovery Board via Serial-USB wire & configured TeraTerm to listen to com port (COM9):

See a snapshot of configured serial port values & correct output:

Serial port configuration

So far all is as expected & good.

I have confirmed the STM32F407G board, and MPU sensors are integrated, and the transmission code on STM32F407G is correct, as the expected output is displayed.

I would like to create my own custom serial receiver on Raspberry Pi (other Linux-embedded boards) to further process my data.

Based on these online resources:

https://www.cmrr.umn.edu/~strupp/serial.html http://www.ing.iac.es/~docs/external/serial/serial.pdf https://www.raspberrypi.org/documentation/configuration/uart.md

These are my steps:

  1. I disconnected the USB serial that was sending data to TeraTerm on Windows and connected my STM32F407G Discovery Board UART to Raspberry Pi UART pins, like this:

STM UART RX (PA3) to Raspberry Pi UART TX (GPIO 14 PIN 8) STM UART TX (PA2) to Raspberry Pi UART RX (GPIO 15 PIN 10)

  1. UART Receive code on the Raspberry Pi side (I made sure my baud rate, parity bit, etc are the same as TeraTerm settings):
#include <iostream>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
using namespace std;
int open_port(char * port);
void read_port(int file_descriptor, int buffer_size);
struct termios SerialPortOptions;
int main() {
 char * port = "/dev/ttyS0";
 std::cout << "Serial comm..." << port << std::endl;
 /*this program must executed via SUDO*/
 int fd = open_port(port);
 if (fd!=-1) {
 std::cout << port << ", Opened successfully " << std::endl;
 /*
 * Set the baud rates to 115200...
 */
 cfsetispeed( & SerialPortOptions, B115200);
 cfsetospeed( & SerialPortOptions, B115200);
 /*
 *Turn off hardware based flow control (RTS/CTS).
 */
 SerialPortOptions.c_cflag &= ~CRTSCTS;
 /*
 * Enable the receiver and set local mode...
 */
 SerialPortOptions.c_cflag |= (CLOCAL | CREAD);
 /*For Serial communications with outside devices like serial modems,mice etc NON Cannonical mode is recommended.*/
 SerialPortOptions.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
 /*setting character size bits*/
 SerialPortOptions.c_cflag &= ~CSIZE; /* Mask the character size bits */
 SerialPortOptions.c_cflag |= CS8; /* Select 8 data bits */
 /* No parity*/
 SerialPortOptions.c_cflag &= ~PARENB;
 SerialPortOptions.c_cflag &= ~CSTOPB;
 SerialPortOptions.c_cflag &= ~CSIZE;
 SerialPortOptions.c_cflag |= CS8;
 tcsetattr(fd, TCSANOW, & SerialPortOptions);
 //read from serial port
 read_port(fd, 128);
 close(fd);
 }
 return 0;
}
 
/*References: http://www.ing.iac.es/~docs/external/serial/serial.pdf
* Page 8-10*/
int open_port(char * port) {
 int fd; /* File descriptor for the port */
 /*
 * O_RDWR - read write mode
 * O_NOCTTY - this program doesn't want to be the "controlling terminal" for that port
 * O_NDELAY - this program doesn't care what state the DCD signal line is in − whether
 * the other end of the port is up and running.
 */
 fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
 cout << "open_port(),fd:" << fd<< endl;
 if (fd == -1) {
 /*
 * Could not open the port.
 */
 perror("open_port: Unable to open ");
 perror(port);
 } else {
 fcntl(fd, F_SETFL, 0);
 }
 return fd;
}
void read_port(int file_descriptor, int buffer_size) {
 char serial_buffer[buffer_size];
 //cout << "read_port(),file_descriptor:" << file_descriptor << endl;
 int total_read= 0;
 int r=0;
 while (true) {
 r = read(file_descriptor, serial_buffer, sizeof(serial_buffer));
 if (r>0) {
 total_read = total_read + r;
 }
 if (total_read >= buffer_size) {
 serial_buffer[buffer_size] = '0円';
 printf("%s\n", serial_buffer);
 fflush(stdout);
 cout << "total_read:" << total_read << endl;
 total_read = 0;
 }
 }
}

Ubuntu on Raspberry Pi, console output snippet:

Serial comm.../dev/ttyS0
open_port(),fd:3
/dev/ttyS0, Opened successfully 
W��k
total_read:128
��k
total_read:128
Y��k
total_read:128
��k
total_read:128
total_read:128
7��k
total_read:128
��k
total_read:128

As you can see I can't display the characters correctly but data is being sent to /dev/ttyS0.

Troubleshooting:

  1. For sanity check, to see if that was actually coming from STM32F407G, I physically disconnected TX (line from STM32F407G) to RX in Raspberry Pi, and data stopped flowing & stopped printing on the console.

  2. For further sanity check, I also tried "minicom" on Ubuntu's shell:

sudo minicom -D "/dev/ttyS0" -b 115200

Minicom output:

CTRL-A Z for help | 115200 8N1 | NOR | Minicom 2.7.1 | VT102 | Offline | ttyS0
5...Y{‚A‚A‚A‚A‚ˆžaÊBœ"WWñö‹]ÁIÈœ"7WšÔä†Q2"UgÛV5F[uIœ"wSË€@‚A‚‚Aþˆžaœ"YM÷‹\ÁÅYÈ5...Qêœ"7[ì†S*ŠZZŸQ:"[

As you can see Minicom also gets data its not formatted correctly & garbage.

  1. I thought this might have to do with endianness, the STM32 has ARM Cortex M4 which according to the document (PM0214 Programming manual STM32 Cortex®-M4 MCUs and MPUs programming manual) is by default little-endian, also running the command "lscpu" on the Raspberry Pi 3 model B, shows the Cortex-A53 which is also Little Endian based (https://en.wikipedia.org/wiki/ARM_architecture#64/32-bit_architecture), so I highly doubt the issue is endianness.

Based on user comments I tried different baud rates here are the results:

BAUDRATE: OUTPUT TERMINAL & ENVIRONMENT: RESULT:
115,200 TeraTerm/Putty (Windows) Good (can see correct data)
115,200 C Program (Linux Ubuntu of Pi) Garbage & Bad format
57,600 TeraTerm/Putty (Windows) Good (can see correct data)
57,600 C Program (Linux Ubuntu of Pi) Garbage & Bad format
38,400 TeraTerm/Putty (Windows) Good (can see correct data)
38,400 C Program (Linux Ubuntu of Pi) Garbage & Bad format
19200 TeraTerm/Putty (Windows) Good (can see correct data)
19200 C Program (Linux Ubuntu of Pi) Garbage & Bad format & also stops after few lines
14400 TeraTerm/Putty (Windows) Good (can see correct data) 
14400 C Program (Linux Ubuntu of Pi) Not supported & constant not present in termios.h 
9600 TeraTerm/Putty (Windows) Good (can see correct data) 
9600 C Program (Linux Ubuntu of Pi) Garbage & Bad format
4800 TeraTerm/Putty (Windows) Good (can see correct data) 
4800 C Program (Linux Ubuntu of Pi) Garbage & Bad format

Another attempt:, i changed the OS to Raspian & followed this blog (https://www.circuits.dk/setup-raspberry-pi-3-gpio-uart/). I wrote this small Python script:

import serial
serialport = serial.Serial("/dev/ttyS0", baudrate=4800, timeout=3.0)
while True:
 rcv = port.read(120)
 print(rcv)

Still getting garbage output!

How can I alter my C code on the Raspberry Pi to display the incoming UART characters properly?

PARTIAL-SOLUTION: Based on user input I tried UART from my original Pi board to the actual PC & also UART loop, but I was not able to get output. At this point I suspected the board, therefore I switched my board with another Pi 3 Model version B. After installing the minicom & disabling the shell over UART. I can see meaningful minicom output:

minicom output

I wrote a simpler version of C program above:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
int main(int argc, char* argv[]) {
 struct termios serial;
 char buffer[120];
 if (argc == 1) {
 printf("Usage: %s [device]\n\n", argv[0]);
 return -1;
 }
 printf("Opening %s\n", argv[1]);
 int fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
 if (fd == -1) {
 perror(argv[1]);
 return -1;
 }
 if (tcgetattr(fd, &serial) < 0) {
 perror("Getting configuration");
 return -1;
 }
 // Set up Serial Configuration
 serial.c_iflag = 0;
 serial.c_oflag = 0;
 serial.c_lflag = 0;
 serial.c_cflag = 0;
 serial.c_cc[VMIN] = 0;
 serial.c_cc[VTIME] = 0;
 serial.c_cflag = B115200 | CS8 | CREAD;
 tcsetattr(fd, TCSANOW, &serial); // Apply configuration
 int flag =0;
 int read_count = 0; 
 while (flag!=-1)
 {
 int rcount = read(fd, buffer, sizeof(buffer));
 if (rcount < 0) {
 perror("Read");
 flag= -1;
 break;
 }
 else if (rcount>0)
 {
 //printf("Received %d characters\n", rcount);
 buffer[rcount] = '0円';
 printf("%s", buffer);
 }
 else {
 //read nothing, do nothing.
 } 
 }
 close(fd);
}

I'm getting the expected output:

dev=D2,Ax=-0.9922,Ay=0.0566,Az=0.8118,Gx=-0.2672,Gy=-1.0611,Gz=0.7634
dev=D0,Ax=-0.0664,Ay=0.0955,Az=0.8772,Gx=-0.6947,Gy=-0.9924,Gz=-1.4351
dev=D2,Ax=-0.9958,Ay=0.0535,Az=0.8113,Gx=-0.2824,Gy=-1.0687,Gz=0.7328
dev=D0,Ax=-0.0664,Ay=0.0962,Az=0.8818,Gx=-0.4656,Gy=-0.8397,Gz=-1.5420
dev=D2,Ax=-0.9961,Ay=0.0554,Az=0.8169,Gx=0.0305,Gy=-0.9771,Gz=0.6870
dev=D0,Ax=-0.0566,Ay=0.0999,Az=0.8813,Gx=-0.4809,Gy=-0.9466,Gz=-1.7023
dev=D2,Ax=-0.9858,Ay=0.0571,Az=0.8225,Gx=-0.3359,Gy=-0.9084,Gz=0.7023
dev=D0,Ax=-0.0657,Ay=0.0896,Az=0.8850,Gx=-0.7939,Gy=-1.0916,Gz=-1.5191
dev=D2,Ax=-0.9956,Ay=0.0623,Az=0.8191,Gx=-0.1756,Gy=-0.9542,Gz=0.8626
dev=D0,Ax=-0.0632,Ay=0.1025,Az=0.8782,Gx=-0.9008,Gy=-1.0076,Gz=-1.3893
dev=D2,Ax=-0.9985,Ay=0.0576,Az=0.8252,Gx=-0.1221,Gy=-0.7252,Gz=0.8702

Solved. The problem was a bad board & then appending extra "\n" in the output after reading from via "C".

Really appreciate the community support.

Velvet
4,9085 gold badges18 silver badges32 bronze badges
asked Feb 13, 2021 at 1:35
\$\endgroup\$
22
  • \$\begingroup\$ might be an encoding issue \$\endgroup\$ Commented Feb 13, 2021 at 1:44
  • \$\begingroup\$ @EdwinFairchild, please be kind enough to expand? How does TeraTerm or Putty automatically convert & display? Im sending over characters and not raw bytes. \$\endgroup\$ Commented Feb 13, 2021 at 1:48
  • \$\begingroup\$ Maybe the clocks of the two devices are too imprecise relative to each other. Try a slower baud rate and if that works then you may need more precise clock sources. \$\endgroup\$ Commented Feb 13, 2021 at 2:35
  • 1
    \$\begingroup\$ Not sure this line is correct: "HAL_UART_Transmit(huart, (uint8_t*) str, sizeof(str), 1000);" sizeof(str) will always be the length of the array. I think you would be better of using strlen(str) instead of sizeof(str). Also you would be better off using snprintf() instead of sprintf(). Just to make sure you don't overrun your buffer. \$\endgroup\$ Commented Feb 13, 2021 at 4:28
  • 1
    \$\begingroup\$ Hi. Have you tried the script for the loopback test at the end of the blog? you should connect a wire from RX to TX on the RPi and test that script or minicom. If you still get garbage on the loopback test I don't know what to tell you other than changing the power supply on the Pi for another one less noisy and/or more powerful. If that does not work either then I think you might need a new board. But I would be very surprised to see a serial port go bad like that, I've tested and tortured many boards; sometimes some things really break down completely... Do you have a spare board to try? \$\endgroup\$ Commented Apr 3, 2021 at 7:13

1 Answer 1

1
\$\begingroup\$

This should work (I did this on the RP4 just 2 days ago at the same baudrate and an STM32F405 and it worked fine after a 'gotcha') these are some things to check:

  1. Make sure you have a ground between boards (TX and RX is not enough)

  2. Check the TX voltage level of the output (with an oscilloscope or logic analyzer) and make sure it's 3.3V for the Pi (which it should be coming from the STM32F407G, but you never know sometimes ports get blown out.

  3. Check the clock rate on the STM32F, I don't have my code with me but I do know there was a problem with one of the clocks that generated the baud rate wrong (there was a multiplier somewhere in the HAL code that was supposed to be 8Mhz higher and was generating an incorrect baud rate (the baud rate was 8x lower, if I remember right). (this is also why it's good to check the baud rate with a scope or logic analyzer). I'll find the error when I get a chance and update.

Also Minicom is not a good way to check sometimes because it will auto adjust the baud rate, whatever COM program you use, make sure you force the baud rate to a fixed known value.

answered Apr 5, 2021 at 20:25
\$\endgroup\$
3
  • \$\begingroup\$ appreciate the input all the things you mentioned I had already tried in the original post. I have already posted the solution. The problem as 1) faulty Pi UART 2) small bug in the C's console print logic. \$\endgroup\$ Commented Apr 6, 2021 at 3:07
  • \$\begingroup\$ 1) The definitive answer was MarcosG's loopback test that identified a faulty UART on my Pi. When Swiped my Pi with another Pi everything worked. Another smaller issue was extra "\n" in C's console output. However, I still appreciate the wisdom. Any thoughts on how STM to Pi communication over UART may go wrong in the production system (mission-critical) application? Strictly focusing on the UART aspect. \$\endgroup\$ Commented Apr 6, 2021 at 3:13
  • \$\begingroup\$ minicom...will auto adjust the baud rate...; are you sure you are not confusing it with something else? The one I have does not have any auto baud rate detection. \$\endgroup\$ Commented Apr 11, 2021 at 6:48

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.