Den första versionen, som också finns på hemsidan, är inte speciellt bra. Den klockan använder endast ESP8266 interna RTC (Real Time Clock = Realtidsklocka på svenska). Eftersom den inte är så stabil så håller den inte tiden speciellt bra. Mitt eget ovetenskapliga test där klockan fick gå över natten gav ett fel på hela fem minuter. Oacceptabelt! Att hela tiden koppla upp sig mot en NTP-server (Network Time Protol) är ohyfsat och förbrukar en massa onödig bandbredd.

Lösningen är en mer exakt, extern RTC. Det finns i och för sig både bra och dåliga såna också. DS1307 t.ex. är mer exakt än ESP8266 interna RTC men ger ändå ett fel på flera minuter per år. En krets som är mycket bättre är en DS3231 som bara ger ett fel på några sekunder på ett år. Bra mycket bättre än fem minuter på åtta timmar. Det finns moduler att köpa för en dryg 20-lapp och det är billigt för att få en mer exakt klocka.

En annan fördel är att man med hjälp av en liten knappcell kan få batteribackup på den externa RTCn så att tiden hålls även under strömavbrott. Detta behövs dock inte med denna version av programmet då tiden hämtas från internet vid en omstart.

Det vi har nu i den här versionen är en klocka som gör följande:

  1. Kopplar upp sig mot internet och hämtar aktuell tid som sedan sparas på den externa RTCn, DS3231.
  2. Den interna RTCn uppdaterar sig mot den externa och använder sedan den tiden till klockan.
  3. Efter fem minuter så uppdateras den interna RTCn igen med tiden från den externa och detta fortsätter hela tiden.
  4. Efter fem dagar så uppdateras återigen den externa RTCn med tiden från internet och så upprepas allt detta i en slinga och nu har vi en acceptabel visning av tiden.

Inkopplingen av displayen görs för enkelhetens skull precis likadant som i version 1.0.

Det som kommer till ifråga om inkoppling är realtidsklockan som kopplas in enligt nedan.

Observera att trots att både TM1637 och DS3231 verkar använda sig av I2C så är inte detta fallet. TM1637 använder ett ”I2C-liknande” protokoll, men om man försöker koppla dem på samma buss så kommer det inte att fungera (enl. den info jag har nu). Därför är de kopplade på olika pinnar.

Bilderna nedan visar ett par av de vanligaste modellerna av DS3231-modulerna som finns tillgängliga. Modulen till vänster är endast bestyckad med en DS3231 och ett litet backupbatteri. Modulen till höger använder ett vanligt CR2032-batteri och kan enkelt bytas ut vid behov. Det finns även ett litet AT24C32 EEPROM med 4 kilobyte minne.

Den mindre av de bägge DS3231-modulerna
Den lite större modulen

Övriga komponenter är, som sagt,  samma som i version 1.0, en Wemos D1 Mini bestyckad med en ESP8266 samt en TM1637-styrd 4-siffrig 7-segments display.

Wemos D1 Mini
TM1637 modul

När allt är inkopplat så är det dags att installera MicroPython, om det inte redan är gjort. Läs hur man kan göra här. Annars rekommenderar jag verkligen att använda Thonny för att både installera MicroPython och att skriva sina Python-program i.

Vad gäller själva programmet så krävs det att det installeras två drivare. En för displayen, precis som i version 1 samt en för realtidsklockan. Klicka på knappen nedan för att hämta den till displayen.

Drivaren till realtidsklockan kan hämtas med knappen nedan, den innehåller allt för att sätta och läsa klockan från DS3231-modulen.

Här under är själva Python-programmet, Och det är fortfarande ganska enkelt. Jag har försökt att underlätta genom att kommentera mycket så det ska gå att förstå hur det fungerar ganska lätt.

