4
\$\begingroup\$

I'm running MicroPython on an ESP32 relaying sensor data to my MQTT server for Home Assistant. I only want it to emit a message when state has changed and a motion detected state to hold for a minute before returning to a clear state. I see a lot of examples using sleep, but I don't like the blocking nature of sleep as I will be adding more sensors. Instead I've been using ticks_ms() and ticks_diff() to keep the state from fluttering on/off too much, but I can't help but think there's a better/more elegant way to do this that I'm not seeing.

There's some repetition and nesting that sticks out to me

from umqtt.robust import MQTTClient
from machine import Pin, unique_id
from time import ticks_diff, ticks_ms
from ubinascii import hexlify
#Config
MQTT_SERVER = "X.X.X.X"
MQTT_PORT = 1883
MQTT_USER = b"USER"
MQTT_PASSWORD = b"PASSWORD"
MQTT_CLIENT_ID = hexlify(unique_id())
MQTT_TOPIC = b"esp/motion"
mqtt = MQTTClient(MQTT_CLIENT_ID, MQTT_SERVER, MQTT_PORT, MQTT_USER, MQTT_PASSWORD)
ledPin = Pin(2, Pin.OUT)
motPin = Pin(15, Pin.IN)
previousState = 0
delay_ms = 60000
clock = ticks_ms()
def main():
 global clock, previousState, delay_ms
 try:
 mqtt.connect()
 while True:
 state = motPin.value()
 if state == 1:
 ledPin.on()
 if previousState == 0:
 if ticks_diff(ticks_ms(), clock) >= 0:
 print('motion_start')
 mqtt.publish(MQTT_TOPIC, 'motion_start')
 clock = ticks_ms() + delay_ms
 previousState = state
 else:
 clock = ticks_ms() + delay_ms
 else:
 ledPin.off()
 if previousState == 1:
 if ticks_diff(ticks_ms(), clock) >= 0:
 print('motion_stop')
 mqtt.publish(MQTT_TOPIC, 'motion_stop')
 previousState = state
 finally:
 ledPin.off()
 mqtt.publish(MQTT_TOPIC, 'motion_stop')
 mqtt.disconnect()
if __name__ == "__main__":
 main()
asked Jun 22, 2020 at 18:06
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Fluttering

 if previousState == 0:
 if ticks_diff(ticks_ms(), clock) >= 0:

This is called a soft debounce. It may or may not be adequate. My usual recommendation is to do hard debounce instead (or maybe in addition) via a first-order RC lowpass filter followed by hysteresis in a Schmitt trigger. If none of that makes sense to you, then that's a question for https://electronics.stackexchange.com/ .

Truthiness

I would sooner write

if state:

rather than

if state == 1:

snake_case

Per PEP8, previousState should be previous_state.

answered Jun 22, 2020 at 18:16
\$\endgroup\$
1
  • \$\begingroup\$ What I'm aiming for isn't necessarily debouncing as the sensor has digital signal processing; multiple motion events all within a minute just tend to present issues with home automation. Agreed on the state boolean - I had that initially, but thought that might obfuscate sensor value too much - but it is indeed cleaner. \$\endgroup\$ Commented Jun 22, 2020 at 18:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.