Pico W Micro Python for SHT30 Temp/Humidity HELP!

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Rissy
Posts: 113
Joined: Sun Aug 14, 2022 8:15 am

Re: Pico W Micro Python for SHT30 Temp/Humidity HELP!

Post by Rissy » Mon Nov 21, 2022 6:19 pm

Well, now that it's been raining quite heavily during the past 16hrs or so, it was inevitable that my SHT30 device would eventually fail because of it. It seems actually that it's failed on quite a few occassions, and it seems that my program is not as hardy against this as I'd thought. I now have a string of errors in my errorlog.txt file i'd like to share with you all.

Errorlog.txt file contents since last post:

Code: Select all

MQTT Error: [Errno 113] EHOSTUNREACH
MQTT Error: [Errno 113] EHOSTUNREACH
MQTT Error: [Errno 107] ENOTCONN
SHT Error: Bus error
SHT Error: Bus error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: Bus error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: CRC error
SHT Error: Bus error
This was my program at the time of these errors:

Code: Select all

#Necessary library imports for this code to function
from secrets import SSID
from secrets import PASSWORD
from secrets import IP
from secrets import IP_mask
from secrets import IP_gateway
from secrets import IP_DNS
from secrets import MQTTSERVE
from umqtt.simple import MQTTClient
import time
import network
import ubinascii
import socket
from machine import I2C, Pin, #wdt
import sht30
from sht30 import SHT30
from sht30 import SHT30Error

led = machine.Pin("LED", machine.Pin.OUT)

#initialise LED to OFF
led.off()

# def appendfile(message, error):
#     file=open("errorlog.txt","a")
#     errorstring=str(error)
#     file.write(message)
#     file.write(errorstring)
#     file.write("\n")
#     file.close()
    #file.flush()
    
def appendfile(message, error):
   with open('errorlog.txt', 'a') as file:
       file.write(message)
       errorstring=str(error)
       file.write(errorstring)
       file.write('\n')
       file.close()

def sht_error(ex):
    print("something went wrong reading the SHT-30!")
    print('Error:', ex)
    message = 'SHT Error: '
    appendfile(message, ex) #message, error
    
#Define the interface of the SHT30 Temp/Humidity sensor with the Pico W
i2c=I2C(0, sda=Pin(4), scl=Pin(5), freq=5000)
sht=sht30.SHT30(i2c=i2c, i2c_address=68)

def readsensor():
    global temperature
    global humidity
    try:
        sensor = sht.measure()
    except SHT30Error as ex:
        #print(ex)
        sht_error(ex)
        try:
            print("resetting SHT30")
            restartsensor = SHT30(i2c)
            time.sleep(1)
            restartsensor.reset()
            time.sleep(2)
            print("SHT30 reset")
            sensor = sht.measure()
        except:# SHT30Error as ex:
            #sht_error(ex)
            print("rebooting Pico W")
            time.sleep(10)
            machine.reset()
    temperature, humidity = sensor

#wdt = wdt(timeout= 8000)
readsensor()
#wdt.feed()
#print("woof!...good boy!")
print('SHT Temperature: {:3.1f}ºC'.format(temperature))
print('SHT Humidity: {:3.1f}%'.format(humidity))

#Define the onboard Pico Temperature sensor and necessary conversion factor
sensor_temp = machine.ADC(4)
conversion_factor = 3.3 / (65535)

#Configure this Pico W for a static IP address on router using the following
UseStaticIP = True
IP = IP
IP_mask = IP_mask
IP_gateway = IP_gateway
IP_DNS = IP_DNS
 
#Active the onboard Pico W Wi-Fi and connect to home network defined through "secrets.py"
wlan = network.WLAN(network.STA_IF)
#Read the MAC address from the Pico W itself
mac = ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
print()
print("MAC address for this Pico W:", mac)
print()
#Configure a high power wi-fi connection
wlan.config(pm = 0xa11140)
wlan.active(True)
print("Scanning Available Wifi Connections...")
time.sleep(5)
#wdt.feed()
#print("woof!...good boy!")
print(wlan.scan())
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
led.on()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
try:
    wlan.connect(SSID, PASSWORD)
