Arduino UNIX Time - Syncing Computer UNIX Time to Arduino Time with Python


 
Thread Tools Search this Thread
Top Forums Programming Arduino UNIX Time - Syncing Computer UNIX Time to Arduino Time with Python
# 1  
Old 12-23-2019
Arduino UNIX Time - Syncing Computer UNIX Time to Arduino Time with Python

Just finished a quick Python script to send the current unix time over to the Arduino from macOS, so in the absence of GPS or some other way to get the unix timestamp (epoch time) to the Arduino, I can get my macOS and Arduino UNO synced to within a second.

Normally, when the Arduino starts up, Arduino run time starts at 0; so I created a Python script, which I will share in a future post (as well as the Arduino sketch), to send the macOS unix time over to the Arduino.

Arduino UNIX Time - Syncing Computer UNIX Time to Arduino Time with Python-img_8719jpg
This User Gave Thanks to Neo For This Post:
# 2  
Old 12-24-2019
Here is a quick sketch I put together for the Arduino UNO to get the unix time from the usb serial port and sync the Arduino time to the computer (in my case macos).

This sketch works but needs more refinement (trap errors, disconnects, add options, etc) but since I will not be doing much with this for the next few weeks, I post the first working draft below and will also post the python script I use on macos soon:

Code:
/*
  Sync UNIX Time with Computer and
  LCD Display with I2C on Arduino UN0
  Rough Draft 0.1  (needs improvements)
  Neo December 2019
  https://www.unix.com
*/

// Include Wire Library for I2C
#include <Wire.h>
// Include NewLiquidCrystal Library for I2C
#include <LiquidCrystal_I2C.h>
#include <Time.h>
#include <TimeLib.h>

#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by Unix time_t as ten ASCII digits
#define TIME_HEADER 'T' // Header tag for serial time sync message
#define TIME_REQUEST 7  // ASCII bell character requests a time sync message
#define DEBUG_SKETCH false
// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;
// can be any integer greater than zero and less than recent unix time
const int time_int = 1000;
// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;
String s;
bool flag = true;
time_t t = now();
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);
void setup()
{
    Serial.begin(9600);
    Wire.begin();
    time_t t = now();
    lcd.begin(16, 2);
    lcd.clear();
}

void loop()
{
    lcd.clear();
    int count = 0;
    if (Serial.available() and flag)
    {
        lcd.clear();
        lcd.setCursor(0, 1);
        lcd.print("Serial OK");
        count = processSyncMessage();
        if (DEBUG_SKETCH)
        {
               Serial.println("Serial Available: " + count);
        }
        if (count > time_int)
            flag = false;
    }

    lcd.setCursor(0, 0);
    if (timeStatus() == timeNotSet)
    {
        if (flag)
        {
            Serial.println("waiting for sync message");
            lcd.print("Arduino Time:");
        }
    }
    else
    {

        lcd.print("Unix Time:");
        if (DEBUG_SKETCH)
        {
            Serial.println("Time Synced");
        }
    }
    t = now();
    s = String(t);
    if (s != '0')
    {
        lcd.setCursor(0, 1);
        lcd.print(t);
        lcd.print(" secs");
    }
    Serial.println(s);
    delay(1000);
    lcd.clear();
}

int processSyncMessage()
{
    while (Serial.available() >= TIME_MSG_LEN)
    { // time message consists of header & 10 ASCII digits
        char c = Serial.read();
        int count = 0;
        Serial.print(c);
        time_t pctime = 0;
        if (c == TIME_HEADER)
        {
            for (int i = 0; i < TIME_MSG_LEN - 1; i++)
            {
                c = Serial.read();
                if (c >= '0' && c <= '9')
                {
                    Serial.print(c);
                    count++;
                    pctime = (10 * pctime) + (c - '0'); // convert digits to a number
                }
            }
            Serial.print("\n");
            if (DEBUG_SKETCH)
            {
                Serial.write(pctime + "\n");
                Serial.println(pctime);
            }
            setTime(pctime); // Sync Arduino clock to the time received on the serial port
        }
        return count;
    }
}

# 3  
Old 12-24-2019
Here is the Python 2.7.16 code I quickly put together to send unix time to the Arduino UNO.

I assume it also works on Python3, but I have not tested it because I have not completely upgrade python on my mac pro yet, sorry about that.

