Python -> USB2TTL -> STM32 UART Serial Communication - Page 1
Forum section: electronics / general

author: AlwaysAbia
author_rank: Contributor
timestamp: September 05, 2024, 10:35:42 am
content: I am working on a project where I need to send serial data to an STM32F103 USART using a USB2TTL module.I want to be able to send numbers and have the stm32 parse the numbers and use them for a certain task. I've accomplished this by having the USARTx_IRQHandler parse the data it receives character by character and append the numbers to a buffer, which gets moved to a variable after the stm receives a delimiting character (In this case i chose 'a' as the delimiting character for no particular reason).Code:void USART3_IRQHandler(void){/* USER CODE BEGIN USART3_IRQn 0 *//* USER CODE END USART3_IRQn 0 */HAL_UART_IRQHandler(&huart3);/* USER CODE BEGIN USART3_IRQn 1 */if(RX_Char == 'a'){newLineCount++;if(newLineCount == 2){// Assign the buffered values to the setpointsbaseSetPoint = baseBuffer;tiltSetPoint = tiltBuffer;// Reset the buffersbaseBuffer = 0;tiltBuffer = 0;newLineCount = 0;}}else if(RX_Char >= '0' && RX_Char <= '9'){// Convert character to digitint currDigit = RX_Char - '0';if(newLineCount == 0) {// Update base bufferbaseBuffer = baseBuffer * 10 + currDigit;}else{// Update tilt buffertiltBuffer = tiltBuffer * 10 + currDigit;}}//Ignore other characters/* USER CODE END USART3_IRQn 1 */}Now here's the problem, this setup works perfectly when I connect to the STM32 using a Teraterm terminal, but when i send the serial data from a python script, it doesn't seem to work. It seems that the teraterm terminal is setup to follow each character with a CR (I am not quite sure about this, the setup tab has dropdown menus for transmit and receive, both of which have CR selected), so i tried following each character with '\r' in python, and also sending them with small delays because I thought maybe the stm32 didn't have enough time to register the character (Might've been a stretch given im running on 72Mhz but im new to this so im not sure).Code:ser = serial.Serial(port='COM12', # Replace with your actual COM portbaudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)dataString = "2000a400a"for char in dataString:ser.write((char + '\r').encode('utf-8'))time.sleep(0.01)these are the relevant lines of code.Question: How do I configure my python script to send the serial data that the stm32 can understand, just as it can understand it when I send it the data from my teraterm terminal, what am I doing wrong?Note: I can read the data coming from the STM32 in python just fine, it's only the sending that is the problem.Thanks in advance.

author: pcprogrammer
author_rank: Super Contributor
timestamp: September 05, 2024, 10:43:26 am
content: Please use the code button to separate the code lines from the post. It will make things better readable for us.

author: thephil
author_rank: Regular Contributor
timestamp: September 05, 2024, 01:49:30 pm
content: I had a look at your code:Code:dataString = "2000a400a"for char in dataString:ser.write((char + '\r').encode('utf-8'))time.sleep(0.01)A few guesses:Is there a reason, you are sending the data string char by char? I would have guessed you need to send the entire string at once and then add the\rat the end. But, of course that will depend on what the receiving side expects.The receiver may expect something else than\ras a line terminator – e.g.\nor\r\n. So you could play with that.Are you sure your device can handle utf-8? Most embedded things I have played with only supported ASCII. (although that would not matter for the specific string you provided.)Is the data supposed to be hexadecimal, by any chance? In that case you would have to convert to bytes and send that.EDIT:Ah - just realized you also control the receiver code (although I didn't read it thoroughly, yet). I think the easiest way would be to stick to a conventional\rinstead of the letter 'a' on both sides. Otherwise you need to deal with both the CR and the 'a' on the receiver side.

author: Nominal Animal
author_rank: Super Contributor
timestamp: September 05, 2024, 07:22:19 pm
content: I would recommend using patternser.write(b'2000a400a')ser.flush()i.e. usebytesand not strings, and to ensure the message is sent to the device and not buffered, do aflush()after each complete message or request. For example, to send a single (signed) integer followed by the'a'separator, I'd recommend usingser.write(b'%da' %value)ser.flush()(Because of poor quality implementation of Python serial libraries for POSIXy systems (namely, poor error checking and ubiquitous assumptions of "short writes and reads never occur"), I prefer to usetermiosinstead; but obviously,termiosisn't available on Windows.)

author: AlwaysAbia
author_rank: Contributor
timestamp: September 08, 2024, 12:04:59 pm
content: Code:dat = "abcabca"ser.write(dat.encode())ser.flush()I got it working, in the end I used the pattern above, although the main problem was on the STM32 side, the way I was trying to receive data was wrong, so I corrected it and then I moved to using DMA instead of interrupts.thanks to everyone who replied.