# clock.py v2.0
#
# 2.0: Lade till stöd för den stabila RTCn DS3231
#
# 1.1: lade till en fördröjning 60 sekunder
# om det blir en 'fail' vid försök att ansluta
# till internet.
#
# 1.0: Fungerande klocka
#
#
# Enklast möjliga klocka i micropython för
# en Wemos D1 Mini med en TM1637-display.
#
# Tiden hämtas från nätet.
#
# Biblioteket för att driva displayen
# kan laddas ned från Github:
#
# mcauser/micropython-tm1637
#
# Wemos TM1637
# =============
# D1 CLK
# D2 DIO
# 3V3/5V VCC
# G GND
#
#
# Biblioteket för att hantera RTCn DS3231,
# kan även det, hämtas från Github:
#
# peterhinch/micropython-samples/tree/master/DS3231
#
# Wemos DS3231
# ==============
# Vin Vcc
# Gnd Gnd
# D5 scl
# D6 sda



# Här importerar vi lite funktioner som krävs
import tm1637
import network, usocket, utime, ntptime
from machine import Pin, I2C
from ds3231_port import DS3231


# Namn och lösenord till trådlösa nätet
ssid = "SSID"
password = "PASSWORD"

# Antal dagar mellan varje uppkoppling till internet
net_upd = 5
# Antal minuter mellan varje uppddatering från DS3231
rtc_upd = 5

# Håller reda om kolon ska vara tänd eller släckt
flg = False
# Tidszon
TZ = 1
# Sommartid/vintertid, 1=sommartid, 0=vintertid
DST = 0
# Räknare för att hålla reda när klockan ska
# uppdateras från internet
cnt = 0
# Räknare som håller reda när den interna RTCn
#ska uppdateras från den, mer precisa, externa RTCn
cnt2 = 0


# Funktionen för att ansluta och hämta tiden från nätet
def GetNTP():
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, password)
while not wifi.isconnected():
pass
try:
ntptime.settime()
retVal = True
except:
retVal = False

wifi.disconnect()
wifi.active(False)
return(retVal)



#Definiera displayen
tm=tm1637.TM1637(clk=Pin(4), dio=Pin(5))
tm.brightness(3)

# Definiera RTC
scl_pin = Pin(14, pull = Pin.PULL_UP, mode = Pin.OPEN_DRAIN)
sda_pin = Pin(12, pull = Pin.PULL_UP, mode = Pin.OPEN_DRAIN)
i2c = I2C(scl = scl_pin, sda = sda_pin)
ds3231 = DS3231(i2c)


# Huvudloopen som körs två gånger per sekund
while True:
if cnt <= 0:
tm.show('net ',False)
tmp = GetNTP()
if tmp == True:
# Om vi har valid internet tid, spara den
# i externa RTCn. Sätt sen räknaren till
# att vänta 'net_upd' dygn till nästa
# uppdatering via nätet.
ds3231.save_time()
cnt = net_upd * 24 * 60 * 60
else:
tm.show('Fail', False)
utime.sleep(3)

# Om det gått 'rtc_upd' minuter ställ den interna
# RTCn med tiden från den externa RTCn
if cnt2 == 0:
ds3231.get_time(set_rtc = True)
cnt2 = rtc_upd * 60

localtmp = utime.time() + TZ * 3600 + DST * 3600
localtime = utime.localtime(localtmp)

h=localtime[3]
m=localtime[4]
tm.numbers(h, m, flg)
if flg == True:
flg = False
cnt = cnt - 1
cnt2 = cnt2 - 1
else:
flg = True

utime.sleep(0.5)

Precis om tidigare är det så att när klockan slås på så försöker den ansluta till internet för att hämta aktuell tid. Detta visas på displayen enligt bilden till vänster nedan. Om inget händer på några minuter eller om ett felmeddelande som det på bilden nedan till höger  visas så har det uppstått något problem.

Kontrollera att inloggningsuppgifterna stämmer och att routern är påslagen. Andra problem kan vara att klockan befinner sig utanför räckvidden för nätverket.

När allt är påslaget och uppkopplat så kommer tiden att uppdateras från DS3231 var femte minut och från internet var femte dag.