except:
    try:
        print("first attempt to connect to router failed!")
        print("cycling wifi for retry")
        wlan.active(False)
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.active(True)
        time.sleep(2)
        print(wlan.scan())
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.connect(SSID, PASSWORD)
    except:
        print("wifi connecting failed.  Rebooting...")
        time.sleep(10)
        machine.reset()

#wdt.feed()
#print("woof!...good boy!")

led.off()

# Wait for connect or fail (3mins)
max_wait = 90
attempt = 1
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        #print(wlan.status)
        #break
        led.on()
        max_wait -= 1
        #print(wlan.status)
        print()
        print("Connection status attempt: ", attempt)
        print()
        print('connection is good...continuing')
        print()
        attempt += 1
        time.sleep(1)
        led.off()
        time.sleep(1)
        break
        #wdt.feed()
        #print("woof!...good boy!")
# Handle connection error
    if wlan.status() != 3:
        print("Connection status attempt: ", attempt)
        max_wait -= 1
        attempt += 1
        print()
        print("Network connection attempt failed!")
        print()
        #raise RuntimeError('network connection attempt failed')
        time.sleep(5)
        #machine.reset()

while max_wait == 0:
     print()
     print("cannot connect to the wifi!")
     print("rebooting...")
     led.on()
     time.sleep(10)
     machine.reset()

else:
    time.sleep(1)
    print("Pico W Wi-Fi is connected to: ",SSID)
    status = wlan.ifconfig()
    print( "ip address for this Pico W: " + status[0] )
    print()
    print("Channel: ", wlan.config('channel'))
    print("SSID: ", wlan.config('essid'))
    print("TXPOWER: ", wlan.config('txpower'))

stringstatus = str(status[0])
if stringstatus == IP:
    print()
    print("IP is good for MQTT connection! -> ", stringstatus)
    print("Moving on to next stage")
else:
    print()
    print("IP is bad for MQTT connection!  Rebooting...")
    time.sleep(10)
    machine.reset()

#wdt.feed()
#print("woof!...good boy!")
print()
print("Flashing LEDs for success display")
print()
#wdt.feed()
#print("woof!...good boy!")
#Show some onboard LED flashing to show that attempting to connect to the Wi-Fi has been completed
time.sleep(2)
led.off()
time.sleep(2)
led.toggle()
print("3")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("2")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("1")
time.sleep(0.2)
led.toggle()
time.sleep(1)
led.toggle()
print("blast off!")
print()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)

#Setup MQTT server, local client ID (not really required),
#and published data transmissions hierarchy
mqtt_server = MQTTSERVE
client_id = b'PICOW'
#topic_pub1 = b'PicoW/OS_Temp'
#topic_pub2 = b'PicoW/OS_Hum'
#topic_pub3 = b'PicoW/Pico_Temp'
topic_pub1 = b'PicoW/OS_Temp'
topic_pub2 = b'PicoW/OS_Hum'
topic_pub3 = b'PicoW/Pico_Temp'

#For the above topics, use "PicoW/+"
#at the subscriber side to receive all
#three messages at once or use the full
#titles individually i.e PicoW/OS_Temp for
#just the outside temperature variable

def mqtt_connect():
    attempt2 = 5
    while attempt2 > 0:
        try:
            client = MQTTClient(client_id, mqtt_server, keepalive=3600)
            client.connect()
            print('Connected to %s MQTT Broker'%(mqtt_server))
            return client
        except:
            client.disconnect()
            print('Failed to connect to the MQTT Broker. Giving it some time!')
            print(attempt2)
            attempt2 -= 1
            time.sleep(5)
            #client.connect()
            #break
            
    while attempt2 == 0:
        reconnect()

def reconnect():
    print('Failed to connect to the MQTT Broker. Rebooting...')
    time.sleep(5)
    machine.reset()

print("Attempting to connect to MQTT Broker...")
print()
#wdt.feed()
#print("woof!...good boy!")

try:
    client = mqtt_connect()
except OSError as mqtterror:
    print(mqtterror)
    message2 = 'MQTT Error: '
    mqtterror2 = str(mqtterror)
    appendfile(message2, mqtterror2)
    reconnect()

#wdt.feed()
#print("woof!...good boy!")
    
#The main script of repeativeness for reading in from the connected sensor
#and taking in onboard temperature readings
while True:                                  #do stuff here
    led.on()
    time.sleep(0.5)

