Skip to content
Open
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions documentation/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ The Enviro boot up process is relatively complex as we need to ensure that thing
have_destination-->|No|sleep3

```

### PIO watchdog

Issues relating to hardware hangs have been corrected by @julia767 adding in a PIO based watchdog timer that will remove the power and put the board back to deep sleep after a set period of time. This can be set in the config.py in minutes. In addition, it also sets the RTC Alarm to wake one minute after the watchdog time puts it to sleep. In the normal execution where there are no hardware hangs the RTC alarm is overwritten with the normal alarm based on the reading frequency. When setting the watchdog timer consider how long the device will need to run to upload many cached files in the event of Wifi or destination outage. Testing to date (mqtt over ssl which is slow to upload) shows a watchdog time of 20 minutes will suffice to upload 100’s of cached readings but should be tuned to your own needs.
72 changes: 72 additions & 0 deletions enviro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,69 @@ def upload_readings():

return True




# define DELAYOFF used to ensure enviro will power down even if it hangs
# ----------------------------------------------------------------------
from machine import Pin
from rp2 import PIO, StateMachine, asm_pio

@asm_pio(sideset_init=PIO.OUT_HIGH)
def delayoff_prog():
label('d_loop')
jmp(y_dec, 'd_loop') [1]
label('done')
jmp('done').side(0)

class DELAYOFF:
def __init__(self, pin, delay, sm_id=0):
delay_ms=int(delay * 60 * 1000)
self._sm = StateMachine(sm_id, delayoff_prog, freq=2000, sideset_base=Pin(pin))
self._sm.put(delay_ms)
self._sm.exec('pull()')
self._sm.exec("mov(y, osr)") #load max count into y
self._sm.active(1)
logging.debug(f'> delayoff set on gpio{pin:} for {delay_ms:} ms')

def arm_watchdog():
# set default alarm now in case processor hangs. Normally ths is overwritten by sleep()

if helpers.file_exists("watchdog_live.txt"):
os.remove("watchdog_live.txt")
logging.warn("> * * Processor recovered by watchdog * *")

# this code extracted from sleep TODO make into routine shared by both -----------------
dt = rtc.datetime()
hour, minute, second = dt[3:6]

# make sure the Alarm in the event of watchdog is set to 1 minute ahead
minute += int(config.pio_watchdog_time)
minute += 1
#For edge case?? May not be needed
if second > 55:
minute += 1

while minute >= 60:
minute -= 60
hour += 1
if hour >= 24:
hour -= 24
ampm = "am" if hour < 12 else "pm"

logging.info(f" - setting default alarm to wake at {hour:02}:{minute:02}{ampm}")

# sleep until next scheduled reading
rtc.set_alarm(0, minute, hour)
rtc.enable_alarm_interrupt(True)
#------------------------------------------------------------------end copied from sleep

# power will be pulled based on wathdog time (set in config file in minutes)
delayoff = DELAYOFF(HOLD_VSYS_EN_PIN, int(config.pio_watchdog_time))
with open("watchdog_live.txt", "w") as hangfile:
hangfile.write("")


def startup():
import sys

Expand All @@ -486,6 +549,9 @@ def startup():

# log the wake reason
logging.info(" - wake reason:", wake_reason_name(reason))
#set watchdog if configured in config file
if config.pio_watchdog_time is not 0:
arm_watchdog()

# also immediately turn on the LED to indicate that we're doing something
logging.debug(" - turn on activity led")
Expand Down Expand Up @@ -548,6 +614,10 @@ def sleep(time_override=None):
# sleep until next scheduled reading
rtc.set_alarm(0, minute, hour)
rtc.enable_alarm_interrupt(True)

# delete watchdog file
if helpers.file_exists("watchdog_live.txt"):
os.remove("watchdog_live.txt")

# disable the vsys hold, causing us to turn off
logging.info(" - shutting down")
Expand Down Expand Up @@ -578,3 +648,5 @@ def sleep(time_override=None):

# reset the board
machine.reset()


3 changes: 3 additions & 0 deletions enviro/config_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
# how often to upload data (number of cached readings)
upload_frequency = 5

# Watchdog timer in whole minutes (integer), 0 is not active
pio_watchdog_time = 20

# web hook settings
custom_http_url = None
custom_http_username = None
Expand Down