Code:
# -----------------------------------------------------------
# Sync Unix Time with Arduino Initial Draft 0.1
# Written on macOS, tested with Python 2.7.16
# Neo, December 2019
# This code needs refinement to be more general
# I will improve this code later when I need to use it in an Arduino project
# For now, it works "OK" and serves it purpose
# Feel free to improve, modify as you like.
# -----------------------------------------------------------
import serial
import time

ser = serial.Serial(
    port='/dev/cu.usbserial-40',  #change this for your device
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=0)

print("connected to: " + ser.portstr)

# this will store the line
line = []
ux = 0
a = False
debugScript = False
offset = 2 .  #adjust this time offset (in seconds) to account for various time delays in script and transferring via the serial port, etc. to insure the Arduino is in closer sync to the computer
time_int = 1000  # this can be any number greater than zero and less than recent unix time
count = 0
while True:
    if debugScript:
        print(str(int(time.time())))
    for c in ser.read():
        if not a:
            if ux < time_int:
                ser.write("T")
                ux = int(time.time())+offset
                ser.write(str(ux))
                ser.write("\n")
                ser.flush()
                if debugScript:
                    print("unixtime: " + str(ux))
        line.append(c)
        count += 1
        if c == '\n':
            print("Line("+str(count)+"): " + ''.join(line))
            x = int(time.time())+offset
            print("time("+str(count)+"): " + str(x) + "\n")
            line = []
            a = True
            break
ser.close()

# 4  
Old 12-24-2019
Maybe I'll make a video and show this in more detail at some point in time (if I get the free time to make videos)

Arduino UNIX Time - Syncing Computer UNIX Time to Arduino Time with Python-img_8721jpg


When I revise this code, I'll add some feature to detect when the usb serial port is available and sync when detected, and I'll add more error checking, trapping code and some options.
# 5  
Old 12-24-2019
Detecting and automatic syncing was trivial to do with cron, crude and rude but it works (but it can be slow, based on the 1 minute cron):

Code:
macos# crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.6hwbckCLEy installed on Tue Dec 24 14:09:49 2019)
# (Cron version -- $FreeBSD: src/usr.sbin/cron/crontab/crontab.c,v 1.24 2006/09/03 17:52:19 ru Exp $)
* * * * * /usr/bin/python /usr/local/bin/neo/checkArduino.py


Code:
macos# cat /usr/local/bin/neo/checkArduino.py
import os.path
from os import path

device = '/dev/cu.usbserial-40'
syncscript = '/usr/local/bin/neo/sync_unixtime.py'
if path.exists(device):
   execfile(syncscript)

The Arduino sketch will not sync after the unixtime is set the first time (in my current draft sketch above), so this will work OK for now.

I could set a PID or some flag in the filesystem to check if already synced, don't run the sync script again; but it's OK for now.

So I think this simple crontab is adequate for my current tests and experiments with the Arduino.

It even works when I press the reset button on the Arduino UNO, which is cool.
# 6  
Old 12-24-2019
Also, on macOS, I added this to launchd so it would sync the unix time with the Arduino UNO on startup:

Code:
macOS:LaunchDaemons# ls -l *neo*
-rw-r--r--  1 root  wheel  453 Dec 24 15:30 com.neo.startup.plist

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.neo.startup</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/bin/python</string>
                <string>/usr/local/bin/neo/checkArduino.py</string>
        </array>
        <key>StartInterval</key>
        <integer>1</integer>
</dict>
</plist>

Code:
macOS:LaunchDaemons# launchctl load -w /Library/LaunchDaemons/com.neo.startup.plist

Unfortunately, because this python script is not a "proper" macOS launch daemon, it will not "keep alive", so I still use cron for that. Maybe I'll find a way to fix this later. Maybe I need to move it to LaunchScripts versus LaunchDaemons? Anyway.... think I'll "call it good" on the unix time sync experiment for now... and as we all know....

It's only rock and roll, and I like it.
# 7  
Old 12-25-2019
As a side note:

I notice that when I use launchd and cron on my mac to keep an Arduino UNO in sync, that I cannot update the Arduino code though the IDE unless I unload the launchd file, stop the cron entry (actually, if fast do not need to modify cron) and power cycle the Arduino.

This takes more time than I like (unloading and loading launchd, editing and restarting cron twice, hard resetting the Arduino), so as a work around, I can update the Arduino on a different mac and then connect the updated Arduino back to the mac running launchd and cron on the required serial port. Note: If I'm fast, can get by not editing and restarting the crontab.

Today, I am experimenting with a 650nm (red) laser and was going to use this little laser to transmit and sync unix time to a remote receiver; but I don't have an optical receiver in my parts box yet.

I do have a long range RF transmitter and receiver in the mail from China, as well as a 3G module, so I maybe I'll transmit and sync unix time to my Ninja, for fun.

Actually, I need to think of some very cool, "science-project-like" Arduino project which is not already on YT or in the Arduino forums. I am thinking to do something with my motorcycle, time, position, and speed via 3G back to my home and store the results (tracking) in a database; but that sounds "too easy" Smilie (waiting on parts). Then I thought, I would create a RF network and transmit unix time as a beacon, but we have GPS for that. Haha....

Any crazy ideas (not already on YT)?
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Programming

Arduino-cli - Uploading to Unknown Chinese Arduino Boards using the Arduino Command Line Interface

In my further exploration of Arduino, today I decided to install the arduino-cli on my mac today. https://github.com/arduino/arduino-cli I followed the instructions for macOS but when I got to this part: arduino-cli board list I got the dreaded "Unknown" Fully Qualified Board Name... (1 Reply)
Discussion started by: Neo
1 Replies

2. Shell Programming and Scripting

Convert UTC time into current UNIX sever time zone

Hi guys thanks for the help for my previous posts.Now i have a requirement that i download a XMl file which has UTC time stamp.I need to convert UTC time into Unix server timezone. For ex if the time zone of unix server is CDT then i need to convert into CDT.whatever may be the system time... (5 Replies)
Discussion started by: mohanalakshmi
5 Replies

3. Shell Programming and Scripting

Adding time to date time in UNIX shell scipting

I needed some help in adding a duration (in seconds) to a start time (in hhmmss format) and a start date (in mmddyy format) in order to get an end date and end time. The concept of a leap year is also to be considered while incrementing the day. The code/ function that I have formed so far is as... (3 Replies)
Discussion started by: codehelp04
3 Replies

4. UNIX for Dummies Questions & Answers

Converting string date time to unix time in AWK

I'd like to convert a date string in the form of sun aug 19 09:03:10 EDT 2012, to unixtime timestamp using awk. I tried This is how each line of the file looks like, different date and time in this format Sun Aug 19 08:33:45 EDT 2012, user1(108.6.217.236) all: test on the 17th ... (2 Replies)
Discussion started by: bkkid
2 Replies

5. Shell Programming and Scripting

How to get time duration between two human readable time stamp in Unix?

Here is two time I have: Jul 12 16:02:01 Jul 13 01:02:01 and how can I do a simple match to get difference between two time which is 09:00:00 Thanks in advance. (3 Replies)
Discussion started by: ford99
3 Replies

6. Shell Programming and Scripting

Unix time

how do i convert unix time to show normal eg i have unix time 1297702242 and i want it converted to normal time. how do i do that (2 Replies)
Discussion started by: blackzinga80
2 Replies

7. Shell Programming and Scripting

Convert Unix Time to Standard Time

I have a list of interfaces and time the interface was last active. I can't figure out how to convert the time in the second column, Fa1/14 0 Se0/0/0 0 Fa1/11 0 Fa1/9 0 Fa1/0 0 Se0/0/1 1240401408 Gi1/0 0 Fa0/0 1240401408 Fa1/3 0 Fa1/8 0 Fa1/15 0 Fa1/13 0 Fa1/10 0 Fa1/1 0 Fa1/12... (7 Replies)
Discussion started by: mrlayance
7 Replies

8. UNIX for Advanced & Expert Users

How To Provide Time Sync Using Nts-150 Time Server On Unix Network?

can anybody tel lme,how to instal NTS -150 on a unix network,it needs some patch to fetch time frm serve,,?? (2 Replies)
Discussion started by: pesty
2 Replies

9. UNIX for Dummies Questions & Answers

Help me!First time use UNIX.

I am assigned a programming work.It is my first time to use unix. The task is writing a shell script to interrogate the university Unix operating system to determine the number of "Runnable" processes at any given time.Then append the result,along with a time-stamp,on a log file. Also there are... (1 Reply)
Discussion started by: zhshqzyc
1 Replies
Login or Register to Ask a Question