#Collect readings from the SHT-30
    readsensor()
    
    #wdt.feed()
    #print("woof!...good boy!")

#Collect temperature reading for the Pico W CPU
    def cpumeasure():
        global picotemp
        try:
            reading = sensor_temp.read_u16() * conversion_factor 
            picotemp = 27 - (reading - 0.706)/0.001721
        except OSError as cpu:
            print("something went wrong reading the onboard CPU Temperature!")
            print(cpu)
            print("rebooting...")
            message3 = 'CPU Temp Error: '
            cpu2 = str(cpu)
            appendfile(message3, cpu2)
            time.sleep(5)
            machine.reset()

    cpumeasure()
    #make readings 1 decimal place
    tpm1 = round(temperature,1)
    tpm2 = round(humidity,1)
    tpm3 = round(picotemp,1)
    
    #convert float reading values into bytes ready for MQTT transmission
    tpm4 = f"{tpm1}".encode()
    tpm5 = f"{tpm2}".encode()
    tpm6 = f"{tpm3}".encode()
    
    topic_msg1 = tpm4
    topic_msg2 = tpm5
    topic_msg3 = tpm6
    
    #Message displayed to the screen
    print()
    print("Publishing...")
    print()
    print('SHT Temperature: {:3.1f}ºC'.format(tpm1))
    print('SHT Humidity: {:3.1f}%'.format(tpm2))
    print('Pico W Temperature: {:3.1f}ºC'.format(tpm3))
    print()
    
    #Equivalent transmission of displayed readings above
    #(reverse order to match above order on subscriber receipt)
    try:
        client.publish(topic_pub3, topic_msg3)
        client.publish(topic_pub2, topic_msg2)
        client.publish(topic_pub1, topic_msg1)
        print("Publishing complete")
    except:
        print("Disconnected from MQTT Broker! Attempting Reconnection...")
        print()
        try:
            client = mqtt_connect()
        except OSError as mqtterror:
            print(mqtterror)
            message4 = 'MQTT2 Error: '
            mqtterror3 = str(mqtterror)
            appendfile(message4, mqtterror3)
            reconnect()
    led.off()
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)
I've now enhanced it further with even more appendfile messages for even better transparency of where my code is not resilient enough to recover from a fault. Clearly it has recovered on quite a few occassions, but the final failure was obviously the nail in the coffin it seems. I'm unsure of why it has not recovered this time, even if this needed to be a complete automatic Pico W reboot...? (If anyone fancied a challenge at helping me identify?)
You'll notice i'm still resisting using the watchdog.

Code: Select all

#Necessary library imports for this code to function
from secrets import SSID
from secrets import PASSWORD
from secrets import IP
from secrets import IP_mask
from secrets import IP_gateway
from secrets import IP_DNS
from secrets import MQTTSERVE
from umqtt.simple import MQTTClient
import time
import network
import ubinascii
import socket
from machine import I2C, Pin, #wdt
import sht30
from sht30 import SHT30
from sht30 import SHT30Error

led = machine.Pin("LED", machine.Pin.OUT)

#initialise LED to OFF
led.off()

# def appendfile(message, error):
#     file=open("errorlog.txt","a")
#     errorstring=str(error)
#     file.write(message)
#     file.write(errorstring)
#     file.write("\n")
#     file.close()
    #file.flush()
    
def appendfile(message, error):
   with open('errorlog.txt', 'a') as file:
       file.write(message)
       errorstring=str(error)
       file.write(errorstring)
       file.write('\n')
       file.close()

def sht_error(ex):
    print("something went wrong reading the SHT-30!")
    print('Error:', ex)
    message = 'SHT Error: '
    appendfile(message, ex) #message, error
    
#Define the interface of the SHT30 Temp/Humidity sensor with the Pico W
i2c=I2C(0, sda=Pin(4), scl=Pin(5), freq=5000)
sht=sht30.SHT30(i2c=i2c, i2c_address=68)

