Introduction: Web Connected Digital Clock
Found a $10 digital clock at Amazon. Now to customize it to get the time from the internet.
Supplies
ARM Stamp programmable in BASIC available here
Step 1: Connect Digit Drive and Segment Drive for Multiplexed Display
I started with a cheap off the shelf big number digital clock. First I removed the existing clock chip. Then did some probing around and located the 7 segment connections, which can be driven directly by the microprocessor. Then found the 4 digit drivers which were transistors which the microprocessor can drive. And then wired those up.
Step 2: Test the Connections
As an experiment I wrote a BASIC program to drive all the lines, to check the wiring and measure the current, which in this case was 82 mA
Next was to write the code to scan the lines.
' web clock display drive
IO(7)=0 ' PMOS drive -- will be PWM someday
for y=45 to 48
IO(y)=0 ' digit drive
for x=8 to 15
IO(x)=0 ' segment drive
wait(500)
IO(x)=1
next x
DIR(y)=0 ' disable drive on segment
next y
Step 3: Code to Display Time and PWM to Control Brightness
Next I added a PMOS transistor in the power supply to all the digit drivers. With that driven by pulse width modulation will control the brightness of the display. Here is the BASIC code to display the time.
' web clock display drive
#include "LPC11U3x.bas"
' globals
hr = 0 ' define hour
min = 0 ' define minute
#define SEG_0 &HBB00
#define SEG_1 &H1800
#define SEG_2 &HD300
#define SEG_3 &HD900
#define SEG_4 &H7800
#define SEG_5 &HE900
#define SEG_6 &HEB00
#define SEG_7 &H9800
#define SEG_8 &HFB00
#define SEG_9 &HF800
#define SEG_o &H4B00
#define SEG_f &HE200
const DIGarray = { SEG_0, SEG_1, SEG_2, SEG_3, SEG_4, SEG_5, SEG_6, SEG_7, SEG_8, SEG_9, SEG_o, SEG_f }
#define DIG_WAIT 1
#define US_TIME
sub display_time(err, hr, min)
dim hr10, hr1, min10, min1, i
#ifdef US_TIME
if hr > 12 then hr -= 12
if hr = 0 then hr = 12
#endif
hr10 = hr / 10
hr1 = hr MOD 10
min10 = min / 10
min1 = min MOD 10
for i=0 to 1
if hr10 then
IO(45) = 0
endif
GPIO_DIR(0) = (GPIO_DIR(0) & &HFFFF00FF) + DIGarray(hr10)
GPIO_CLR(0) = DIGarray(hr10)
wait(DIG_WAIT)
INPUT(45)
IO(46) = 0
GPIO_DIR(0) = (GPIO_DIR(0) & &HFFFF00FF) + DIGarray(hr1) + IF(i , &H400 , 0)
GPIO_CLR(0) = DIGarray(hr1) + IF(i , &H400 , 0)
wait(DIG_WAIT)
INPUT(46)
IO(47) = 0
GPIO_DIR(0) = (GPIO_DIR(0) & &HFFFF00FF) + DIGarray(min10)
GPIO_CLR(0) = DIGarray(min10)
wait(DIG_WAIT)
INPUT(47)
IO(48) = 0
GPIO_DIR(0) = (GPIO_DIR(0) & &HFFFF00FF) + DIGarray(min1)
GPIO_CLR(0) = DIGarray(min1)
wait(DIG_WAIT)
INPUT(48)
next i
endsub
' user TIMER1 (32 bit) to interrupt each minute
INTERRUPT SUB TIMER1IRQ
T1_IR = 1 ' Clear interrupt
min += 1
if min > 59 then
min = 0
hr += 1
if hr > 23 then
hr = 0
endif
endif
ENDSUB
SUB ON_TIMER ( max_cnt, dothis )
TIMER1_ISR = dothis + 1 'set function of VIC -- need the +1 for Thumb operation
SYSCON_SYSAHBCLKCTRL OR= (1<<10) ' enable TIMER1
T1_PR = 0 'no prescale -- will adjust the value for more accurate time
VICIntEnable OR= (1<<TIMER1_IRQn) 'Enable interrupt
T1_MR0 = max_cnt-1 ' set up match number of ms
T1_MCR = 3 ' Interrupt and Reset on
MR0 T1_IR = 1 ' clear interrupt
T1_TC = 0 ' clear timer counter
T1_TCR = 1 ' TIMER1 Enable
ENDSUB
#define MINUT_PCLK 2880000000 ' 60 seconds at 48 MHz
main:
hr = 9
min = 33
ON_TIMER(MINUT_PCLK , ADDRESSOF TIMER1IRQ)
IO(7) = 0 ' PWM some day -- need to move to P0_22 ??
while 1
display_time(0, hr, min)
loop
Step 4: Make an Internet Connection
Use an ESP8266 for a WiFi connection. After poking around the web for a while the best solution was nodemcu version 0.9.6 and an older esp8266_flasher worked the best.
https://www.electrodragon.com/w/File:Nodemcu_20150704_firmware.zip
Then a simple PHP webpage to serve time from the internet--
<!DOCTYPE html>
<html lang=en>
<head>
<title>Coridium Time Server</title>
</head>
<body>
<?php
$timezone = htmlspecialchars($_GET["zone"]);
if ( $timezone == "")
$timezone = 'America/Los_Angeles';
$tz_object = new DateTimeZone($timezone);
$datetime = new DateTime();
$datetime->setTimezone($tz_object);
echo "time is-",$datetime->format('H:i:s');
echo "<br>";
echo "date is-",$datetime->format('m/d/Y');
?>
</body>
</html>
That webpage is so you can request
coridium.us/time.php -- and you well get US Pacific time zone
or
coridium.us/time.php?zone=Europe/London
No error checking and most likely never will be
And the Lua to read that --
> wifi.sta.config("your_SSID","your_PASSWORD")
> wifi.sta.connect() ...
> sk=net.createConnection(net.TCP, 0)
> sk:on("receive", function(sck, c) print(c) end )
>sk:connect(80,"coridium.us")
>sk:send("GET /time.php HTTP/1.1\r\nHost: coridium.us\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
And you get back time as
time is-09:38:49
date is-12/31/2018
Step 5: Add BASIC Code to Parse the Time From the Web
This is a subset of the full BASIC program, that full program can be viewed at the link in the final step.
if strstr(build_gets, "time is-") = 0 then
hr = build_gets(8) - "0"
if build_gets(9) = ":" then
min = (build_gets(10) - "0")*10
min += build_gets(11) - "0"
else
hr = hr * 10 + build_gets(9) - "0"
min = (build_gets(11) - "0")*10
min += build_gets(12) - "0"
endif
endif
Step 6: Add a Light Sensor and Code to Dim the Display
A photo transistor was added to sense the ambient light in the room. Without it the display is bright enough to wake the dead (me) at night.
The analog voltage of the output of the photo transistor is read and the pulse width modulation sets the overall brightness of the display.
Step 7: Button Up the Clock and Start Using It.
The final version displays the time, and at around 3 AM it goes out to the web to read the current time. This also handles day light saving time.
The motivation for this project was the power failures we experience here in the mountains and the need to reset clocks or replace batteries to keep them alive.
This has been a quick overview of the project.