Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

day and night cycle #3

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 164 additions & 69 deletions slag-in-de-rondte.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
# Warning: For tinkering only!
# Use at your own risk.
# Drawing too much power from the GPIO pins may damage the RPI Pico board.
# Use a separate controller, PCA9685 ? to separate the LED power from the board.
# The setup used here (without controller) works fine for me. Your mileage may vary.
# Use a separate I/O controller to separate the LED power from the board.
# The setup used here (without separate controller) works fine for me. Your mileage may vary.
#
#########################################################################################
# Lichtkarakters:
# Light characteristics of lighthouses on the Dutch Wadden isles:
# Texel FL(2) W 10s
# Vlieland ISO W 4s
# Terschelling FL(1) W 5s
Expand All @@ -61,93 +61,188 @@
schiermonnikoog = PWM(Pin(20), f)

# Coroutine: Flash a LED, once
# Glow the LED on and off, using PWM (Pulse Width Modulation).
async def flash(pwm):
# A lighthouse 'flash' may take 2 seconds or more
# According to RaspberryPi.org the max PWM duty cycle: 65025
# Light off ==> 'duty cycle = 0'
# Light on ==> 'duty cycle = 65025'

# Turn light on and off, using fractions of the duty cycle (PWM)
for i in range(100):
# Using sin() is just a snazzy way of getting increasing and descreasing fractions in one loop...
fraction = math.sin(i/100 * math.pi)
pwm.duty_u16(round(fraction * 65025))
await uasyncio.sleep_ms(12)
# Force light off
pwm.duty_u16(0)
await uasyncio.sleep_ms(1600)

# Corouting: Isophase a LED; first half of the duration 'on', second half of the duration 'off'
# Glow the LED on and off, using PWM (Pulse Width Modulation).
"""Fade a LED on and off, using Pulse Width Modulation

Parameters
----------
pwm
The PWM object representing a LED.

Returns
-------
None

Description
-----------
A lighthouse 'flash' may take 2 seconds or more
According to RaspberryPi.org the max PWM duty cycle: 65025
Light off ==> 'duty cycle = 0'
Light on ==> 'duty cycle = 65025'
"""
for i in range(100):
# Using sin() is just a snazzy way of getting increasing and descreasing fractions in one loop...
fraction = math.sin(i/100 * math.pi)
pwm.duty_u16(round(fraction * 65025))
await uasyncio.sleep_ms(12)

# Force light off
pwm.duty_u16(0)
await uasyncio.sleep_ms(1600)

# Corouting: Isophase a LED
async def isophase(pwm, d):
# Light on
for i in range(0, 100, 5):
pwm.duty_u16(round(i/100 * 65025))
await uasyncio.sleep_ms(10)
await uasyncio.sleep_ms(round(d/2) * 1000)
"""Isophase a LED on and off, using Pulse Width Modulation

Parameters
----------
pwm
The PWM object representing a LED.
d : int
Duration of the entire on-and-off cycle in seconds.

Returns
-------
None

Description
-----------
Isophase means:
first half of the duration 'on', second half of the duration 'off'
"""
# Light on
for i in range(0, 100, 5):
pwm.duty_u16(round(i/100 * 65025))
await uasyncio.sleep_ms(10)
await uasyncio.sleep_ms(round(d/2) * 1000)

# Light off
for i in range(100, 0, -5):
pwm.duty_u16(round(i/100 * 65025))
await uasyncio.sleep_ms(10)
pwm.duty_u16(0)
await uasyncio.sleep_ms(round(d/2) * 1000)
# Light off
for i in range(100, 0, -5):
pwm.duty_u16(round(i/100 * 65025))
await uasyncio.sleep_ms(10)
pwm.duty_u16(0)
await uasyncio.sleep_ms(round(d/2) * 1000)

# Corouting: Fade out a LED
async def fade_out(pwm):