def readsensor():
    global temperature
    global humidity
    try:
        sensor = sht.measure()
    except SHT30Error as ex:
        #print(ex)
        sht_error(ex)
        try:
            print("resetting SHT30")
            restartsensor = SHT30(i2c)
            time.sleep(1)
            restartsensor.reset()
            appendfile("SHT30 reset", "command")
            time.sleep(2)
            print("SHT30 reset")
            sensor = sht.measure()
        except:# SHT30Error as ex:
            #sht_error(ex)
            print("cannot read from SHT30, rebooting Pico W")
            appendfile("cannot read from SHT30, rebooting Pico W", "command")
            time.sleep(10)
            machine.reset()
    temperature, humidity = sensor

#wdt = wdt(timeout= 8000)
readsensor()
#wdt.feed()
#print("woof!...good boy!")
print('SHT Temperature: {:3.1f}ºC'.format(temperature))
print('SHT Humidity: {:3.1f}%'.format(humidity))

#Define the onboard Pico Temperature sensor and necessary conversion factor
sensor_temp = machine.ADC(4)
conversion_factor = 3.3 / (65535)

#Configure this Pico W for a static IP address on router using the following
UseStaticIP = True
IP = IP
IP_mask = IP_mask
IP_gateway = IP_gateway
IP_DNS = IP_DNS
 
#Active the onboard Pico W Wi-Fi and connect to home network defined through "secrets.py"
wlan = network.WLAN(network.STA_IF)
#Read the MAC address from the Pico W itself
mac = ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
print()
print("MAC address for this Pico W:", mac)
print()
#Configure a high power wi-fi connection
wlan.config(pm = 0xa11140)
wlan.active(True)
print("Scanning Available Wifi Connections...")
time.sleep(5)
#wdt.feed()
#print("woof!...good boy!")
print(wlan.scan())
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
led.on()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
try:
    wlan.connect(SSID, PASSWORD)
except:
    try:
        print("first attempt to connect to router failed!")
        print("cycling wifi for retry")
        wlan.active(False)
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.active(True)
        time.sleep(2)
        print(wlan.scan())
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.connect(SSID, PASSWORD)
    except:
        print("wifi connecting failed.  Rebooting...")
        appendfile("wifi connecting failed.  Rebooting...", "command")
        time.sleep(10)
        machine.reset()

#wdt.feed()
#print("woof!...good boy!")

led.off()

# Wait for connect or fail (3mins)
max_wait = 90
attempt = 1
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        #print(wlan.status)
        #break
        led.on()
        max_wait -= 1
        #print(wlan.status)
        print()
        print("Connection status attempt: ", attempt)
        print()
        print('connection is good...continuing')
        print()
        attempt += 1
        time.sleep(1)
        led.off()
        time.sleep(1)
        break
        #wdt.feed()
        #print("woof!...good boy!")
# Handle connection error
    if wlan.status() != 3:
        print("Connection status attempt: ", attempt)
        max_wait -= 1
        attempt += 1
        print()
        print("Network connection attempt failed!")
        print()
        #raise RuntimeError('network connection attempt failed')
        time.sleep(5)
        #machine.reset()

while max_wait == 0:
     print()
     print("cannot connect to the wifi!")
     print("rebooting...")
     led.on()
     appendfile("cannot connect to the wifi!", "reboot command")
     time.sleep(10)
     machine.reset()

else:
    time.sleep(1)
    print("Pico W Wi-Fi is connected to: ",SSID)
    status = wlan.ifconfig()
    print( "ip address for this Pico W: " + status[0] )
    print()
    print("Channel: ", wlan.config('channel'))
    print("SSID: ", wlan.config('essid'))
    print("TXPOWER: ", wlan.config('txpower'))

stringstatus = str(status[0])
if stringstatus == IP:
    print()
    print("IP is good for MQTT connection! -> ", stringstatus)
    print("Moving on to next stage")
else:
    print()
    print("IP is bad for MQTT connection!  Rebooting...")
    appendfile("IP is bad for MQTT connection!  Rebooting...", "command")
    time.sleep(10)
    machine.reset()

#wdt.feed()
#print("woof!...good boy!")
print()
print("Flashing LEDs for success display")
print()
#wdt.feed()
#print("woof!...good boy!")
#Show some onboard LED flashing to show that attempting to connect to the Wi-Fi has been completed
time.sleep(2)
led.off()
time.sleep(2)
led.toggle()
print("3")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("2")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("1")
time.sleep(0.2)
led.toggle()
time.sleep(1)
led.toggle()
print("blast off!")
print()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)

