/
clock7.py
278 lines (239 loc) · 7.51 KB
/
clock7.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# microbit clock application, using WhaleySans font to show 2 digits per microbit
# David Saul copyright 2017 @david_ms, www.meanderingpi.wordpress.com
# Inspired by utilising code by David Whale [@whaleygeek] and M Atkinson [multiWingSpan.co.uk]
# Available under MIT License via github.com/DavidMS51
# this version devloped to use a 2331 RTC module connected via the I2C port
# s/w will identify which microbit has the RTC connected and make that the master
# microbit with p0 taken high will display hours [ 24 hour clock ]
# microbit with p1 taken high will display minutes
# microbit with p0 & p1 taken low will display seconds
# microbit with p3 taken high will display scrolling time
# All microbit work from the same code, and you have have as many as you want
# running at the same time but keep it to one mast !
# It can take up to a minute for all the microbit to sort themsleves out from startup
# To set the RTC hold button A at reset until clock apears
# use button a to advance hours
# use button b to advance minutes
# hold button a & b down at the same time to write the new time to the RTC
# The code includes options for either 12 or 24 hour clocks - just uncomment the lines as shown
# note you have to change the code in 2 places currently to do this
from microbit import *
import radio
#setup global variables
radio.config(group=7)
TICK_RATE = 1000 # ticks in a second
HOURS, MINS, SECS, SCROLL = 'h','m','s','r' # config IDs
next_tick = 0 # init tick counter
mst = False # master microbit flag
upd = False # radio update - used to avoide multiple updates
addr = 0x68
buf = bytearray(7)
#I2C read and write code
def bcd2dec(bcd):
return (((bcd & 0xf0) >> 4) * 10 + (bcd & 0x0f))
def dec2bcd(dec):
tens, units = divmod(dec, 10)
return (tens << 4) + units
def get_time():
i2c.write(addr, b'\x00', repeat=False)
buf = i2c.read(addr, 7, repeat=False)
ss = bcd2dec(buf[0])
mm = bcd2dec(buf[1])
if buf[2] & 0x40:
hh = bcd2dec(buf[2] & 0x1f)
if buf[2] & 0x20:
hh += 12
else:
hh = bcd2dec(buf[2])
# DD = bcd2dec(buf[4])
# MM = bcd2dec(buf[5] & 0x1f)
# uncoment for 12hour clock
if hh >= 13:
hh = hh-12
return hh,mm,ss
#change RTC time setting - only runs at reset on master
def set_time():
global hours, mins
but_a = True
but_b = True
while True:
if button_a.is_pressed() and button_b.is_pressed():
break
elif button_a.is_pressed():
if but_a:
display.show('H', clear=True)
hours -=1
but_a = False
but_b = True
hours +=1
if hours > 23:
hours = 0
display.show(img(hours))
elif button_b.is_pressed():
if but_b:
display.show('M', clear=True)
mins -=1
but_b = False
but_a = True
mins +=1
if mins > 59:
mins = 0
display.show(img(mins))
sleep(250)
# to set time manually
# s,m,h,w,dd,mm,yy - array format for time
# t=bytes([0,58,0,01,17,08,17]) # coment out following line, uncoment this line
try:
t = bytes([0,mins,hours,01,01,01,17])
for i in range(0,7):
i2c.write(addr, bytes([i,dec2bcd(t[i])]), repeat=False)
display.show(Image.YES)
except:
display.show(Image.SAD)
sleep(2000)
return
#identify which config the microbit will be
def read_config():
global config
if pin2.read_digital() == 1:
config = SCROLL
elif pin0.read_digital() == 1:
config = HOURS
elif pin1.read_digital() == 1:
config = MINS
else:
config = SECS
# Image cade for 2 digit display options
FONT = ( # WhaleySans font, 2x5 digits only
("88","88","88","88","88"),
("08","08","08","08","08"),
("88","08","88","80","88"),
("88","08","88","08","88"),
("80","80","88","08","08"),
("88","80","88","08","88"),
("88","80","88","88","88"),
("88","08","08","08","08"),
("88","88","00","88","88"),
("88","88","88","08","88")
)
#("99","99","99","99","99"),
#("09","09","09","09","09"),
#("99","09","99","90","99"),
#("99","09","99","09","99"),
#("90","90","99","09","09"),
#("99","90","99","09","99"),
#("99","90","99","99","99"),
#("99","09","09","09","09"),
#("99","99","00","99","99"),
#("99","99","99","09","99")
#)
def img(n):
lg = FONT[int(n/10)]
if int(n/10) == 0 and config == HOURS :
lg = ("00","00","00","00","00")
rg = FONT[int(n%10)]
c = ""
for r in range(5):
c += lg[r] + "0" + rg[r]
if r != 4:
c += ':'
return Image(c)
def set_clock(t):
global hours, mins, secs
#hh:mm:ss\n
try:
t2 = t.strip()
hours, mins, secs = t2.split(':')
hours = int(hours)
mins = int(mins)
secs = int(secs)
print('Time update ok')
except:
print("Invalid time set:%s" % str(t))
# Create counting logic
def tick():
global hours, mins, secs
secs += 1
if secs >= 60:
secs = 0
mins += 1
if mins >= 60:
mins = 0
hours += 1
# uncoment for 24hour clock
# if hours >= 24:
# hours = 0
# uncoment for 12hour clock
if hours >= 13:
hours = 1
#update the microbit display depenind on the config option
def refresh_display():
if config == HOURS:
display.show(img(hours))
elif config == MINS:
display.show(img(mins))
elif config == SECS:
display.show(img(secs))
elif config == SCROLL:
if secs%6 == 0:
if secs != 0:
display.scroll(str(hours)+':'+str(mins)+' ', wait=False, delay=180)
# unless master microbit check for time re-cal
def check_time_radio():
if mst == False:
try:
t = radio.receive()
if t is not None:
set_clock(t)
except:
# print("radio error reseting")
radio.off()
radio.on()
#sent time cal to all slave microbits
def pass_on_time():
t = "%02d:%02d:%02d" % (hours, mins, secs)
radio.send(t)
# check if 1 second since last 'tick'
# also every minute check RTC and update
def check_update():
global next_tick, upd
global hours, mins, secs
now = running_time()
if now >= next_tick:
tick()
if mst == True:
if secs == 5 and upd == False:
try:
hours,mins,secs = get_time()
upd = True
pass_on_time()
except:
upd = False
else:
upd = False
next_tick = now + TICK_RATE
refresh_display()
# main running routine
# setup
read_config()
radio.on()
try:
hours,mins,secs = get_time()
display.show(Image.HAPPY)
sleep(2000)
mst = True
pass_on_time()
# check to RTC update request
if button_a.is_pressed():
display.show(Image.ALL_CLOCKS, loop=True, delay=150, wait=False)
while button_a.is_pressed():
sleep(100)
set_time()
except:
display.show(Image.DIAMOND_SMALL)
sleep(2000)
hours,mins,secs = 0,0,0
#main running loop
while True:
check_time_radio()
check_update()