浏览代码

Rough code for 2019 button

DarkMorford 5 年之前
父节点
当前提交
93326506aa
共有 6 个文件被更改,包括 193 次插入15 次删除
  1. 11 5
      code/Pipfile.lock
  2. 28 2
      code/boot.py
  3. 13 0
      code/button.py
  4. 17 5
      code/config.json.tmpl
  5. 85 3
      code/main.py
  6. 39 0
      code/quadrature.py

+ 11 - 5
code/Pipfile.lock

@@ -31,10 +31,10 @@
         },
         "ecdsa": {
             "hashes": [
-                "sha256:163c80b064a763ea733870feb96f9dd9b92216cfcacd374837af18e4e8ec3d4d",
-                "sha256:9814e700890991abeceeb2242586024d4758c8fc18445b194a49bd62d85861db"
+                "sha256:64c613005f13efec6541bb0a33290d0d03c27abab5f15fbab20fb0ee162bdd8e",
+                "sha256:e108a5fe92c67639abae3260e43561af914e7fd0d27bae6d2ec1312ae7934dfe"
             ],
-            "version": "==0.13.3"
+            "version": "==0.14.1"
         },
         "esptool": {
             "hashes": [
@@ -45,8 +45,7 @@
         },
         "pyaes": {
             "hashes": [
-                "sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f",
-                "sha256:0b6ec2e5058000d89ae65252dd53f1c5e27936dfd750e27fc2a51df74fe3dde9"
+                "sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f"
             ],
             "version": "==1.6.1"
         },
@@ -63,6 +62,13 @@
                 "sha256:f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544"
             ],
             "version": "==0.10.3"
+        },
+        "six": {
+            "hashes": [
+                "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
+                "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
+            ],
+            "version": "==1.13.0"
         }
     },
     "develop": {}

+ 28 - 2
code/boot.py

@@ -1,7 +1,33 @@
 # This file is executed on every boot (including wake-boot from deepsleep)
 #import esp
 #esp.osdebug(None)
+
+# Disable built-in WiFi access point
+import network
+wifi_ap = network.WLAN(network.AP_IF)
+wifi_ap.active(False)
+del wifi_ap
+del network
+
+# Load configuration data from file
+import ujson
+with open('config.json', encoding='utf8') as fd:
+    CONFIG = ujson.load(fd)
+del ujson
+
+# Define input handler
+import quadrature
+input_handler = quadrature.Encoder(0, 4)
+del quadrature
+
+# Set up LED pins
+from machine import Pin, Signal
+led_red1 = Signal(CONFIG['pins']['led_1'], Pin.OUT, value=0, invert=False)
+led_red2 = Signal(CONFIG['pins']['led_2'], Pin.OUT, value=0, invert=False)
+led_green = Signal(CONFIG['pins']['led_3'], Pin.OUT, value=0, invert=False)
+del Pin, Signal
+
+# Clean up temporary setup variables
 import gc
-#import webrepl
-#webrepl.start()
 gc.collect()
+del gc

+ 13 - 0
code/button.py

@@ -0,0 +1,13 @@
+from machine import Pin
+
+class Button:
+    def __init__(self, pin):
+        self.trigger = pin
+        self.pressed = False
+        self.trigger.irq(self._cb, Pin.IRQ_FALLING)
+
+    def reset(self):
+        self.pressed = False
+
+    def _cb(self, pin):
+        self.pressed = True

+ 17 - 5
code/config.json.tmpl

@@ -1,7 +1,19 @@
 {
-	"wifi": {
-		"ssid": "LunarModule",
-		"password": "DesertBus"
-	},
-	"buttonId": 0
+  "pins": {
+    "encoder_A": 4,
+    "encoder_B": 5,
+    "led_1": 12,
+    "led_2": 13,
+    "led_3": 14,
+    "play_dat": 0
+  },
+  "logic": {
+    "sleep_time": 5,
+    "active_time": 60,
+    "wake_threshold": 4
+  },
+  "wifi": {
+    "ssid": "DesertBus",
+    "password": "iwantinternet"
+  }
 }