#Setup MQTT server, local client ID (not really required),
#and published data transmissions hierarchy
mqtt_server = MQTTSERVE
client_id = b'PICOW'
#topic_pub1 = b'PicoW/OS_Temp'
#topic_pub2 = b'PicoW/OS_Hum'
#topic_pub3 = b'PicoW/Pico_Temp'
topic_pub1 = b'PicoW/OS_Temp'
topic_pub2 = b'PicoW/OS_Hum'
topic_pub3 = b'PicoW/Pico_Temp'

#For the above topics, use "PicoW/+"
#at the subscriber side to receive all
#three messages at once or use the full
#titles individually i.e PicoW/OS_Temp for
#just the outside temperature variable

def mqtt_connect():
    attempt2 = 5
    while attempt2 > 0:
        try:
            client = MQTTClient(client_id, mqtt_server, keepalive=3600)
            client.connect()
            print('Connected to %s MQTT Broker'%(mqtt_server))
            return client
        except:
            client.disconnect()
            print('Failed to connect to the MQTT Broker. Giving it some time!')
            appendfile('Failed to connect to the MQTT Broker. Giving it some time!', "command")
            print(attempt2)
            attempt2 -= 1
            time.sleep(5)
            #client.connect()
            #break
            
    while attempt2 == 0:
        reconnect()

def reconnect():
    print('Failed to connect to the MQTT Broker. Rebooting...')
    appendfile('Failed to connect to the MQTT Broker. Rebooting...',"command")
    time.sleep(5)
    machine.reset()

print("Attempting to connect to MQTT Broker...")
print()
#wdt.feed()
#print("woof!...good boy!")

try:
    client = mqtt_connect()
except OSError as mqtterror:
    print(mqtterror)
    message2 = 'MQTT Error 2: '
    mqtterror2 = str(mqtterror)
    appendfile(message2, mqtterror2)
    reconnect()

#wdt.feed()
#print("woof!...good boy!")
    
#The main script of repeativeness for reading in from the connected sensor
#and taking in onboard temperature readings
while True:                                  #do stuff here
    led.on()
    time.sleep(0.5)

#Collect readings from the SHT-30
    readsensor()
    
    #wdt.feed()
    #print("woof!...good boy!")

#Collect temperature reading for the Pico W CPU
    def cpumeasure():
        global picotemp
        try:
            reading = sensor_temp.read_u16() * conversion_factor 
            picotemp = 27 - (reading - 0.706)/0.001721
        except OSError as cpu:
            print("something went wrong reading the onboard CPU Temperature!")
            print(cpu)
            print("rebooting...")
            message3 = 'CPU Temp Error: '
            cpu2 = str(cpu)
            appendfile(message3, cpu2)
            time.sleep(5)
            machine.reset()

    cpumeasure()
    #make readings 1 decimal place
    tpm1 = round(temperature,1)
    tpm2 = round(humidity,1)
    tpm3 = round(picotemp,1)
    
    #convert float reading values into bytes ready for MQTT transmission
    tpm4 = f"{tpm1}".encode()
    tpm5 = f"{tpm2}".encode()
    tpm6 = f"{tpm3}".encode()
    
    topic_msg1 = tpm4
    topic_msg2 = tpm5
    topic_msg3 = tpm6
    
    #Message displayed to the screen
    print()
    print("Publishing...")
    print()
    print('SHT Temperature: {:3.1f}ºC'.format(tpm1))
    print('SHT Humidity: {:3.1f}%'.format(tpm2))
    print('Pico W Temperature: {:3.1f}ºC'.format(tpm3))
    print()
    
    #Equivalent transmission of displayed readings above
    #(reverse order to match above order on subscriber receipt)
    try:
        client.publish(topic_pub3, topic_msg3)
        client.publish(topic_pub2, topic_msg2)
        client.publish(topic_pub1, topic_msg1)
        print("Publishing complete")
    except:
        print("Disconnected from MQTT Broker! Attempting Reconnection...")
        print()
        try:
            client = mqtt_connect()
        except OSError as mqtterror:
            print(mqtterror)
            message4 = 'MQTT2 Error 4: '
            mqtterror3 = str(mqtterror)
            appendfile(message4, mqtterror3)
            reconnect()
    led.off()
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)

