Skip to content

Instantly share code, notes, and snippets.

@danmou
Created May 11, 2020 20:05
Show Gist options
  • Save danmou/ced74b8df3719988a7c8294f9f6ffb25 to your computer and use it in GitHub Desktop.
Save danmou/ced74b8df3719988a7c8294f9f6ffb25 to your computer and use it in GitHub Desktop.
MicroPython script for LED wall clock using ESP8266 and NeoPixels
import time
from neopixel import NeoPixel
from machine import Pin, I2C
from math import floor, ceil
from ntptime import settime
import tsl2561 # https://github.com/adafruit/micropython-adafruit-tsl2561
color_m = (0.65, 0.65, 0)
width_m = 2.0
color_h = (0, 0, 1.0)
width_h = 1.8
decay_factor = 1.0
max_int = 0.8
min_int = 0.25
max_lux = 5
min_lux = 0.5
np = NeoPixel(Pin(4), 60 + 24) # D2
i2c_sensor = I2C(scl=Pin(2), sda=Pin(13)) # scl=D4, sda=D7
sensor = tsl2561.TSL2561(i2c_sensor)
summertime = 0
last_update = 0
last_draw = 0
intensity_scaling = 0
debug = False
def round(x):
return floor(x + 0.5)
def draw_time(h, m):
global last_draw
dt = int(h) * 60 + m - last_draw # minutes
if dt > 1.0:
draw_range_m = 30
draw_range_h = 12
else:
draw_range_m = width_m
draw_range_h = width_h
for i in range(ceil(m - draw_range_m), ceil(m + draw_range_m)):
np[i % 60] = gamma(*color_m, s=1 - (abs(i - m) / width_m)**decay_factor)
h = (h % 12)*2
for i in range(ceil(h - draw_range_h), ceil(h + draw_range_h)):
np[60 + i % 24] = gamma(*color_h, s=1 - (abs(i - h) / width_h)**decay_factor)
np.write()
last_draw += dt
def gamma(r, g, b, s=1):
s *= intensity_scaling
s = max(0, s)
return (_gamma(r*s), _gamma(g*s), _gamma(b*s))
def _gamma(x):
return max(0, min(255, round(x**2.8 * 255)))
def clear_display():
np.fill((0, 0, 0))
np.write()
def update_summertime():
global summertime
y, M, d, h, m, s = time.localtime()[0:6]
if (3 < M < 10
or M == 3 and d >= 31 - (((5 * y) / 4 + 4) % 7) and h >= 1
or M == 10 and (d < 31 - (((5 * y) / 4 + 1) % 7)
or d == 31 - (((5 * y) / 4 + 1) % 7) and h == 0)):
summertime = 1
else:
summertime = 0
def get_time():
if debug:
# 60x speed
m = time.ticks_ms() / 1000
h = (m / 60) % 24
m = m % 60
return h, m
y, M, d, h, m, s = time.localtime()[0:6]
m = m + s / 60
h = h + m / 60
return (h + summertime + 1, m) # localtime is in UTC
def update_intensity_scaling():
global intensity_scaling
lux = sensor.read() # ranges between approximately 0.5 and 6
intensity_scaling = min(
max(
(lux - min_lux) * (max_int - min_int) / (max_lux - min_lux) + min_int,
min_int),
max_int)
if debug:
print("Lux: {:.2f}, scaling: {:.2f}".format(lux, intensity_scaling))
def do_animation():
cur_h, cur_m = get_time()
for i in range(121):
h = cur_h - i / 5 # -1 rotation
m = cur_m + i / 2 # 1 rotation
draw_time(h, m)
draw_time(*get_time())
def run(debug_=False):
global last_update, debug
debug = debug_
sensor.gain(1)
sensor.integration_time(402)
sensor.active(True)
clear_display()
while True:
try:
settime()
except OSError:
print("Error connecting to time server, trying again...")
time.sleep_ms(500)
else:
last_update = time.time()
break
last_m = 0
while True:
if time.time()-last_update >= 3600:
if debug:
print("Updating time")
try:
settime()
except OSError:
print("Error connecting to time server")
else:
last_update = time.time()
update_intensity_scaling()
update_summertime()
t = get_time()
if debug:
print("Time is: h={:.2f}, m={:.2f}".format(*t))
if last_m > 0 and t[1] < last_m:
do_animation()
else:
draw_time(*t)
time.sleep_ms(100 if debug else 500)
last_m = t[1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment