2

I have created a Python 3 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 sketch running on the Nucleo board 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:

  • Most 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 most of the time (i.e. without them first two digits of timestamps get cut out most of the time).

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

Swapnil Saha
  • 61
  • 1
  • 8
  • 1
    how fast are you running the chip, unlikely at 9600 but it could be the baud rate accuracy do to clock rate and divisor has too much margin relative to that on the other side and it may just be a corruption of the serial interface.. if you simply make a program/sketch that runs at 9600 and all it does is blast characters (vary the data of course) are they clean all the time? do power cycles result in corrupt data? If always clean then it is not this problem (it is unlikely the uart divisor but should always check when you start to see corruption). – old_timer Nov 19 '20 at 10:20
  • I agree with you. I think instead of blasting with several characters at once, I should send the chars one by one. The problem actually disappears when I input the string through keyboard presses (which is obv. much slower than the python script, which sends everything at once without error checking). – Swapnil Saha Nov 19 '20 at 21:01

0 Answers0