Rissy
Posts: 113
Joined: Sun Aug 14, 2022 8:15 am

Re: Pico W Micro Python for SHT30 Temp/Humidity HELP!

Post by Rissy » Tue Nov 22, 2022 6:11 pm

I couldn't help myself this evening. Even though everything was still working as normal when i got home from work, I wanted to check out my errorlog.txt file to see what's been ocurring.

This is what I found:

Code: Select all

IP is bad for MQTT connection!  Rebooting...command
SHT Error: CRC error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
SHT Error: Bus error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
SHT Error: Bus error
SHT30 resetcommand
SHT Error: CRC error
SHT30 resetcommand
You can pretty much ignore that top error. For some reason when my Pico W attempts to connect to the Virgin router too soon after previously being connected before, then it either fails to connect (for which I have multiple attempts to do so) or it connects successfully, but it doesn't have its IP address assigned properly (I'm assigning it a fixed IP address in my code via my "secrets" file). When this fault happens, it gets 0.0.0.0 assigned to it, which means it wont successfully connect to my MQTT broker, so I've coded it so that if the IP address assigned doesn't match the IP i've designated in my secrets file, then just reboot the Pico W and try again. I wasn't sure of there being any other action I could take at this point besides rebooting....?

After that, you can see that my sensor has multiple errors when trying to be read, but it also seems to be successfully catching these errors and resetting the SHT30 accordingly and then continuing. This is good news for me for sure.

I've now enhanced my code even further with yet more errorlog.txt append commands so that I can get even further transparency, but ultimately I need to wait until I get to one of those rainy days again where I come home from work to find its crashed and no longer contributing its readings to my home monitoring so that I can see the resultant errorlog.txt logs up to the point of crashing.

For those who might still be interested to follow, this is what my code looks like now (still resisting using watchdog):

Code: Select all

#Necessary library imports for this code to function
from secrets import SSID
from secrets import PASSWORD
from secrets import IP
from secrets import IP_mask
from secrets import IP_gateway
from secrets import IP_DNS
from secrets import MQTTSERVE
from umqtt.simple import MQTTClient
import time
import network
import ubinascii
import socket
from machine import I2C, Pin, #wdt
import sht30
from sht30 import SHT30
from sht30 import SHT30Error

led = machine.Pin("LED", machine.Pin.OUT)

#initialise LED to OFF
led.off()

# def appendfile(message, error):
#     file=open("errorlog.txt","a")
#     errorstring=str(error)
#     file.write(message)
#     file.write(errorstring)
#     file.write("\n")
#     file.close()
    #file.flush()
    
def appendfile(message, error):
   with open('errorlog.txt', 'a') as file:
       file.write(message)
       errorstring=str(error)
       file.write(errorstring)
       file.write('\n')
       file.close()

def sht_error(ex):
    print("something went wrong reading the SHT-30!")
    print('Error:', ex)
    message = 'SHT Error: '
    appendfile(message, ex) #message, error
    
#Define the interface of the SHT30 Temp/Humidity sensor with the Pico W
i2c=I2C(0, sda=Pin(4), scl=Pin(5), freq=5000)
sht=sht30.SHT30(i2c=i2c, i2c_address=68)

def readsensor():
    global temperature
    global humidity
    try:
        sensor = sht.measure()
    except SHT30Error as ex:
        #print(ex)
        sht_error(ex)
        try:
            print("resetting SHT30")
            restartsensor = SHT30(i2c)
            time.sleep(1)
            restartsensor.reset()
            appendfile("SHT30 reset", " command")
            time.sleep(2)
            print("SHT30 reset")
            sensor = sht.measure()
        except:# SHT30Error as ex:
            #sht_error(ex)
            print("cannot read from SHT30, rebooting Pico W")
            appendfile("cannot read from SHT30, rebooting Pico W", " command")
            time.sleep(10)
            machine.reset()
    temperature, humidity = sensor

#wdt = wdt(timeout= 8000)
readsensor()
#wdt.feed()
#print("woof!...good boy!")
print('SHT Temperature: {:3.1f}ºC'.format(temperature))
print('SHT Humidity: {:3.1f}%'.format(humidity))

