Hiya,
I’ve run into an annoying bug which I can only see when I run my project off battery power (and through a Power Timer Hat)
Essentially, all I need to do, is for my RPi Pico W to read the ADC, and send the reading over MQTT to my server.
My Current setup work when it is powered from
- My server’s USB
- Another Computers USB
- A USB power supply plugged into the wall
However, when I power it up using batteries plugged into the timer hat, my server does not get anny messages. I can see the LED on both the HAT and the RPi toggling on and off with the timmer, so I can see that it is powering up, and receiving a shut down signal, but I cannot see where it is going wrong.
Any ideas how I might approach isolating the issue?
Thanks!
Picture for reference:
import machine
import time
from machine import Pin, ADC
import network
# Import MQTT with error handling
try:
from umqtt.simple import MQTTClient
except ImportError:
import mip
mip.install("umqtt.simple")
from umqtt.simple import MQTTClient
from config import *
# Initialize hardware
led = Pin('LED', Pin.OUT)
csm_sensor = ADC(CSM_PIN)
timer = machine.Timer()
def blink(timer):
"""Toggle LED state periodically"""
led.toggle()
def read_CSM():
"""Read and return the CSM sensor value"""
try:
return csm_sensor.read_u16()
except Exception as e:
print(f"Sensor read error: {e}")
return None
class MQTTHandler:
def __init__(self, broker, port, client_id):
self.broker = broker
self.port = port
self.client_id = client_id
self.client = None
def connect(self):
"""Connect to MQTT broker with retry logic"""
try:
self.client = MQTTClient(self.client_id, self.broker, port=self.port)
self.client.connect()
return True
except Exception as e:
print(f"MQTT connection failed: {e}")
return False
def send_message(self, topic, message):
"""Send message to MQTT topic with reconnection logic"""
try:
if not self.client:
if not self.connect():
return False
self.client.publish(topic, str(message).encode())
return True
except Exception as e:
print(f"Failed to send MQTT message: {e}")
self.client = None # Force reconnection on next attempt
return False
class WiFiManager:
def __init__(self, ssid, password):
self.ssid = ssid
self.password = password
self.wlan = network.WLAN(network.STA_IF)
def connect(self, max_wait=10):
"""Connect to WiFi with timeout"""
print("Connecting to WiFi...")
self.wlan.active(True)
self.wlan.connect(self.ssid, self.password)
while not self.wlan.isconnected() and max_wait > 0:
time.sleep(1)
max_wait -= 1
print("Waiting for connection...")
if not self.wlan.isconnected():
raise RuntimeError("WiFi connection failed")
print("WiFi connected:", self.wlan.ifconfig())
def ensure_connected(self):
"""Check and restore WiFi connection if needed"""
if not self.wlan.isconnected():
try:
self.connect()
return True
except Exception as e:
print(f"WiFi reconnection failed: {e}")
return False
return True
def BOOTUP():
"""Shutdown the device"""
# print("Shutting down...")
# Initialize shutdown pin
shutdown_pin = Pin(SHUTDOWN_PIN, Pin.OUT)
shutdown_pin.value(0) # Set pin low
def main():
led.on() # Turn off LED
DONE = Pin(22, Pin.OUT) # setting this pin High will remove power, and wait for the next interval
# Initialize components
wifi = WiFiManager(SSID, PASSWORD)
mqtt = MQTTHandler(MQTT_BROKER, MQTT_PORT, CLIENT_ID)
# Initial connections
try:
wifi.connect()
mqtt.connect()
except Exception as e:
print(f"Startup error: {e}")
machine.reset() # Reset device on startup failure
print("Entering main loop...")
try:
# Read sensor and send data
reading = read_CSM()
if reading is not None:
mqtt.send_message(TOPIC, reading)
except Exception as e:
print(f"Loop error: {e}")
# Shutdown
print("Shutting down...")
# Initialize shutdown pin
led.off()
DONE.on() # Set pin high to trigger shutdown
if __name__ == "__main__":
main()
NOTE: Config.py is a seperate file with the Wifi details and pin locations etc, omitted for privacy.