Per Dan, here is the full code. I know it pushes the limits of the RPi Pico W. However it does work.
The error only goes away when I pull power.
At REPL prompt - microcontroller.restart does not fix it, code restarts but error persists
If it is a software issue, microcontroller.restart should have trumped the others and fixed the issue.
adafruit2, Thank you for your post. I must not understand what you are saying. I understand the wrong format number is being passed to the function. Restarting the code with one of the non-power removal options should have restarted things fresh. Pushing the RESET (RUN) button is a very harsh restart (that until now I thought was the same a power), but it does not fix it. CP 8.0.0 B6 or the LTR may be holding onto something that survives everything but a power reset. But then I will admit I don't know what all the pieces and parts are doing at the boiler plate level. When I do a power reset, things run for days with no problem.
The next time it happens I am going to move lines of code to different positions to see if the error moves with the code or stays at the same relative position. Move line #275 down and test. Comment out line #275 and test. other things dictated by the previous results and test. Report results.
I count code loops, loops this run, and code starts.
This code has been run through almost 1 million loops, with 771 code starts. Code starts include power applied, starts after an edit of code and a restart, starts after a supervisor.reload, microntroller.restart and Crtl C & D.
Code: Select all
"""
Internet Clock using Maker Pi Pico and CircuitPython
20 - Soft Reload
21 - Hard Reboot + 22
22 - Soft Reload
Pico W 28:cd:c1:00:6b:08 .204 Maker Pi Pico W
Pico W 28:cd:c1:00:6b:73 .215 Under keyboard
Pico W 28:cd:c1:01:1c:6a .229 Client
Pico W 28:cd:c1:03:9e:26 .236 Server
ESP-01 2c:f4:32:8c:85:61 .208 Maker Pi Pico Rev 1.2
ESP-01 2c:f4:32:8c:85:b8 .211
ESP-01 2c:f4:32:8c:8a:25 .220
ESP-01 2c:f4:32:8c:8d:84 .233
"""
# Intrinsic Libraries
import time
#timetime = time.time()
import os
import gc
import rtc
import sys
import ssl
import wifi # 8.0.0 Beta 5 Pico W
import json
import math
import busio
import busio as busio
import board
from board import *
#from struct import unpack
import random
import storage
import builtins
import digitalio
from digitalio import *
import ipaddress # 8.0.0 Beta 5 Pico W
import traceback
import socketpool # 8.0.0 Beta 5 Pico W
import supervisor
from neopixel_write import neopixel_write
import microcontroller
try: # for FRAM
from digitalio import DigitalInOut
from busio import I2C, SPI
except ImportError:
raise
# Extrinsic Libraries
import simpleio
import adafruit_ntp
import adafruit_fram
import adafruit_ds3231
import adafruit_sht4x
from adafruit_bme280 import advanced as adafruit_bme280
import adafruit_sdcard
import adafruit_ssd1306
#import adafruit_bus_device
import adafruit_ltr329_ltr303 as LTR_329
import adafruit_requests as requests
from pitches import tones
from pitches import mario
#import adafruit_wiznet5k
#class adafruit_wiznet5k.adafruit_wiznet5k.WIZNET5K(spi_bus, cs, reset=None, is_dhcp=True,
# mac=(222, 173, 190, 239, 254, 237), hostname=None, dhcp_timeout=30, debug=False)
# ## 222, 173, 190, 239, 254, 237 = 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed = dead beef feed
# spi_bus = busio.SPI(board.GP6,board.GP7,board.GP4, board.GP9)
# eth = WIZNET5K(spi_bus, mac=(222, 173, 190, 239, 254, 237))
try: from sparkfun_alphanumeric_bbb import QwiicAlphanumeric as Qwiic
except: from sparkfun_alphanumeric import QwiicAlphanumeric as Qwiic
import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket
from adafruit_espatcontrol import adafruit_espatcontrol as espatcontrol
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("All secret keys are kept in secrets.py, please add them there!")
raise
Board = board.board_id
if Board == 'raspberry_pi_pico':
Board = 'Pico'
import Maker_Pi_Pico_Base as MPPio
elif Board == 'raspberry_pi_pico_w':
Board = 'PicoW'
MPPio = builtins.__import__('/boards/' + board.board_id)
else:
print('No compatable OS or board found')
raise
#print('\t ', time.time() - timetime, 'Seconds to get all librarys loaded')
time.sleep(0.1)
prev_scnds = None
prev_minutes = None
prev_hours = None # Not Used
prev_mday = None
prev_year = None
internet = None # Not Tested
request_time = True
display_date = True
Clock = "24" # "24"=24 hour Clock, "12"=AM/PM Clock
setTime = True
# Options
BME_Flag = True # 0x760x
SHT_Flag = not True # 0x44
CPU_Flag = True
FRAM_Flag = True # 0x50
FRAM_Full = not True # 0x50
HTTP_Flag = not True
LTR_Flag = True # ltr_329(), True, False, 2 0x29
OLED_Flag = not True # 0x3C
PING_Flag = True
RTC_Flag = True # DS3231 0x68
WiFi_Flag = True # WiFi Address
Qwiic_Flag = True
# WiFi & SD Card Stuff
AP_List_Flag = True
ESP_01_WiFi = True
SD_card_Flag = True
PicoW_WiFi = True
if (Board == 'PicoW'): SD_card_Flag = False
if (Board == 'Pico' ): PicoW_WiFi = False
Sea_Level = 1030.0 # @ USNA
ZIP = '21402'
int_size = 4
Loops = 0x98+0x0 # 152/98 # FRAM memory locations
Starts = 0x98+0x4 # 156/9c # FRAM 4 bytes per intiger number
this_run = 0x98+0x8 # 160/a0 #
next_num = 0x98+0xc # 164/a4 #
next_num = 0x98+0x10 # 164/a8 #
TickTock = True
Westminster = not True
Chime_Flag = not True # Hourly Chimes
Pi_e = True
playMario = not True
First = True
First_OWM = True
Yes_No = ('No', 'Yes')
WIFI_SSID = os.getenv("WIFI_SSID")
WIFI_PASSWORD = os.getenv("WIFI_PASSWORD")
WIFI_SSID0 = os.getenv("WIFI_SSID0")
WIFI_PASSWORD0 = os.getenv("WIFI_PASSWORD0")
MODEM_IP = os.getenv("modem_ip")
DoW = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Beerday"]
Month = ["Null","January","February","March","April","May","June",
"July","August","September","October","November","December"]
DTG_API = "http://worldtimeapi.org/api/ip"
URL = 'http://api.openweathermap.org/data/2.5/weather'
CITY_ZIP = '?zip='
OWM_KEY = '&appid='
OWM_TOKEN = secrets["openweather_token"]
# end of constants, flags, and variables
if Board == 'Pico':
VMon = DigitalInOut(board.VOLTAGE_MONITOR)
SMPS = DigitalInOut(board.SMPS_MODE)
VBUS = DigitalInOut(board.VBUS_SENSE)
VMon.direction = Direction.INPUT
SMPS.direction = Direction.INPUT
VBUS.direction = Direction.INPUT
if True != True:
print(microcontroller.cpu.uid)
print('')
print(board.board_id)
print('')
print(dir(MPPio))
print('')
print(MPPio.GROVE_4)
print('')
time.sleep(5)
# on-board buzzer
KHz = 10**3 * 1
BUZZER = MPPio.BUZZER # board.GP18
simpleio.tone(BUZZER, KHz, 0.25)
BR = 21
if BR == 26: _BAUDRATE = 26_400_000 # bps aka 253.44 MBps, 26 Seconds
elif BR == 21: _BAUDRATE = 21_120_000 # bps aka 168.96 MBps, 26 Seconds
elif BR == 10: _BAUDRATE = 10_560_000 # bps aka 84.48 MBps, 35 Seconds
elif BR == 5: _BAUDRATE = 5_280_000 # bps aka 42.24 MBps, 40 Seconds
elif BR == 2: _BAUDRATE = 2_640_000 # bps aka 21.12 MBps, 52 Seconds
elif BR == 1: _BAUDRATE = 1_320_000 # bps aka 10.56 MBps, 73 Seconds
elif BR == 0: _BAUDRATE = 660_000 # bps aka 5.28 MBps, 119 Seconds
else: _BAUDRATE = 1_320_000 # bps aka 10.56 MBps, 73 Seconds DEFAULT
# Connect to the card and mount the filesystem.
print("\t\t\b\bBaud Rate: {:,} bps".format(_BAUDRATE))
if SD_card_Flag:
try:
# on-board default SPI for SD card
SCK = MPPio.SCK # board.GP10
MOSI = MPPio.MOSI # board.GP11
MISO = MPPio.MISO # board.GP12
SD_CS = MPPio.SD_CS # board.GP15
spi = busio.SPI(SCK, MOSI, MISO)
cs = digitalio.DigitalInOut(SD_CS)
cs.direction = digitalio.Direction.OUTPUT
sd = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sd)
except(OSError) as er:
print("SD Card Mount Fail...", er)
SD_card_Flag = False
try:
storage.mount(vfs, '/SD_Card')
if 1: sys.path.append('/sd') # Add to end
if 0: sys.path.insert(0, '/sd') # Add to front
if 0: sys.path.append('/sd/lib') # Add to end
if 0: sys.path.insert(0, '/sd/lib') # Add to front
print('\t\t\bsys.path:', sys.path)
except:
print("storage.mount(vfs, '/SD_Card') Failure")
SD_card_Flag = False
if SD_card_Flag: # Test write/read to SD card
with open("/SD_Card/test.txt", "w") as f:
#print("Write line to file /SD_Card/test.txt:")
f.write("Hello CircuitPython!\r\n")
with open("/SD_Card/test.txt", "r") as f:
#print("Read line from file /SD_Card/test.txt:")
print(f.readline())
time.sleep(1)
# RGB Pin
RGB = digitalio.DigitalInOut(MPPio.NEOPIXEL) # GP28)
RGB.direction = digitalio.Direction.OUTPUT
# RGB Colors
C = 25
pixel_off = bytearray([0, 0, 0])
pixel_black = bytearray([0, 0, 0])
pixel_green = bytearray([C, 0, 0])
pixel_red = bytearray([0, C, 0])
pixel_blue = bytearray([0, 0, C])
pixel_magenta = bytearray([0, C, C])
pixel_cyan = bytearray([C, 0, C])
pixel_yellow = bytearray([C, C, 0])
pixel_white = bytearray([C, C, C])
neopixel_write(RGB, pixel_yellow)
# Create access to the three Buttons
BUTTON = [MPPio.BUTTON_20, MPPio.BUTTON_21, MPPio.BUTTON_22]
BUTTON_nn = [20, 21, 22] # aka [0, 1, 2]
for btns in range(3):
BUTT = DigitalInOut(BUTTON[btns])
BUTT.direction = Direction.INPUT
BUTT.pull = Pull.UP
BUTTON_nn[btns] = BUTT
# Define access to the six Grove Ports
print("\t\t Setup GROVE Ports.")
GROVE = [MPPio.GROVE_1, MPPio.GROVE_2, MPPio.GROVE_3, MPPio.GROVE_4, MPPio.GROVE_5, MPPio.GROVE_6]
GROVE_n = [0, 1, 2, 3, 4, 5, 6]
Qwiic70, Qwiic71, Qwiic72, Qwiic73 = False, False, False, False
GROVE4_ = [False, False, False, False, False, False, False, False, False, False]
GROVE4 = [0x29, 0x3c, 0x44, 0x50, 0x68, 0x70, 0x71, 0x72, 0x73, 0x76]
Flags_ = [LTR_Flag,OLED_Flag,SHT_Flag,FRAM_Flag,RTC_Flag,Qwiic70,Qwiic71,Qwiic72,Qwiic73,BME_Flag]
for ports in range(len(GROVE)): # set up & scan each port
try:
print("GROVE_"+str(ports+1)+" - I2C ports: ", end='= ')
_i2c = busio.I2C(*GROVE[ports])
while not _i2c.try_lock(): pass
print([hex(x) for x in _i2c.scan()])
for x in _i2c.scan():
for y in range(len(GROVE4)):
if GROVE4[y] == x: GROVE4_[y] = True
_i2c.unlock()
GROVE_n[ports+1] = _i2c
except(ValueError, RuntimeError, espatcontrol.OKError) as er:
print("GROVE#"+str(ports+1)+" -", er)
print(GROVE4)
print(GROVE4_)
simpleio.tone(BUZZER, KHz, 0.25)
# GROVE_n[x] port usages defined
I2C_Port4 = 4 ####
if LTR_Flag: ltr = LTR_329.LTR329(i2c=GROVE_n[I2C_Port4], address=0x29)
if OLED_Flag: oled = adafruit_ssd1306.SSD1306_I2C(128, 64, GROVE_n[I2C_Port4], addr=0x3c)
if SHT_Flag: sht = adafruit_sht4x.SHT4x(GROVE_n[I2C_Port4]) # address=0x44
if FRAM_Flag: FRAM50 = adafruit_fram.FRAM_I2C(GROVE_n[I2C_Port4], address=0x50, write_protect=False, wp_pin=None)
if RTC_Flag: rtc = adafruit_ds3231.DS3231(GROVE_n[I2C_Port4]) # address=0x68
if Qwiic_Flag: pass
if BME_Flag: bme280 = adafruit_bme280.Adafruit_BME280_I2C(GROVE_n[I2C_Port4], address=0x76)
# Qwiic 14 Segment Alphanumeric Display 0x70 >> 0x73
if Qwiic_Flag:
display_n = []
for n in range(4):
display_n.append(Qwiic(GROVE_n[I2C_Port4], address=0x70+n, brightness=1.0/2**6))
display_n[n].clear()
display_n[n].print(hex(0x70+n))
time.sleep(0.125)
time.sleep(1)
I2C_Port5 = 5 ####
if OLED_Flag:
oled.fill(0)
Left = 0 # 10=0-5 lines, 9=0-6 Lines, 8=0-7 7=0-8 Lines
Line = 9 # Pixels per line of text (lower number >>> more lines)
oled.text('______NTP Time______' , Left, Line*0, 1)
oled.text('GP20: Reboot' , Left, Line*1, 1)
oled.text('0x70: Year' , Left, Line*2, 1)
oled.text('0x71: Month Day.Ord' , Left, Line*3, 1)
oled.text('0x72: Hour:Min:Sec' , Left, Line*4, 1)
oled.text('0x73: Day Of Week' , Left, Line*5, 1)
if Line <= 9: oled.text(board.board_id, Left, Line*6, 1)
S = ((str(sys.implementation.version[0]))+":"+(str(sys.implementation.version[1]))+
':'+(str(sys.implementation.version[2])))
if Line <= 8: oled.text('CircuitPython: ' + S, Left, Line*7, 1)
if Line <= 7: oled.text('CircuitPython: ' + S, Left, Line*8, 1)
oled.show()
#$$$$
if PicoW_WiFi:
gc.collect()
led = digitalio.DigitalInOut(LED)
led.direction = digitalio.Direction.OUTPUT
if AP_List_Flag:
show = not True
X = 0
aps = []
# initialize comm
print("\fMy MAC addr:", [hex(i) for i in wifi.radio.mac_address])
# wifi scan
print("\tAvailable CYW43439KUBG WiFi networks:")
print(" Seq\tSSID\t\t Power\tChannel: No.")
for network in (wifi.radio.start_scanning_networks()):
s = "."*(18-len(str(network.ssid, "utf-8")))
if (len(s) == 0):
s = "...Hidden.SSID...."
else:
aps.append((network.ssid, network.rssi, network.channel))
X += 1
if show: print("%3d\t%s%sRSSI: %d\tChannel: %2d" % (X, str(network.ssid, "utf-8"), s,
network.rssi, network.channel))
wifi.radio.stop_scanning_networks()
network = []
show = not show
network = (sorted(aps, key=lambda x: x[1], reverse=True))
for snort in range(X):
#print(' ', snort+1, '\t', network[snort][0], '\t', network[snort][1], '\t', network[snort][2])
s = "."*(18-len(str(network[snort][0], "utf-8")))
if show: print("%3d\t%s%sRSSI: %d\tChannel: %2d" % (snort+1, str(network[snort][0], "utf-8"), s,
network[snort][1], network[snort][2]))
wifi.radio.connect(WIFI_SSID0, WIFI_PASSWORD0)
print("Hello World ~", WIFI_SSID0, '~', wifi.radio.ipv4_address, '~', wifi.radio.ipv4_subnet,
'\n\t\t\t', wifi.radio.ipv4_gateway, ' ~', wifi.radio.ipv4_dns)
print('\tBefore:', gc.mem_free(), end='')
network = None
app = None
gc.collect()
print(' ~ After:', gc.mem_free())
#$$$
if ESP_01_WiFi:
print("Setup ESP8266 - ESP-01 Module")
# Initialize UART/ESP-01 connection to the ESP8266 WiFi Module.
TX = MPPio.ESP_TX # GP16
RX = MPPio.ESP_RX # GP17
BUFFER_SIZE = int(1024 * 2) # 1=1024, 2=2048, 3=3072, 4=4096 Bytes
BAUDRATE = 115200
DEBUG = False
# Use a large buffer as we're not using hardware flow control.
uart = busio.UART(TX, RX, receiver_buffer_size=BUFFER_SIZE)
esp = espatcontrol.ESP_ATcontrol(uart, default_baudrate=BAUDRATE, debug=DEBUG)
requests.set_socket(socket, esp)
else:
print("*** No WiFi Module.")
raise
simpleio.tone(BUZZER, KHz, 0.25)
#$$$
if AP_List_Flag:
X = 1
print("\t\tScanning for ESP-01 WiFi Access Points.")
print("Seq\tECN\tSSID\t\t dBm\tMAC Address\t\tChan\tFoffs\tFcal")
#Field #0 is ECN, Field #1 is SSID, Field #2 is dBm, Field #3 is MAC Address, Field #4 is Chan
for ap in sorted(esp.scan_APs(), key=lambda x: x[2], reverse=True):
if(len(str(ap[1])) >= 18): ap[1] = ap[1][0:16] + '@'
S = ' '+"." * (16 - len(str(ap[1]))) + ' '
print("{0:2}\t{1:2}\t{2:}{3:}{4:}\t{5:}\t{6:3}\t{7:3}\t{8:}".format(X,ap[0],ap[1],S,ap[2],ap[3],ap[4],ap[5],ap[6]))
X += 1
print(" ECN = 0:OPEN 1:WEP 2:WPA_PSK 3:WPA2_PSK 4:WPA_WPA2_PSK 5:WPA2_Enterprise")
print('\tBefore:', gc.mem_free(), end='')
ap = None
gc.collect()
print(' ~ After:',gc.mem_free())
#aps.sort(key=lambda x: x[0], reverse=False)
if PicoW_WiFi:
_ = 0
print('Getting NTP Time.', end=' ')
flag = True
while flag:
pool = socketpool.SocketPool(wifi.radio)
request = requests.Session(pool, ssl.create_default_context())
ntp = adafruit_ntp.NTP(pool, tz_offset=-5, socket_timeout=2)
print(_, end=' ')
try:
ntp_time = ntp.datetime
if flag:
tm = ntp.datetime
print("\n\t%04d/%02d/%02d %02d:%02d:%02d %s %03d %02d" %((tm.tm_year), (tm.tm_mon), (tm.tm_mday),
(tm.tm_hour), (tm.tm_min), (tm.tm_sec), DoW[(tm.tm_wday+1)%7], (tm.tm_yday), (tm.tm_isdst)))
flag = False
except:
_ += 1
if _ > 10:
if not BUTTON_nn[0].value: supervisor.reload # Ctrl-C then Ctrl-D
elif not BUTTON_nn[1].value: microcontroller.reset # Power or Button Hard Reset
else: pass
time.sleep(0.1)
simpleio.tone(BUZZER, KHz, 0.25)
#$$$
time.sleep(0.25)
print("Resetting ESP8266 * ESP-01 module.")
esp.soft_reset()
time.sleep(0.25)
print("Socket Disconnect.")
esp.socket_disconnect()
time.sleep(0.25)
#
time.sleep(0.25)
####
Square = lambda x: x**2
CtoF = lambda x: (x*1.8)+32
FtoC = lambda x: (x-32)/1.8
KtoC = lambda x: x-273.15
KtoF = lambda x: CtoF(KtoC(x)) # (x-273.15)*1.8+32
####
def number_line():
print("0"*9+"1"*10+"2"*10+"3"*10+"4"*10+"5\n"+"1234567890"*5)
####
def play_melody(notes, duration):
for i in range(len(notes)):
simpleio.tone(BUZZER, notes[i], 1/duration[i])
####
def Beethovens_Fifth():
C = 6
_notes = [tones['A4'], 0, tones['A4'], 0, tones['A4'], 0, tones['C4']]
_duration = [C, C*2, C, C*2, C, C*2, C/4]
play_melody(_notes, _duration)
####
def ds3231_ReadTime1():
if not RTC_Flag: return(None)
try:
return(rtc.datetime)
except:
return(None)
####
def ds3231_WriteTime1(t):
if not RTC_Flag: return(None)
try:
rtc.datetime = t
return(ds3231_ReadTime1())
except:
return(None)
####
def Board_UID():
print(f"\t\b\bCircuit Python ID: %s" % board.board_id)
UID = (microcontroller.cpu.uid) # (str(network.ssid, "utf-8"))
_UID_ = ''
for x in range(8):
if (len(hex(UID[x])[2:4]) < 2): _UID_ += "0"
_UID_ += hex(UID[x])[2:4]
if x%2: _UID_ += " "
print(f" Microcontroller UID: %s" % _UID_.upper())
####
def Z_to_L(hours, Clock):
if (Clock != "24"):
if hours >= 12:
hours -= 12 # hours = hours%12
Clock = "PM"
if not hours: hours = 12
else:
Clock = "AM"
return(hours, Clock)
####
def ds3231_rtc(Clock):
if not RTC_Flag: return(None)
global a, b, c, d, e, f, g, h, i
now = ds3231_ReadTime1()
a = now.tm_year # Year
b = now.tm_mon # Month
c = now.tm_mday # Day of Month
d = now.tm_hour # Hours_24
e = now.tm_min # Minute
f = now.tm_sec # Second
g = now.tm_wday # Day of Week 1-7
h = now.tm_yday # Day of Year -1=N/A
i = now.tm_isdst # is DST -1=N/A
holiday(b, c) # Month, Day of Month
hours = d
hours, Clock = Z_to_L(hours, Clock)
l = ("{} {}, {} {:02}:{:02}:{:02} {} {} DS3231".format(Month[b], c, a, hours, e, f, Clock, DoW[g]))
for n in range(len(l)/2):
if l[n:n+1] == ":": break
n -= 15
print(' '*n + l)
r = rtc.temperature
print(f"\t\b\b\b\b DS3231 Temperature: %0.2f°C\t%0.2f°F" % (r, CtoF(r)))
return(now)
####
def holiday(b, c): # Month, Day of Month
if (b == 1): January(c)
elif (b == 2): February(c)
elif (b == 3): March(c)
elif (b == 4): April(c)
elif (b == 5): May(c)
elif (b == 6): June(c)
elif (b == 7): July(c)
elif (b == 8): August(c)
elif (b == 9): September(c)
elif (b == 10): October(c)
elif (b == 11): November(c)
elif (b == 12): December(c)
else: print('WTF')
####
def January(c): # 1
if (c == 1): print('\t\t***** New Years Day *****')
def February(c): # 2
if (c == 2): print('\t\t** Groundhog Day 700cc **')
elif (c == 14): print('\t\t**** Valentines Day ****')
def March(c): # 3
if (c == 17): print('\t\t** St. Patrick\'s Day **')
elif (c == 25): print('\t\t* Happy Birthday Bruce *')
elif (c == 27): print('\t\t** Happy Birthday Todd **')
def April(c): # 4
if (c == 1): print('\t\t**** April Fools Day ****')
def May(c): # 5
if (c == 5): print('\t\t***** Cinco de Mayo *****')
def June(c): # 6
if (c == 19): print('\t\t****** Jumeteenth ******')
def July(c): # 7
if (c == 4): print('\t\t*** Independance Day ***')
elif (c == 26): print('\t\t** Happy Birthday Ben **')
def August(c): # 8
if (c == 10): print('\t\t* Happy Birthday Jackie *')
elif (c == 23): print('\t\t* Happy Birthday Aaron *')
def September(c): # 9
pass
def October(c): # 10
if (c == 31): print('\t\t******* Holloween *******')
def November(c): # 11
if (c == 11): print('\t\t***** Armistis Day *****')
def December(c): # 12
if (c == 7): print('\t\t*** Pearl Harbor Day ***')
elif (c == 12): print('\t\t****** Anniversary ******')
elif (c == 23): print('\t\t******* Festivus *******')
elif (c == 24): print('\t\t***** Christmas Eve *****')
elif (c == 25): print('\t\t***** Christmas Day *****')
elif (c == 31): print('\t\t***** New Years Eve *****')
####
def CPU_Temp():
print(f" *********** CPU: Temperatures and Device Status ***********")
for i in range(2):
cpu_C = microcontroller.cpus[i].temperature
print(f"\t\t CPU(%d): %3.2f°C\t%3.2f°F" % (i, cpu_C, CtoF(cpu_C)))
if Board == 'Pico':
print(f"\tVOLTAGE_MONITOR: %s" % str(VMon.value)) # GP23
print(f"\t SMPS_MODE: %s" % str(SMPS.value)) # GP24
print(f"\t VBUS_SENSE: %s" % str(VBUS.value)) # GP25
####
def SHT_40():
if not SHT_Flag: return
print(f" *************** SHT40: Environment Readings **************")
print(f"Found SHT4x with serial number:", hex(sht.serial_number))
# Can also set the mode to enable heater
# sht.mode = adafruit_sht4x.Mode.LOWHEAT_100MS
sht.mode = adafruit_sht4x.Mode.NOHEAT_HIGHPRECISION
print(f"\tCurrent mode is: ", adafruit_sht4x.Mode.string[sht.mode])
temperature, relative_humidity = sht.measurements
dewpoint = dewpoint(temperature, relative_humidity) # Calculated
print(f"\t Temperature: %0.2f°C\t%0.2f°F" % (temperature, CtoF(temperature)))
h = ' ' if relative_humidity < 10 else ''
print(f"\t\t\bHumidity:%s %0.1f %%" % (h, relative_humidity))
u = ' ' if dewpoint < 10 else ''
print(f"\t\t\b\bDew Point:%s %0.2f°C\t%0.2f°F" % (u, dewpoint, CtoF(dewpoint)))
####
def BME_280():
global Sea_Level, First_OWM
if not BME_Flag: return
# Local Weather Source hPa/mB https://forecast.weather.gov/MapClick.php?lat=38.97&lon=-76.49
# USNA, Annapolis, MD https://api.weather.gov/gridpoints/LWX/115,78/forecast
if((not (time.time() % (5*60))) or First_OWM): Sea_Level = Annapolis(Sea_Level)
bme280.sea_level_pressure = Sea_Level # hPa @ Annapolis, MD
t_off_set = -3.75
h_off_set = 6.25
t = bme280.temperature + t_off_set
h = bme280.humidity + h_off_set
d = dewpoint(t, h) # Calculated
p = bme280.pressure
a = bme280.altitude
u = ''
if d < 10: u = ' '
print(f" *************** BME280: Environment Readings **************")
print(f"\t Temperature: %0.2f°C\t%0.2f°F" % (t, CtoF(t)))
print(f"\t\t\bHumidity: %0.1f%%\t\t%0.1f%%" % (h, h))
print(f"\t\t\b\bDew Point:%s %0.2f°C\t%0.2f°F" % (u, d, CtoF(d)))
print(f"\t Heat Index: %0.2f°C\t%0.2f°F %s" % (heat_index(t, h)))
print(f" Barometric Pressure: %0.2f hPa\t%0.2f mmHg\tUSNA: %0.1f hPa" % (p, p/33.8638867, Sea_Level))
print(f"\t Altitude: %0.2f Meters\t%0.2f Feet" % (a, a*3.28))
if Pi_e: print(f" ********** Constants: Pi = " + str(math.pi) + ",\te = " + str(math.e)+" **********")
####
def dewpoint(C, H): # Calculated
c1 = 17.62
c2 = 243.15
gamma = ((c1 * C) / (c2 + C)) + math.log(H / 100.0)
dp = (c2 * gamma) / (c1 - gamma)
return(dp)
####
def heat_index(t, h): # aka Chill Factor, Feels Like
# Formula Source https://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
T = CtoF(t) # Convert to Fahrenheit
RH = h # RH Relative Humidity, HI Heat Index
HI = 0.5 * (T + 61.0 + ((T - 68.0) * 1.2) + (RH * 0.094))
s = "Standard"
if HI > 80:
c1,c2,c3,c4,c5 = -42.379, 2.04901523, 10.14333127, 0.22475541, 0.00683783
c6, c7, c8, c9 = 0.05481717, 0.00122874, 0.00085282, 0.00000199
Tsq = Square(T)
RHsq = Square(RH)
HI = c1 + c2*T + c3*RH - c4*T*RH - c5*Tsq - c6*RHsq + c7*Tsq*RH + c8*T*RHsq - c9*Tsq*RHsq
s = " detailed "
if RH < 13 and T > 85: # Subrtact from HI
HI -= ((13-RH)/4)*sqrt((17-abs(T-95.))/17)
s = s + "adjusted - low"
if RH > 85 and (T >= 80 and T <= 87): # Add to HI
HI += ((RH-85)/10) * ((87-T)/5)
s = s + " adjusted - high"
return(FtoC(HI), HI, s)
####
def read_FRAM(adr): # 4 Byte Intiger
#print(adr)
if(adr % int_size): return(None)
num = 0
for i in range(int_size):
b = 3 - i
num *= 0x100
num += (FRAM50[b+adr][0])
#print(i, FRAM50[b+adr][0])
return(num)
####
def write_FRAM(adr, val): # 4 Byte Intiger
#print(adr,val)
if(adr % int_size): return(None)
for i in range(int_size):
num = val & 0xFF
#print(i, num)
FRAM50[i+adr] = num
val = int(val/0x100)
return(num)
####
def inc_FRAM(adr):
val = read_FRAM(adr)
val += 1
write_FRAM(adr, val)
return(read_FRAM(adr))
####
def FRAM_test():
if False:
write_FRAM(Loops, 0) # \ Reset the counters
write_FRAM(this_run, 0)
write_FRAM(Starts, 0) # /
inc_FRAM(Loops)
inc_FRAM(this_run)
print("\t\b\bLoops/Runs/Starts: {:,}/{:,}/{:,} ~ FRAM: {}".format (read_FRAM(Loops), read_FRAM(this_run),
read_FRAM(Starts), len(FRAM50)))
if FRAM_Full:
values = list(range(128)) # or bytearray or tuple
FRAM50[0:128] = values
print("\t\b\b\b\b",end='')
print(FRAM50[ 0:32])
print("\t\b\b\b\b",end='')
print(FRAM50[32:64])
print("\t\b\b\b\b",end='')
print(FRAM50[64:96])
print("\t\b\b\b\b",end='')
print(FRAM50[96:128])
print("\t\b\b\b\b",end='')
print(FRAM50[128:144])
print("\t\b\b\b\b",end='')
print(FRAM50[65], "#", FRAM50[65][0], "#", chr(FRAM50[65][0]))
print(FRAM50[152:170])
time.sleep(100)
####
def ltr_329():
# Can set the ALS light gain, can be: 1, 2, 4, 8, 48 or 96 times
# to range from 1~64 kLux to 0.01~600 Lux
ltr.als_gain = 8 # 1 Default
# Can set the ALS measurement integration time, how long the sensor
# 'looks' for light data. Default is 100ms.
# Set to: 50, 100, 150, 200, 250, 300, 350, or 400 millisec
ltr.integration_time = 100 # 100 Default
# Can set the ALS measurement rate, how often the data register updates
# Default is 500ms. Must be equal or greater than the integration time
# Set to: 50, 100, 200, 500, 1000, 2000 millisec
ltr.measurement_rate = 500 # 500 Default
print("\t\bLTR-329 ALS gain: "+str(ltr.als_gain)+', ', end='')
print("Integration Time: "+str(ltr.integration_time)+'ms, ', end='')
print("Measurement Rate: "+str(ltr.measurement_rate)+'ms')
# The sensor will let us know when the measurement time has
# created a new data reading!
if ltr.new_als_data_available:
# The sensor can get 'overwhelmed' by bright light if the
# gain isn't set right, in which case the data is invalid.
# We can check the data invalid first and toss out the reading...
# we can also check `ltr329.als_data_invalid` if we want, to verify the data
if ltr.als_data_invalid:
ltr.throw_out_reading() # perform & toss out the reading
print("LTR-329 ALS Data Invalid")
time.sleep(0.1)
# OR we can 'try' to do the read and get an exception if the data is invalid
try:
# If we're using `new_als_data_available` we should read both channels ONCE only! To do that use;
visible_plus_ir, ir_lux = ltr.light_channels
# this will get both channels at once! (It's also faster)
# Now we can do various math...
visible_lux = visible_plus_ir - ir_lux
print(" Visible+IR: %d lux = IR: %d lux + Visible: %d lux" % (visible_plus_ir, ir_lux, visible_lux))
return(visible_plus_ir, ir_lux, visible_lux)
except ValueError:
print("Light sensor data invalid, trying again!")
return(0, 0, 0)
####
def Ping():
st = ['Yahoo', ' ', 'Google', ' ', 'Verizon', '', 'Amazon', ' ']
st_ = int(len(st)/2)
s = (seconds%st_)*2
n = st[s+1]
s_ = st[s] + '.com'
try:
info = pool.getaddrinfo(s_, 80)
addr = info[0][4][0]
#print(f"\t\b{n}{s_}'s IP: {addr}")
ipv4 = ipaddress.ip_address(addr)
result_ms = wifi.radio.ping(ipv4)
if result_ms:
print("\t\b%sPing %s: %s ~ %.0f ms" % (n, s_, addr, result_ms*1000))
else:
print("\t\bNo response from: "+s_)
result_ms = 1001
except:
result_ms = 1000
return(result_ms)
####
def connect_wifi():
try:
print("Connecting...")
flag = False
while not flag:
try:
print(WIFI_SSID, WIFI_PASSWORD)
esp.connect(WIFI_SSID, WIFI_PASSWORD)
flag = True
except:
supervisor.reload() #SoftReload('Connect Fail', 1)
print("Connected!...")
time.sleep(0.25)
p = esp.ping(MODEM_IP)
print("Ping round trip time: " + str(p) + "ms")
internet = True
if playMario: Mario()
except(ValueError, RuntimeError, espatcontrol.OKError) as er:
print("Failed, retrying\n", er)
internet = False
return(internet)
####
def print_wifi():
print("\t ESP-01 WiFi IP:", esp.local_ip)
print("\t Pico W Wifi IP:", wifi.radio.ipv4_address)
####
def HTTP():
TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"
af_requests = requests.Session(pool)
print("Fetching text from %s" % TEXT_URL)
try:
response = af_requests.get(TEXT_URL)
except:
print(response.text)
print("Text Response: ", response.text)
response.close()
return()
####
def play(tune):
for Note in tune: simpleio.tone(BUZZER, Note, 0.25)
####
def FirstBar(): play((tones['Gs4'], tones['Fs4'], tones['E4' ], tones['B3']))
def SecondBar(): play((tones['E4' ], tones['Gs4'], tones['Fs4'], tones['B3']))
def ThirdBar(): play((tones['E4' ], tones['Fs4'], tones['Gs4'], tones['E4']))
def ForthBar(): play((tones['Gs4'], tones['E4' ], tones['Fs4'], tones['B3']))
def FifthBar(): play((tones['B3' ], tones['Fs4'], tones['Gs4'], tones['E4']))
####
def Minutes15():
FirstBar()
def Minutes30():
SecondBar()
time.sleep(0.25)
ThirdBar()
def Minutes45():
ForthBar()
time.sleep(0.25)
FifthBar()
time.sleep(0.25)
FirstBar()
def Minutes00():
SecondBar()
time.sleep(0.25)
ThirdBar()
time.sleep(0.25)
ForthBar()
time.sleep(0.25)
FifthBar()
####
def Mario():
_ = 0.125
for note in range(len(mario)):
if mario[note] == '0': time.sleep(_)
else: simpleio.tone(BUZZER, tones[mario[note]], _)
return(True)
####
def chime(hour, min, sec):
hour = hour % 12
if(not hour): hour = 12
if((sec <= hour) and (min == 0)):
simpleio.tone(BUZZER, 220)
time.sleep(0.25)
####
def SoftReload(text='Soft', btn=0, ts=5):
print(text+' ~ Reload')
Beethovens_Fifth()
for x in range(ts):
print('\t'+str(ts-x), end=' \r')
time.sleep(1)
print('\t'+'0', end='\r')
if btn == 3: supervisor.reload() # Ctrl-C then Ctrl-D
elif BUTTON_nn[0].value: supervisor.reload() # Ctrl-C then Ctrl-D
elif BUTTON_nn[1].value: microcontroller.reset() # Power or Button Hard Reset
elif BUTTON_nn[2].value: pass
else: pass
####
def Annapolis(bp):
global First_OWM
#return(1015.0)
TEXT_URL = (URL + CITY_ZIP + ZIP + OWM_KEY + OWM_TOKEN)
print("Fetching weather from", URL + CITY_ZIP + ZIP, '\n')
# if True:
try:
req = requests.get(TEXT_URL, timeout=5) # Try to get data from OWM (Open Weather Map)
txt = req.text
if True:
spt = []
spt = txt.split(',')
for _ in range(len(spt)):
_spt = []
_spt = spt[_].split(':')
if _spt[0] == '"pressure"':
bp = float(int(_spt[1]))
break
First_OWM = False
spt = []
txt = None
gc.collect()
else:
print(txt)
#weather = json.loads(txt)
print(txt["main"]["pressure"])
bp = (txt["main"]["pressure"])
req.close()
# else:
except: # RuntimeError as err:
print("Could not connect to OWM, rebooting: ") #, err)
print("***************************** Exception Rebbot *****************************")
#supervisor.set_next_code_file('NTP_Clock_code.py')
#supervisor.reload() # Ctrl-C then Ctrl-D
return(bp)
#####
# End of Definitions, Start of Main Program
write_FRAM(this_run, 0)
if playMario: Mario()
else:
play((tones['A4'], tones['F4'], tones['G4'], tones['C4']))
time.sleep(0.5)
play((tones['C4'], tones['G4'], tones['A4'], tones['F4']))
time.sleep(0.5)
gc.collect()
open_mem = gc.mem_free()
inc_FRAM(Starts)
print("*\t*\tOpen Memory: {} Starts/Restarts: {:,}".format (open_mem, read_FRAM(Starts)))
def Main():
global request_time, prev_scnds, seconds, setTime, Clock, prev_minutes
global prev_mday, prev_year, display_date, current_time, time_offset
global wday, month, yday, JSON, hours_24, Day_of_week, isdst
#global hours, scnds, minutes, mday, year, internet
if request_time:
for i in range(5): # Try five times
print("\nTry #" + str(i+1) + " of Connect/Get Data loop. (top)")
if not esp.is_connected: # Check if WiFi is still working
for i in range(3): # Try 3 times
internet = connect_wifi()
try:
time.sleep(0.1)
p = esp.ping(MODEM_IP)
print("Ping round trip time: " + str(p) + "ms")
if p == 'None': SoftReload('Ping Fail', 3, 15) # Nonems
print("Getting DTG from: " + DTG_API)
try:
response = requests.get(DTG_API)
JSON = response.json()
# UnixTime - SysTime + TZ Offset + DST Offset
time_offset = (JSON["unixtime"]-time.time()+JSON["raw_offset"]+(JSON["dst_offset"]))
except:
SoftReload('get DTG Fail', 3, 15)
print("Got ... DTG")
Day_of_week = JSON['day_of_week']
print(JSON["utc_datetime"], "UTC")
print(JSON["datetime"], JSON["abbreviation"])
print(JSON["dst_from"], "DST Starts")
print("\t\t\t ", JSON["abbreviation"], "Time Zone")
print(JSON["dst_until"], "DST Stops")
request_time = False
internet = True
time.sleep(0.1)
break
except(ValueError, RuntimeError, espatcontrol.OKError) as er:
print("Failed, Retrying,\nError: ", er)
print("Resetting ESP8266 * ESP-01 module.")
esp.soft_reset()
print("Socket Disconnect.")
esp.socket_disconnect()
Beethovens_Fifth()
print("End of try #" + str(i+1) + " Connect/Get Data loop.")
time.sleep(10)
internet = False
try:
current_time = time.time() + time_offset
except:
SoftReload('Get Time Fail', 3, 10)
now = time.localtime(current_time)
scnds = now.tm_sec
led.value = False
if scnds != prev_scnds: # Skip the following code until seconds changes
led.value = True
prev_scnds = scnds
try:
year = now.tm_year
month = now.tm_mon
mday = now.tm_mday
yday = now.tm_yday
hours_24 = now.tm_hour
minutes = now.tm_min
seconds = now.tm_sec
isdst = now.tm_isdst
wday =(now.tm_wday+1)%7
_ = 25
R = random.randrange(_)
G = random.randrange(_)
B = random.randrange(_)
RND = bytearray([R,G,B])
neopixel_write(RGB, RND)
except:
SoftReload('get Time Fail', 3, 7)
#Check if we should reboot
if(not BUTTON_nn[0].value):
SoftReload('Button 20 Pushed', 0)
print('\f', end='')
#Display Date, Time, Day on 14 segment displays
S = "0" if seconds < 10 else "" # Leading Zero for numbers less than 10
if (not seconds % 2) : S = ":" + S # flash colon (OFF for Odd numbers)
if (not seconds % 2) and setTime: S = S[1:] # len(S)-1
gc.collect()
print("\t\t\t {:,}".format (gc.mem_free()))
hours = hours_24
hours, Clock = Z_to_L(hours, Clock)
if Clock != "24":
S3 = S + str(seconds) + Clock # Seconds AM/PM
else:
S3 = S + str(seconds) + DoW[wday][0:2].upper() # Seconds & first two letters of day
if Qwiic_Flag: display_n[3].print(S3)
if(prev_minutes != minutes):
prev_minutes = minutes
if Qwiic_Flag:
S = ":0" if (minutes < 10) else ":"
S2 = str(hours) + S + str(minutes)
display_n[2].print(S2)
if(prev_mday != mday):
prev_mday = mday
if Qwiic_Flag:
S = " " if (minutes < 10) else ""
S1 = str(month) + S + str(mday)
display_n[1].print(S1)
if(prev_year != year):
prev_year = year
if Qwiic_Flag:
S0 = str(year)
display_n[0].print(S0)
#Create REPL string
if(hours_24 == 2 and minutes == 0 and seconds == 0): request_time = True # 2:00 AM
#hours = hours_24
#hours, Clock = Z_to_L(hours, Clock)
ds3231_rtc(Clock) # Get time from DS3231 RTC clock chip and print to REPL.
s = " " * (11 - int(len(DoW[wday])))
print(" {}{}, {:02}/{:02}/{:04} {:02}:{:02}:{:02} {} {}, {:03}~Julian".format(s, DoW[wday],
month, mday, year, hours, minutes, seconds, Clock, JSON["abbreviation"], yday))
# Show the CPU temperatures
if TickTock:
#Play Seconds and Hourly Alerts
KHz = 1000
if not (minutes + seconds): ToneTime = 0.25 # Long Tick at each hour if not Wesminster
elif minutes == 59 and seconds >= 55: ToneTime = 0.05 # Medium Tick for seconds 55 >>> 59 before hour
elif not seconds: ToneTime = 0.01 # Short Tick at each minute
else:
ToneTime = 0.005 # Tick at each second
KHz = 500 if seconds%2 else 2000
simpleio.tone(BUZZER, KHz, ToneTime)
if Westminster: # Play Westminster chimes every 1/4 hour
if minutes == 0 and seconds == 0: Minutes00() # On the Hour
elif minutes == 15 and seconds == 0: Minutes15() # On the 1/4 Hour
elif minutes == 30 and seconds == 0: Minutes30() # On the 1/2 Hour
elif minutes == 45 and seconds == 0: Minutes45() # On the 3/4 Hour
else: pass
else: pass
if Chime_Flag: chime(hours, minutes, seconds)
# Go Show the Board Environment
if CPU_Flag : Board_UID() ##
if WiFi_Flag: print_wifi()##
if CPU_Flag : CPU_Temp() ##
if SHT_Flag : SHT_40() ##
if BME_Flag : BME_280() ##
if LTR_Flag : ltr_329() ##
if PING_Flag: Ping() ##
if HTTP_Flag: HTTP() ##
if FRAM_Flag: FRAM_test() ##
#Check if we are connected to WiFi
interval = 30
if (minutes%interval == 0 or minutes == 0) and seconds == 0 and display_date == True:
print(str(interval) + " Minute Time Check.")
display_date = False
prev_minutes = minutes
if not esp.is_connected: # Check if WiFi is still working
for i in range(3): # Try 3 times
internet = connect_wifi()
else:
if minutes == prev_minutes and display_date == False:
display_date = True
if RTC_Flag:
tm_ = time.struct_time((year, month, mday, hours_24, minutes, seconds, Day_of_week, yday, isdst))
if((seconds != f) or (minutes != e)): # Adjust DS3231 if off by +/-1 second or more
setTime = True
if(seconds > f):
tm_ = time.struct_time((year, month, mday, hours_24, minutes, (seconds+1 )%60, Day_of_week, yday, isdst))
if(seconds < f):
tm_ = time.struct_time((year, month, mday, hours_24, minutes, (seconds+59)%60, Day_of_week, yday, isdst))
ds3231_WriteTime1(tm_)
print(" DS3231 reset.", minutes, seconds, e, f)
else:
setTime = False
if OLED_Flag:
offset = 1
flip = not minutes % 2
oled.fill(not flip)
oled.text('______NTP Time______0', Left, Line*0, flip)
oled.text('GP20: Reboot', Left, Line*1, flip)
oled.text('0x70: '+ S3, Left, Line*2, flip)
if mday >= 11 and mday <= 13: ordinal = "th"
elif mday % 10 == 0: ordinal = "th"
elif mday % 10 == 1: ordinal = "st"
elif mday % 10 == 2: ordinal = "nd"
elif mday % 10 == 3: ordinal = "rd"
elif mday % 10 >= 4: ordinal = "th"
else: ordinal = "wtf"
oled.text('0x71: '+ Month[month]+" "+str(mday)+ordinal, Left, Line*3, flip)
sec = seconds + offset
s1 = '0' if(sec < 10 or sec == 60) else ''
S = ":0" if (minutes < 10) else ":"
S2 = str(hours) + S + str(minutes)
oled.text('0x72: ' + S2+':' + s1 + str(sec%60), Left, Line*4, flip)
oled.text('0x73: ' + DoW[wday] , Left, Line*5, flip)
oled.text(board.board_id, Left, Line*6, flip)
oled.show()
First = False
####
while True:
#if True:
try:
Main()
#else:
except:
print('\tWe have crashed (5 sec)!')
#traceback.print_exception()
time.sleep(5)
#microcontroller.reset # Power or Button Hard Reset
supervisor.reload # Ctrl-C then Ctrl-D
_ = time.time()
while time.time() == _ : pass
# The End!