#Define the onboard Pico Temperature sensor and necessary conversion factor
sensor_temp = machine.ADC(4)
conversion_factor = 3.3 / (65535)

#Configure this Pico W for a static IP address on router using the following
UseStaticIP = True
IP = IP
IP_mask = IP_mask
IP_gateway = IP_gateway
IP_DNS = IP_DNS
 
#Active the onboard Pico W Wi-Fi and connect to home network defined through "secrets.py"
wlan = network.WLAN(network.STA_IF)
#Read the MAC address from the Pico W itself
mac = ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
print()
print("MAC address for this Pico W:", mac)
print()
#Configure a high power wi-fi connection
wlan.config(pm = 0xa11140)
wlan.active(True)
print("Scanning Available Wifi Connections...")
time.sleep(5)
#wdt.feed()
#print("woof!...good boy!")
print(wlan.scan())
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
led.on()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)
#wdt.feed()
#print("woof!...good boy!")
try:
    wlan.connect(SSID, PASSWORD)
except:
    try:
        print("first attempt to connect to router failed!")
        print("cycling wifi for retry")
        appendfile("first router connection failed, cycling wifi", " command")
        wlan.active(False)
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        led.toggle()
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.active(True)
        time.sleep(2)
        print(wlan.scan())
        time.sleep(2)
        #wdt.feed()
        #print("woof!...good boy!")
        wlan.connect(SSID, PASSWORD)
    except:
        print("wifi connecting failed.  Rebooting...")
        appendfile("wifi connecting failed.  Rebooting...", " command")
        time.sleep(10)
        machine.reset()

#wdt.feed()
#print("woof!...good boy!")

led.off()

# Wait for connect or fail (3mins)
max_wait = 90
attempt = 1
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        #print(wlan.status)
        #break
        led.on()
        max_wait -= 1
        #print(wlan.status)
        print()
        print("Connection status attempt: ", attempt)
        print()
        print('connection is good...continuing')
        print()
        attempt += 1
        time.sleep(1)
        led.off()
        time.sleep(1)
        break
        #wdt.feed()
        #print("woof!...good boy!")
# Handle connection error
    if wlan.status() != 3:
        print("Connection status attempt: ", attempt)
        max_wait -= 1
        appendfile("Network connection failed attempt:", attempt)
        attempt += 1
        print()
        print("Network connection attempt failed!")
        print()
        #raise RuntimeError('network connection attempt failed')
        time.sleep(5)
        #machine.reset()

while max_wait == 0:
     print()
     print("cannot connect to the wifi!")
     print("rebooting...")
     led.on()
     appendfile("cannot connect to the wifi!", " reboot command")
     time.sleep(10)
     machine.reset()

else:
    time.sleep(1)
    print("Pico W Wi-Fi is connected to: ",SSID)
    status = wlan.ifconfig()
    print( "ip address for this Pico W: " + status[0] )
    print()
    print("Channel: ", wlan.config('channel'))
    print("SSID: ", wlan.config('essid'))
    print("TXPOWER: ", wlan.config('txpower'))

stringstatus = str(status[0])
if stringstatus == IP:
    print()
    print("IP is good for MQTT connection! -> ", stringstatus)
    print("Moving on to next stage")
else:
    print()
    print("IP is bad for MQTT connection!  Rebooting...")
    appendfile("IP is bad for MQTT connection!  Rebooting...", " command")
    time.sleep(10)
    machine.reset()

#wdt.feed()
#print("woof!...good boy!")
print()
print("Flashing LEDs for success display")
print()
#wdt.feed()
#print("woof!...good boy!")
#Show some onboard LED flashing to show that attempting to connect to the Wi-Fi has been completed
time.sleep(2)
led.off()
time.sleep(2)
led.toggle()
print("3")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("2")
time.sleep(0.2)
led.toggle()
time.sleep(1)
#wdt.feed()
#print("woof!...good boy!")
led.toggle()
print("1")
time.sleep(0.2)
led.toggle()
time.sleep(1)
led.toggle()
print("blast off!")
print()
#wdt.feed()
#print("woof!...good boy!")
time.sleep(2)

