Unstable behavior of serial communication for Nucleo L476RG

I have created a Python sketch to try and upload the current NTP time to STM32L476RG Nucleo. The sketch is as follows:

import serial
import glob
import sys
import time
from socket import AF_INET, SOCK_DGRAM
import socket
import struct
def serial_ports():
    """ Lists serial port names

    :raises EnvironmentError:
        On unsupported or unknown platforms
    :returns:
        A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
    ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
    # this excludes your current terminal "/dev/tty"
    ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
    ports = glob.glob('/dev/tty.*')
else:
    raise EnvironmentError('Unsupported platform')

result = []
for port in ports:
    try:
        s = serial.Serial(port)
        s.close()
        result.append(port)
    except (OSError, serial.SerialException):
        print("OSError or Serial Exception raised, exiting...")
        pass
return result



def getNTPTime(host = "pool.ntp.org"):
        port = 123
        buf = 1024
        address = (host,port)
        msg = '\x1b' + 47 * '\0'
 
        # reference time (in seconds since 1900-01-01 00:00:00)
        TIME1970 = 2208988800 # 1970-01-01 00:00:00
 
        # connect to server
        client = socket.socket( AF_INET, SOCK_DGRAM)
        while True:
            try:
                client.sendto(msg.encode('utf-8'), address)
                msg, address = client.recvfrom( buf )
 
                t = struct.unpack( "!12I", msg )[10]
                t -= TIME1970
                return t
            except (socket.gaierror):
                print("Error! Internet connection not found, exiting...")
                break

my_t_zone = -8
cur_ser = ''.join([s for s in serial_ports() if 'usbmodem' in s])
if(len(cur_ser)>0):
    ser = serial.Serial(cur_ser)
    if(not ser.isOpen()):
        ser.open()
    valid = 0
    time.sleep(.5)
    while(not valid):
        ser.reset_input_buffer()
        line = ser.readline().decode('utf-8').strip()
        if(line=="Hello"):
            ntp_time = ("DEA"+str(getNTPTime()+(my_t_zone*3600))+"L").encode('utf_8') 
            ser.write(ntp_time)
            valid = 1
    time.sleep(.5)
    print("Done uploading time.")
    ser.close()  
else:
    print("No compatible serial device found, exiting...")

The Mbed code is as follows:

#include "mbed.h"

Serial   pc(USBTX, USBRX);

const int kMaxBufferSize = 100;
char      buffer[kMaxBufferSize];
int       len = 0;
int contact = 1;

void removeChar(char *s, int c){ 
  
    int j, n = strlen(s); 
    for (int i=j=0; i<n; i++) 
       if (s[i] != c) 
          s[j++] = s[i]; 
      
    s[j] = '\0'; 
}

int main()
{
    pc.baud(9600);
    while(contact) {
        pc.printf("Hello\n");
        if (pc.readable() > 0) {
            char new_char;
            while(new_char != 'L') {
                new_char = pc.getc();
                buffer[len++] = new_char;
            }
        contact = 0;
        }
    }
    removeChar(buffer, 'D');
    removeChar(buffer, 'E');
    removeChar(buffer, 'A');
    removeChar(buffer, 'L');
    int x = atoi(buffer);
    while(!contact) {
        pc.printf("%s\n",buffer);
    }

}

The behavior of the system is unstable. I observe several things:

  • Around 60% of the time this code snippet works fine and Mbed shows the uploaded Posix timestamp properly after parsing.
  • Sometimes erroneous characters are shown in the parsed timestamp (e.g. symbols and other characters)
  • Sometimes the entire posix timestamp is not shown by Mbed and gets cut out.
  • Also, you can see the Python code uploads three characters before the timestamp. These are used to make sure the code works the 60% of the time (i.e. without them first two digits of timestamps get cut out most of the time).

Can anyone explain what’s wrong? Seems like a sync issue.

Hello,

I not tried your python code and also I not have same board. I use Nucleo-L432KC and MbedOS 5.15.5.
But when I tried your Mbed code then was my terminal apliaction overloaded with spam of “Hello” strings.
After commented out this, then I it was working 10-15 attempts with test “DEA123456789L” .

BR, Jan

Hi.

Initially it will overload Hello strings until you press a key on keyboard through terminal (and of course send it) or mbed detects write request. That’s ok behavior. Think of it as a request for write from terminal or python. You shouldn’t comment it out.

Also, it will work with test strings, but the problem is it is inconsistent. Sometimes it shows the entire string, sometimes it cuts out part of the string, sometimes random characters are injected.

Hello,

I think I understand how it works but my point was about that practise is wrong. If you need a feed back about the board is running then use a LED. If you want to debug it then use the printf but call it on a safe place.
The printf is very slow function and its usage on bad place can lead to problems. For example you can lose some data.

As a demonstration how slow it is, you can put a timer and a counter to your while loop and print out the result together with the final string.

Serial output with printf("Hello\n") in loop:

  • Hello
    HelDEA123456789Llo
    Hello
    3456789
    loops: 161 /1013ms
  • Hello
    HellDEA123456789Lo
    Hello
    23456789
    loops: 103 /651ms
  • Hello
    HeDEA123456789Lllo
    Hello
    456789
    loops: 146 /917ms

Serial output with printf("Hello\n") before loop (one time):

  • Hello
    DEA123456789L123456789
    loops: 483736 /701ms
  • Hello
    DEA123456789L123456789
    loops: 812118 /1169ms
  • Hello
    DEA123456789L123456789
    loops: 434693 /631ms

BR, Jan