Browse Source

Refactor to work around switch bouncing

DarkMorford 5 years ago
parent
commit
89514552b9
3 changed files with 51 additions and 104 deletions
  1. 2 2
      code/config.json.tmpl
  2. 41 84
      code/main.py
  3. 8 18
      code/quadrature.py

+ 2 - 2
code/config.json.tmpl

@@ -8,9 +8,9 @@
     "play_dat": 0
   },
   "logic": {
-    "sleep_time": 5,
+    "sleep_time": 3,
     "active_time": 60,
-    "wake_threshold": 4
+    "wake_threshold": 25
   },
   "wifi": {
     "ssid": "DesertBus",

+ 41 - 84
code/main.py

@@ -3,6 +3,7 @@ import machine
 from machine import Pin
 import network
 import urequests as requests
+import utime
 
 BTN_IDLE = 0
 BTN_FWD_1 = 1
@@ -12,6 +13,18 @@ BTN_REV_1 = 4
 BTN_REV_2 = 5
 BTN_REV_RDY = 6
 
+def full_reset():
+    global current_state
+    led_red1.off()
+    led_red2.off()
+    led_green.off()
+    activity_timeout.deinit()
+    THE_BUTTON.reset()
+    current_state = BTN_IDLE
+    input_handler.reset()
+    input_handler.enable()
+    wifi.active(False)
+
 def check_forward_1(handler):
     if handler.total_change > 100:
         led_red2.on()
@@ -31,7 +44,7 @@ def check_forward_2(handler):
 def check_forward_trigger(handler):
     if (THE_BUTTON.pressed):
         # Ping overlay server
-        requests.get('http://192.168.0.210:42069/rdp')
+        # requests.get('http://192.168.0.210:42069/rdp')
         led_red1.off()
         led_red2.off()
         led_green.off()
@@ -41,108 +54,52 @@ def check_forward_trigger(handler):
         return BTN_IDLE
     return BTN_FWD_RDY
 
-button_triggered = False
-def button_handler(pin):
-    global button_triggered
-    button_triggered = True
-
 def time_up(timer):
-    global current_state, current_pos
     print('Timeout exceeded, resetting')
-    current_state = BTN_IDLE
-    current_pos = 0
-    led_red1.off()
-    led_red2.off()
-    led_green.off()
-    input_handler.reset()
-
-def dummy_cb(*args, **kwargs):
-    return current_state
-
-def get_state_handler(state):
-    handler_map = {
-        BTN_FWD_1: check_forward_1,
-        BTN_FWD_2: check_forward_2,
-        BTN_FWD_RDY: check_forward_trigger
-    }
-    return handler_map.get(state, dummy_cb)
+    full_reset()
 
 btn_pin = Pin(CONFIG['pins']['play_dat'], Pin.IN, Pin.PULL_UP)
 THE_BUTTON = button.Button(btn_pin)
 
 activity_timeout = machine.Timer(-1)
-current_pos = input_handler.total_change
 current_state = BTN_IDLE
 
+wifi = network.WLAN(network.STA_IF)
 while True:
     while current_state == BTN_IDLE:
         machine.lightsleep(CONFIG['logic']['sleep_time'] * 1000)
-        if input_handler.total_change - current_pos > CONFIG['logic']['wake_threshold']:
+        if input_handler.total_change > CONFIG['logic']['wake_threshold']:
+            print('Entering BTN_FWD_1')
             current_state = BTN_FWD_1
-        elif current_pos - input_handler.total_change > CONFIG['logic']['wake_threshold']:
-            current_state = BTN_REV_1
 
-    wifi = network.WLAN(network.STA_IF)
+    led_red1.on()
     wifi.active(True)
     wifi.connect(CONFIG['wifi']['ssid'], CONFIG['wifi']['password'])
-    led_red1.on()
+    input_handler.disable()
+    start_time = utime.ticks_ms()
     activity_timeout.init(mode=machine.Timer.ONE_SHOT, callback=time_up,
                           period=CONFIG['logic']['active_time'] * 1000)
-    input_handler.reset()
-    while current_state != BTN_IDLE:
+    while current_state == BTN_FWD_1:
         machine.lightsleep(100)
-        handler_func = get_state_handler(current_state)
-        current_state = handler_func(input_handler)
-    wifi.active(False)
-
-"""
-from machine import Pin, Signal
-LED_PIN = Signal(13, Pin.OUT, invert=False)
-BUTTON_PIN = Pin(0, Pin.IN)
-
-# Turn off "ready" LED
-LED_PIN.off()
-
-# Read configuration from JSON file
-with open('config.json') as fd:
-    import ujson
-    config = ujson.load(fd)
-
-# Configure wireless networking
-import network
-wifi_host = network.WLAN(network.AP_IF)
-wifi_host.active(False)
+        if utime.ticks_diff(utime.ticks_ms(), start_time) > 1500:
+            print('Entering BTN_FWD_2')
+            current_state = BTN_FWD_2
 
-wifi_guest = network.WLAN(network.STA_IF)
-wifi_guest.active(True)
-if not wifi_guest.isconnected():
-    wifi_guest.connect(config['wifi']['ssid'], config['wifi']['password'])
-    while not wifi_guest.isconnected():
-        pass
-print(wifi_guest.ifconfig())
-
-# Set up interrupt handler
-BUTTON_PIN.irq(button_handler, Pin.IRQ_RISING)
-
-# Turn on "ready" LED
-LED_PIN.on()
-
-# Enter main loop
-import time
-while True:
-    if button_triggered:
-        import urequests as requests
-
-        LED_PIN.off()
+    led_red2.on()
+    start_time = utime.ticks_ms()
+    while current_state == BTN_FWD_2:
+        machine.lightsleep(100)
+        if (utime.ticks_diff(utime.ticks_ms(), start_time) > 1500) and wifi.isconnected():
+            print('Entering BTN_FWD_RDY')
+            current_state = BTN_FWD_RDY
 
-        btn_id = config['buttonId']
-        endpoint = 'http://192.168.0.212:42069/rdp?id={0}'.format(btn_id)
-        res = requests.get(endpoint)
-#       print(res.status_code)
+    led_green.on()
+    THE_BUTTON.reset()
+    while current_state == BTN_FWD_RDY:
+        machine.lightsleep(100)
+        if THE_BUTTON.pressed:
+            print('Launching dance party')
+            requests.get('http://192.168.0.210:42069/rdp')
+            current_state = BTN_IDLE
 
-        time.sleep(5)
-        button_triggered = False
-        LED_PIN.on()
-    else:
-        time.sleep(1)
-"""
+    full_reset()

+ 8 - 18
code/quadrature.py

@@ -1,6 +1,4 @@
-import machine
 from machine import Pin
-import sys
 
 class Encoder:
     _increment_grid = [[0, -1, 1, None],
@@ -14,29 +12,21 @@ class Encoder:
 
     def __init__(self, channel_a, channel_b):
         self.channel_a = self._configure_channel(channel_a)
-        self.channel_b = self._configure_channel(channel_b)
         self.reset()
 
+    def disable(self):
+        self.channel_a.irq(None)
+
+    def enable(self):
+        self.channel_a.irq(self._irq_cb, trigger=Pin.IRQ_RISING)
+
     def reset(self):
-        self._previous_value = None
         self._total_change = 0
 
     def _irq_cb(self, input_pin):
-        interrupt_mask = machine.disable_irq()
-        current_value = (self.channel_a.value() * 2) + self.channel_b.value()
-        if self._previous_value == None:
-            self._previous_value = current_value
-            machine.enable_irq(interrupt_mask)
-            return
-        try:
-            change_amount = self._increment_grid[self._previous_value][current_value]
-            self._total_change += change_amount
-        except TypeError:
-            print('Detected invalid encoder state! Can the system keep up?', file=sys.stderr)
-        self._previous_value = current_value
-        machine.enable_irq(interrupt_mask)
+        self._total_change += 1
 
     def _configure_channel(self, pin):
         p = pin if isinstance(pin, Pin) else Pin(pin, Pin.IN, pull=Pin.PULL_UP)
-        p.irq(self._irq_cb, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
+        p.irq(self._irq_cb, trigger=Pin.IRQ_RISING)
         return p