#Setup MQTT server, local client ID (not really required),
#and published data transmissions hierarchy
mqtt_server = MQTTSERVE
client_id = b'PICOW'
#topic_pub1 = b'PicoW/OS_Temp'
#topic_pub2 = b'PicoW/OS_Hum'
#topic_pub3 = b'PicoW/Pico_Temp'
topic_pub1 = b'PicoW/OS_Temp'
topic_pub2 = b'PicoW/OS_Hum'
topic_pub3 = b'PicoW/Pico_Temp'

#For the above topics, use "PicoW/+"
#at the subscriber side to receive all
#three messages at once or use the full
#titles individually i.e PicoW/OS_Temp for
#just the outside temperature variable

def mqtt_connect():
    attempt2 = 5
    while attempt2 > 0:
        try:
            client = MQTTClient(client_id, mqtt_server, keepalive=3600)
            client.connect()
            print('Connected to %s MQTT Broker'%(mqtt_server))
            return client
        except:
            client.disconnect()
            print('Failed to connect to the MQTT Broker. Giving it some time!')
            appendfile('Failed to connect to the MQTT Broker. Giving it some time!', " command")
            appendfile('attempt: ', attempt2)
            print(attempt2)
            attempt2 -= 1
            time.sleep(5)
            #client.connect()
            #break
            
    while attempt2 == 0:
        reconnect()

def reconnect():
    print('Failed to connect to the MQTT Broker. Rebooting...')
    appendfile('Failed to connect to the MQTT Broker. Rebooting...'," command")
    time.sleep(5)
    machine.reset()

print("Attempting to connect to MQTT Broker...")
print()
#wdt.feed()
#print("woof!...good boy!")

try:
    client = mqtt_connect()
except OSError as mqtterror:
    print(mqtterror)
    message2 = 'MQTT Error 2: '
    mqtterror2 = str(mqtterror)
    appendfile(message2, mqtterror2)
    reconnect()

#wdt.feed()
#print("woof!...good boy!")
    
#The main script of repeativeness for reading in from the connected sensor
#and taking in onboard temperature readings
while True:                                  #do stuff here
    led.on()
    time.sleep(0.5)

#Collect readings from the SHT-30
    readsensor()
    
    #wdt.feed()
    #print("woof!...good boy!")

#Collect temperature reading for the Pico W CPU
    def cpumeasure():
        global picotemp
        try:
            reading = sensor_temp.read_u16() * conversion_factor 
            picotemp = 27 - (reading - 0.706)/0.001721
        except OSError as cpu:
            print("something went wrong reading the onboard CPU Temperature!")
            print(cpu)
            print("rebooting...")
            message3 = 'CPU Temp Error: '
            cpu2 = str(cpu)
            appendfile(message3, cpu2)
            time.sleep(5)
            machine.reset()

    cpumeasure()
    #make readings 1 decimal place
    tpm1 = round(temperature,1)
    tpm2 = round(humidity,1)
    tpm3 = round(picotemp,1)
    
    #convert float reading values into bytes ready for MQTT transmission
    tpm4 = f"{tpm1}".encode()
    tpm5 = f"{tpm2}".encode()
    tpm6 = f"{tpm3}".encode()
    
    topic_msg1 = tpm4
    topic_msg2 = tpm5
    topic_msg3 = tpm6
    
    #Message displayed to the screen
    print()
    print("Publishing...")
    print()
    print('SHT Temperature: {:3.1f}ºC'.format(tpm1))
    print('SHT Humidity: {:3.1f}%'.format(tpm2))
    print('Pico W Temperature: {:3.1f}ºC'.format(tpm3))
    print()
    
    #Equivalent transmission of displayed readings above
    #(reverse order to match above order on subscriber receipt)
    try:
        client.publish(topic_pub3, topic_msg3)
        client.publish(topic_pub2, topic_msg2)
        client.publish(topic_pub1, topic_msg1)
        print("Publishing complete")
    except:
        print("Disconnected from MQTT Broker! Attempting Reconnection...")
        print()
        try:
            client = mqtt_connect()
        except OSError as mqtterror:
            print(mqtterror)
            message4 = 'MQTT2 Error 4: '
            mqtterror3 = str(mqtterror)
            appendfile(message4, mqtterror3)
            reconnect()
    led.off()
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)
    #wdt.feed()
    #print("woof!...good boy!")
    time.sleep(5)

Post Reply