+ 85 - 3
code/main.py

@@ -1,12 +1,93 @@
-from machine import Pin, Signal
-LED_PIN = Signal(13, Pin.OUT, invert=False)
-BUTTON_PIN = Pin(0, Pin.IN)
+from enum import Enum, auto
+import machine
+import network
+import urequests as requests
+
+class ButtonState(Enum):
+    IDLE = auto()
+    FWD_1 = auto()
+    FWD_2 = auto()
+    FWD_RDY = auto()
+    REV_1 = auto()
+    REV_2 = auto()
+    REV_RDY = auto()
+
+def check_forward_1(handler):
+    if handler.total_change > 30:
+        led_red2.on()
+        handler.reset()
+        return ButtonState.FWD_2
+    return ButtonState.FWD_1
+
+def check_forward_2(handler):
+    global button_triggered
+    if handler.total_change > 30 and wifi.isconnected():
+        led_green.on()
+        button_triggered = False
+        return ButtonState.FWD_RDY
+    return ButtonState.FWD_2
+
+def check_forward_trigger(handler):
+    if (button_triggered):
+        # Ping overlay server
+        led_red1.off()
+        led_red2.off()
+        led_green.off()
+        return ButtonState.IDLE
+    return ButtonState.FWD_RDY
 
 button_triggered = False
 def button_handler(pin):
     global button_triggered
     button_triggered = True
 
+def time_up(timer):
+    global current_state, current_pos
+    current_state = ButtonState.IDLE
+    current_pos = 0
+    input_handler.reset()
+
+def dummy_cb(*args, **kwargs):
+    return current_state
+
+def get_state_handler(state):
+    handler_map = {
+        ButtonState.FWD_1: check_forward_1,
+        ButtonState.FWD_2: check_forward_2,
+        ButtonState.FWD_RDY: check_forward_trigger
+    }
+    return handler_map.get(state, dummy_cb)
+
+activity_timeout = machine.Timer(-1)
+current_pos = input_handler.total_change
+current_state = ButtonState.IDLE
+
+while True:
+    while current_state == ButtonState.IDLE:
+        machine.lightsleep(CONFIG['logic']['sleep_time'] * 1000)
+        if input_handler.total_change - current_pos > CONFIG['logic']['wake_threshold']:
+            current_state = ButtonState.FWD_1
+        elif current_pos - input_handler.total_change > CONFIG['logic']['wake_threshold']:
+            current_state = ButtonState.REV_1
+
+    wifi = network.WLAN(network.STA_IF)
+    wifi.active(True)
+    wifi.connect(config['wifi']['ssid'], config['wifi']['password'])
+    led_red1.on()
+    activity_timeout.init(mode=machine.Timer.ONE_SHOT, callback=time_up,
+                          period=CONFIG['logic']['active_time'] * 1000)
+    input_handler.reset()
+    while current_state != ButtonState.IDLE:
+        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()
 
@@ -52,3 +133,4 @@ while True:
         LED_PIN.on()
     else:
         time.sleep(1)
+"""

+ 39 - 0
code/quadrature.py

@@ -0,0 +1,39 @@
+from machine import Pin
+import sys
+
+class Encoder:
+    _increment_grid = [[0, -1, 1, None],
+                       [1, 0, None, -1],
+                       [-1, None, 0, 1],
+                       [None, 1, -1, 0]]
+
+    @property
+    def total_change(self):
+        return self._total_change
+
+    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 reset(self):
+        self._previous_value = None
+        self._total_change = 0
+
+    def _irq_cb(self, input_pin):
+        print('IRQ handler called')
+        current_value = (self.channel_a.value() * 2) + self.channel_b.value()
+        if self._previous_value == None:
+            self._previous_value = current_value
+            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
+
+    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))
+        return p