I am very inexperienced with Python so bear with me. I am trying to set a schedule in a RaspiPico to turn a RaspPi 3B+ on at given times. The RaspPi 3B+ turns itself off at the 57th minute of every hour, the Pico is supposed to turn it on at the 24th minute of every hour. I've worked out the code so that when I manually run it through Thonny, it turns the RaspPi 3B+ on and doesnt give any error messages anymore, but when left on its own it doesn't appear to be following a schedule. To clarify there is also an RTC included in this Raspi Sandwich. Here is my code:
from machine import Pin, Timer, RTC, I2C
import time
import binascii
# I2C PINSs
I2C_PORT = 0
I2C_SDA = 20
I2C_SCL = 21
# Times when the B+ should be booted up
# Format is (hours, minutes)
# For now, keep it sorted; we could do this in code, but why not just do it by hand
SCHEDULE = [(0, 24, 0), (0, 56, 0), (1, 24, 0), (1, 56, 0), (2, 24, 0), (2, 56, 0), (3, 24, 0), (3, 56, 0), (4, 24, 0), (4, 56, 0), (5, 24, 0), (5, 56, 0), (6, 24, 0), (6, 56, 0), (7, 24, 0), (7, 56, 0), (8, 24, 0), (8, 56, 0), (9, 24, 0), (9, 56, 0)
, (10, 24, 0), (10, 56, 0), (11, 24, 0), (11, 56, 0), (12, 24, 0), (12, 56, 0), (13, 24, 0), (13, 56, 0), (14, 24, 0), (14, 56, 0), (15, 24, 0), (15, 56, 0), (16, 24, 0), (16, 56, 0), (17, 24, 0), (17, 56, 0), (18, 24, 0), (18, 56, 0), (19, 24, 0), (19, 56, 0),
(20, 24, 0), (20, 56, 0), (21, 24, 0), (21, 56, 0), (22, 24, 0), (22, 56, 0), (23, 24, 0), (23, 56, 0)]
# This function returns the next scheduled boot time
# after the hour, minute we provide
def grab_next_time(time_tuple):
current_hour, current_min, current_sec = time_tuple
# Go through all scheudled boot times from first to last
for h, m, s in SCHEDULE:
# If current hour is before hour, we found the next time
if current_hour < h:
return (h,m, s)
# If its the same hour
elif current_hour == h:
# If its before the minute, we found the next time
if current_min < m:
return (h,m,s)
# if its the same minute
elif current_min == m:
# If its before the second, we found the next time
if current_sec < s:
return (h,m,s)
# If the current hour is not the same or before, lets try the next
# We tried all times in the schedule,
# we're after, so lets start from the begining
return SCHEDULE[0]
# This function returns the time we need to wait in seconds
def wait_time(current_time, next_time):
next_hour, next_min, next_sec = next_time[0], next_time[1], next_time[2]
current_hour, current_min, current_sec = current_time[0], current_time[1], current_time[2]
wait_time = (next_sec - current_sec)
if (next_sec - current_sec) < 0:
wait_time += 60
next_min -= 1
wait_time += (next_min - current_min) * 60
if (next_min - current_min) < 0:
wait_time += (60 * 60)
next_hour -= 1
wait_time += (next_hour - current_hour) * 60 * 60
if (next_hour - current_hour) < 0:
wait_time += (60 * 60 * 24)
return wait_time
def start_local_rtc(date=(2017, 8, 23, 2, 12, 48, 0, 0)):
rtc = machine.RTC()
rtc.datetime(date)
return rtc
class ds3231(object):
NowTime = b'\x00\x45\x13\x02\x24\x05\x21'
w = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
address = 0x68
start_reg = 0x00
alarm1_reg = 0x07
control_reg = 0x0e
status_reg = 0x0f
def __init__(self,i2c_port,i2c_scl,i2c_sda):
self.bus = I2C(i2c_port,scl=Pin(i2c_scl),sda=Pin(i2c_sda))
def read_time(self):
t = self.bus.readfrom_mem(int(self.address),int(self.start_reg),7)
seconds = (t[0]&0x0F) + 10 * ((t[0]>>4)&0x07)
minutes = (t[1]&0x0F) + 10 * ((t[1]>>4)&0x07)
hour = (t[2]&0x0F) + 20 * ((t[2]>>4)&0x02) #hour ( 11 1111)
dow = t[3]&0x07 #week
day = (t[4]&0x0F) + 10 * ((t[4]>>4)&0x03) #day
month = (t[5]&0x1F) + 10 * ((t[5]>>4)&0x01) #month
year = 2000 + ((t[6]&0x0F) + 10 * ((t[6]>>4)&0x0F)) # year
#(year, month, day, weekday, hours, minutes, seconds, subseconds)
return (year, month, day, hour, minutes, seconds, 0, 0)
#print("20%x/%02x/%02x %02x:%02x:%02x %s" %(t[6],t[5],t[4],t[2],t[1],t[0],self.w[t[3]-1]))
# For a second, override the start pin
def start_pi():
boot = Pin(21, Pin.OUT)
boot.value(0)
time.sleep(0.1) # 100 ms should do
boot = Pin(21, Pin.IN) # Setting the pin to IN should make it float
if __name__ == '__main__':
# On startup grab the time from the RTC
hw_rtc = ds3231(I2C_PORT, I2C_SCL, I2C_SDA)
time_rtc = hw_rtc.read_time()
print(time_rtc)
local_rtc = start_local_rtc()
# This is our infinite loop
while True:
current_time = local_rtc.datetime()
current_time = (current_time[4], current_time[5], current_time[6])
print(current_time)
next_time = grab_next_time(current_time)
print("Next time: ", next_time)
wait_time = wait_time(current_time, next_time)
print("Wait time: ", wait_time)
# If within 30 seconds, start the pi
if wait_time < 30:
start_pi()
# If we need to wait for more than 30 seconds, keep waiting
else:
time.sleep(wait_time - 5)
The person I am working with mentioned that the Pico will "poke" the Pi and not stop poking until the specified time. hence why my schedule is listed as "(0,24,0), (0,56,0)". In my head this is supposed to start the "poking" at the 24th minute after midnight and stop at the 56th minute. As was stated before this obviously isn't what is going on. Some help would be appreciated.