# Get the current duty cycle and fade out from there.
current_duty_cycle = pwm.duty_u16()
current_duty_cycle_fraction = (current_duty_cycle // 650.25)

# Light off
for i in range(current_duty_cycle_fraction, 0, -2):
pwm.duty_u16(round(i/100 * 65025))
await uasyncio.sleep_ms(12)
pwm.duty_u16(0)

# Coroutine: characteristics of light: Texel FL(2) W 10s
async def characteristics_texel(texel):
while True:
time_begin = time.ticks_ms()
await flash(texel)
await flash(texel)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(10000 - time_elapsed)
while True:
try:
time_begin = time.ticks_ms()
await flash(texel)
await flash(texel)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(10000 - time_elapsed)

except (uasyncio.CancelledError):
# Switch off
await fade_out(texel)
print('Task Texel cancelled')
raise

# Coroutine: characteristics of light: Vlieland ISO W 4s
async def characteristics_vlieland(vlieland):
while True:
await isophase(vlieland, 4)
while True:
try:
await isophase(vlieland, 4)

except (uasyncio.CancelledError):
# Switch off
await fade_out(vlieland)
print('Task Vlieland cancelled')
raise

# Coroutine: characteristics of light: Terschelling FL(1) W 5s
async def characteristics_terschelling(terschelling):
while True:
time_begin = time.ticks_ms()
await flash(terschelling)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(5000 - time_elapsed)
while True:
try:
time_begin = time.ticks_ms()
await flash(terschelling)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(5000 - time_elapsed)

except (uasyncio.CancelledError):
# Switch off
await fade_out(terschelling)
print('Task Terschelling cancelled')
raise

#Coroutine: characteristics of light: Ameland FL(3) W 15s
async def characteristics_ameland(ameland):
while True:
time_begin = time.ticks_ms()
await flash(ameland)
await flash(ameland)
await flash(ameland)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(15000 - time_elapsed)
while True:
try:
time_begin = time.ticks_ms()
await flash(ameland)
await flash(ameland)
await flash(ameland)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(15000 - time_elapsed)

except (uasyncio.CancelledError):
# Switch off
await fade_out(ameland)
print('Task Ameland cancelled')
raise

# Coroutine: characteristics of light: Schiermonnikoog FL(4) W 20s
async def characteristics_schiermonnikoog(schiermonnikoog):
while True:
time_begin = time.ticks_ms()
await flash(schiermonnikoog)
await flash(schiermonnikoog)
await flash(schiermonnikoog)
await flash(schiermonnikoog)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(20000 - time_elapsed)
while True:
try:
time_begin = time.ticks_ms()
await flash(schiermonnikoog)
await flash(schiermonnikoog)
await flash(schiermonnikoog)
await flash(schiermonnikoog)
time_elapsed = time.ticks_ms() - time_begin
await uasyncio.sleep_ms(20000 - time_elapsed)

except (uasyncio.CancelledError):
# Switch off
await fade_out(schiermonnikoog)
print('Task Schiermonnikoog cancelled')
raise

# Coroutine: entry point for uasyncio program
async def main():
uasyncio.create_task(characteristics_texel(texel))
uasyncio.create_task(characteristics_vlieland(vlieland))
uasyncio.create_task(characteristics_terschelling(terschelling))
uasyncio.create_task(characteristics_ameland(ameland))
uasyncio.create_task(characteristics_schiermonnikoog(schiermonnikoog))

while True:
# do nothing, while tasks run :)
await uasyncio.sleep_ms(10000)

# Half a day contains roughly two tidal cycles
# In the board game this takes 8 minutes (480 seconds)
two_tidal_cycles = 480
while True:

# A night of sailing starts
# Switch on all five lighthouses
task_tx = uasyncio.create_task(characteristics_texel(texel))
task_vl = uasyncio.create_task(characteristics_vlieland(vlieland))
task_ts = uasyncio.create_task(characteristics_terschelling(terschelling))
task_am = uasyncio.create_task(characteristics_ameland(ameland))
task_sch = uasyncio.create_task(characteristics_schiermonnikoog(schiermonnikoog))

# Let everything run for two cycles
await uasyncio.sleep(two_tidal_cycles)

# After a night of sailing comes... a day of sailing :)
# Switch off all five lighthouses
task_tx.cancel()
task_vl.cancel()
task_ts.cancel()
task_am.cancel()
task_sch.cancel()

## Let everything be off for two cycles
await uasyncio.sleep(two_tidal_cycles)

# Start event loop
uasyncio.run(main())