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 STM32F407G Discovery Board micro-controller to RasperryPi 3 Model B running Ubuntu.
I was able to send data using STM32F407G Discovery Board "C" libraries & display that output on TeraTerm & Putty apps on Windows via serial-usb interface wire.
My goal is to create my own simple serial port reader/writer program that displays the UART character data thaw which will come from 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 snap of configured serial port values & correct output:
So far all is as expected & good.
I have confirmed the STM32F407G board, MPU sensors are integrated, and transmission code on STM32F407G is correct, as expected output is displayed.
I would like to create my own custom serial receiver on RasperryPi (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:
- I disconnected the usb-serial that was sending data to TeraTerm on Windows and connect my STM32F407G Discovery Board UART to RasperryPi UART pins, like this:
STM UART RX (PA3) to Rasperry UART TX (GPIO 14 PIN 8) STM UART TX (PA2) to Rasperry UART RX (GPIO 15 PIN 10)
UART Receive code on RasperryPi side (Im made sure my buadrate, parity bit, etc are 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 RasperryPi, 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 cant display the characters correctly but data is being sent to /dev/ttyS0.
Troubleshooting:
For sanity check, to see if that was actually coming from STM32F407G, I physically disconnect TX (line from STM32F407G) to RX in RasperryPi, data stops flowing & stops printing on console.
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.
- I though this might have to do with endianess, 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 RasperryPi 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 endianess.
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 RasperryPi to display the incoming UART characters properly?
PARTIAL-SOLUTION: Based on user input I tried UART from my original Pi board to actual PC & also UART loop, I was not able to get output. At this point I suspect the board, therefore I switched my board with another Pi 3 Model version B. After instaling minicom & disabking shell over UART. I can see meaningful 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);
}
Im getting 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 apprecaite the community support.