So, the basics of this project is to obtain temperature data from an API for an industrial oven on the same network as the pico W, and then display that output to a multiplexed 4 digit, 7 segment display. I've been doing this through urequests, and ujson, and using _thread to run both the retrieval of temperature data, and run the multiplexing of the 4 digit 7 segment display as well.
This all works great, however, I keep getting to a point where randomly, the temperature data will freeze (although the API is still accessible, and updating appropriately), so it ends up just holding the last gathered temp on the display and multiplexing it until the board is unplugged, where it will then reconnect, and continue for hours sometimes before it fails and freezes the temp again.
I believe this is either a urequests issue, or a network issue, and I've tried to implement exceptions (this is running without anyway of seeing what gets logged, besides some symbols on the 7 segment display, and have never gotten it to freeze while connected to PC.) but the exceptions don't resolve or give light into whats actually going on when the temp data freezes.
Here is the code:
from machine import Pin
import _thread
import utime as time
import network
import urequests as requests
import ujson as json
led = Pin("LED", Pin.OUT)
displaydash = Pin(8, Pin.OUT) #dashpin -
display_list = [2, 3, 4, 5, 6, 7, 8] #a, b, c, d, e, f, g segments
colonpin = Pin(9, Pin.OUT)
display_obj = [] #to create the display object
dig1 = Pin(10, Pin.OUT) #digit 1
dig2 = Pin(11, Pin.OUT)
dig3 = Pin(12, Pin.OUT)
dig4 = Pin(13, Pin.OUT) #digit 4
global temp
temp = 0
for seg in display_list:
display_obj.append(Pin(seg, Pin.OUT))
arrSeg = [[1,1,1,1,1,1,0], # -> arrSeq[0] displays 0
[0,1,1,0,0,0,0], # -> arrSeq[1] displays 1
[1,1,0,1,1,0,1], # -> arrSeq[2] displays 2
[1,1,1,1,0,0,1], # -> arrSeq[3] displays 3
[0,1,1,0,0,1,1], # -> arrSeq[4] displays 4
[1,0,1,1,0,1,1], # -> arrSeq[5] displays 5
[1,0,1,1,1,1,1], # -> arrSeq[6] displays 6
[1,1,1,0,0,0,0], # -> arrSeq[7] displays 7
[1,1,1,1,1,1,1], # -> arrSeq[8] displays 8
[1,1,1,1,0,1,1]] # -> arrSeq[9] displays 9
def SegDisplay(toDisplay):
numDisplay = int(toDisplay.replace(".", ""))
for a in range(7):
display_obj[a].value(arrSeg[numDisplay][a])
if toDisplay.count("-") == 1:
Pin(3,Pin.OUT).value(1)
else:
colonpin.value(0)
def clear(): #sets all display output pins to zero
Pin(2, Pin.OUT).value(0)
Pin(3, Pin.OUT).value(0)
Pin(4, Pin.OUT).value(0)
Pin(5, Pin.OUT).value(0)
Pin(6, Pin.OUT).value(0)
Pin(7, Pin.OUT).value(0)
Pin(8, Pin.OUT).value(0)
Pin(9, Pin.OUT).value(0)
colonpin.value(0)
def error(): #displays EEEE
clear()
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
Pin(9, Pin.OUT).value(0)
Pin(8,Pin.OUT).value(1)
Pin(7,Pin.OUT).value(1)
Pin(6,Pin.OUT).value(1)
Pin(5,Pin.OUT).value(1)
Pin(2,Pin.OUT).value(1)
dig1.value(0)
dig2.value(0)
dig3.value(0)
dig4.value(0)
def dash(): #displays ----
clear()
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
Pin(9, Pin.OUT).value(0)
Pin(8,Pin.OUT).value(1)
dig1.value(0)
dig2.value(0)
dig3.value(0)
dig4.value(0)
def outside_dash(): #displays - -
clear()
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
Pin(9, Pin.OUT).value(0)
Pin(8,Pin.OUT).value(1)
dig1.value(0)
dig2.value(1)
dig3.value(1)
dig4.value(0)
def display():
refresh = 0.0025
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
while True:
global temp
value = temp
if value != None or value != 9998 or value != 9999:
try:
value = float(value)
value = int(value) #not rounding, just getting whole number.
value = str(value)
if len(value)==1:
pl1 = "0"
pl2 = "0"
pl3 = "0"
pl4 = value[0]
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
SegDisplay(pl4)
dig4.value(0)
time.sleep(refresh)
dig4.value(1)
elif len(value)==2:
pl1 = "0"
pl2 = "0"
pl3 = value[0]
pl4 = value[1]
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
SegDisplay(pl3)
dig3.value(0)
time.sleep(refresh)
dig3.value(1)
SegDisplay(pl4)
dig4.value(0)
time.sleep(refresh)
dig4.value(1)
elif len(value)==3:
pl1 = "0"
pl2 = value[0]
pl3 = value[1]
pl4 = value[2]
dig1.value(1)
dig2.value(1)
dig3.value(1)
dig4.value(1)
SegDisplay(pl2)
dig2.value(0)
time.sleep(refresh)
dig2.value(1)
SegDisplay(pl3)
dig3.value(0)
time.sleep(refresh)
dig3.value(1)
SegDisplay(pl4)
dig4.value(0)
time.sleep(refresh)
dig4.value(1)
time.sleep(refresh)
elif len(value)==4:
pl1 = value[0]
pl2 = value[1]
pl3 = value[2]
pl4 = value[3]
SegDisplay(pl1)
dig1.value(0)
time.sleep(refresh)
dig1.value(1)
SegDisplay(pl2)
dig2.value(0)
time.sleep(refresh)
dig2.value(1)
SegDisplay(pl3)
dig3.value(0)
time.sleep(refresh)
dig3.value(1)
SegDisplay(pl4)
dig4.value(0)
time.sleep(refresh)
dig4.value(1)
except:
dash()
time.sleep(1)
pass
elif value == None or value == 9999:
dash()
time.sleep(1)
elif value == 9998:
error()
time.sleep(1)
def connect():
#Connect to WLAN
clear()
ssid = "networkname" #set up wifi network
password = 'password' #set up wifi password
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.config(pm = 0xa11140)
wlan.connect(ssid, password)
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('Waiting for connection...')
led.on()
time.sleep(.5)
led.off()
time.sleep(.5)
# Handle connection error
if wlan.status() != 3:
raise RuntimeError('Network connection failed')
error()
led.off()
else:
led.on()
print('Connected')
status = wlan.ifconfig()
print( 'IP = ' + status[0] )
def get_temp():
temp_url = "the api url goes here"
while True:
global temp
wlan = network.WLAN(network.STA_IF)
if wlan.status() != 3: #check if connected first
led.off()
print("Lost connection")
temp = wlan.status()
connect()
time.sleep(0.25)
elif wlan.status() == 3:
try: #get temp if connected
r = requests.get(temp_url).json()
temp = r.get('ispoint')
time.sleep(1)
except: #if requests fail, reset
print("Couldn't gather data")
temp = wlan.status()
outside_dash()
print(wlan.status())
machine.reset()
break
connect() #connect to wifi first
_thread.start_new_thread(display, ()) #start the display thread
get_temp()
I have been doing a lot of shuffling and testing of this code, so it's not complete in regards to how everythings packed up and laid out for now, but as I said, this works, and gathers the temp correctly and multiplexes it on the 4 digit 7 segment display well, but I just can't seem to figure out why the temp value keeps freezing after so long. I tried to implement an exception in get_temp to machine.reset() if for some reason requests.get didn't respond (which is what I thought was happening) but that didn't happen when it ran into the issue today. I also tried to add a part in get_temp to monitor wlan.status() for any disconnects, and that also has never happened. The end symptom of the fault is just an endless looping in display() of a frozen temp value. I also plan to use a different method of storing the temp once I can figure out this issue as oppose to a global variable, but for testing it was the only thing I'd gotten to work well thus far.
UPDATE HERE: I actually just noticed that it did eventually start to work again, but this was at least an hour or more after it initially froze, while I know for certain the API was reachable and providing data. Didn't see the actual restart to know if it did a full reset, or if it just started working, unfortunately, so still don't know the exact issue, but still assuming a network, requests issue.