minor changes

This commit is contained in:
marble 2025-12-02 22:00:01 +01:00
commit 35817c2219
5 changed files with 226 additions and 0 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Geheimorganisation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

29
README.md Normal file
View file

@ -0,0 +1,29 @@
# Geheimbadge Firmware
This is the Geheimbadge firmware.
It wares the Geheimbadge firm.
## Deployment
Run `nix-shell` in this repo to enter an environment with all necessary tools.
Replace `/dev/ttyACM0` with the correct port for your system.
### Micropython
Download the latest [Firmware Release](https://micropython.org/download/esp32c6/) .bin file.
Flash the firmware using [esptool](https://github.com/espressif/esptool).
```shell
esptool.py --chip esp32c6 --port /dev/ttyACM0 erase_flash
esptool.py --chip esp32c6 --port /dev/ttyACM0 write_flash -z 0x0 esp32c6-20241129-v1.24.1.bin
```
### Scripts
Deployment via [rshell](https://github.com/dhylands/rshell) is recommendet.
```shell
rshell --port /dev/ttyACM0 "cp ./*.py /pyboard"
```
### WiFi Config
Copy `sta-template.json` to `sta.json` and edit.
```shell
rshell --port /dev/ttyACM0 "cp ./sta.json /pyboard"
```

47
button.py Normal file
View file

@ -0,0 +1,47 @@
from machine import Pin, Timer
from time import ticks_ms
class Button:
def __init__(self, pin_num, pull=Pin.PULL_UP, thresholds_ms=[1000, 3000]):
self.pin = Pin(pin_num, Pin.IN, pull)
self.pin_state = 1 if Pin.PULL_UP else 0
self.thresholds_ms = thresholds_ms
self.threshold_idx = 0
self.timer = Timer()
self.pin.irq(self._isr)
def _timer_cb(self, timer):
self.threshold_idx += 1
if self.threshold_idx < len(self.thresholds_ms):
timer.init(
period=self.thresholds_ms[self.threshold_idx]
- self.thresholds_ms[self.threshold_idx - 1],
mode=Timer.ONE_SHOT,
callback=self._timer_cb,
)
if self.callback_fn:
self.callback_fn(self.pin_state, self.threshold_idx)
def _isr(self, pin):
pin_state = pin()
if pin_state != self.pin_state:
self.pin_state = pin_state
if pin_state == 0:
self.threshold_idx = 0
self.timer.init(
period=self.thresholds_ms[self.threshold_idx],
mode=Timer.ONE_SHOT,
callback=self._timer_cb,
)
else:
self.timer.deinit()
if self.callback_fn:
self.callback_fn(pin_state, self.threshold_idx)
def callback(self, fn):
self.callback_fn = fn

117
main.py Normal file
View file

@ -0,0 +1,117 @@
from machine import Pin, ADC
from button import Button
from time import sleep, time, sleep_us
DEAD_ZONE = 0.125
TIMEOUT = 10
GAMMA = 1
DELAY_MIN_US = 500
DELAY_MAX_US = 100000
class Motor:
_LUT = [
(1, 0, 0, 0),
(1, 1, 0, 0),
(0, 1, 0, 0),
(0, 1, 1, 0),
(0, 0, 1, 0),
(0, 0, 1, 1),
(0, 0, 0, 1),
(1, 0, 0, 1),
]
def __init__(self, pins, phase=0):
self._pins = pins
self._phase = phase
def update_pins(self):
pattern = self._LUT[self._phase]
for pin, value in zip(self._pins, pattern):
pin(value)
def step(self, dir):
dir = 1 if dir > 0 else -1 if dir < 0 else 0
self._phase = (self._phase + dir) % len(self._LUT)
self.update_pins()
def inc(self):
self.step(1)
def dec(self):
self.step(-1)
@property
def phase(self):
return self._phase
def off(self):
for pin in self._pins:
pin(0)
class Joystick:
_OFFSET = 30000
_RANGE = 2**16
def __init__(self, adcs):
self._adcs = adcs
def pos(self):
return [2 * adc.read_u16() / self._RANGE - 1 for adc in self._adcs]
# motor = Motor([Pin(i, Pin.OUT) for i in range (4)])
motors = [Motor([Pin(2 + i + 4 * j, Pin.OUT) for i in range(4)]) for j in range(3)]
motor_idx = 3
joystick = Joystick([ADC(i) for i in range(2)])
rgb_led = [Pin(20 - i, Pin.OUT) for i in range(3)]
for led in rgb_led:
led(0)
button = Button(22, thresholds_ms=[1000])
def button_cb(pin_state, threshold):
global motor_idx
if pin_state == 0 and threshold > 0:
motor_idx = (motor_idx + 1) % 4
for i in range(len(rgb_led)):
rgb_led[i](1 if i == motor_idx or motor_idx == 3 else 0)
button.callback(button_cb)
for i in range(len(rgb_led)):
rgb_led[i](1 if i == motor_idx or motor_idx == 3 else 0)
for motor in motors:
motor.update_pins()
now = time()
while True:
joystick_pos = joystick.pos()[1]
abs_pos = abs(joystick_pos)
step_dir =1 if joystick_pos < 0 else -1
dir = joystick_pos < 0
if abs_pos > DEAD_ZONE:
print(joystick_pos, abs_pos)
now = time()
if motor_idx != 3:
motors[motor_idx].step(step_dir)
else:
for motor in motors:
motor.step(step_dir)
normalized = (abs_pos - DEAD_ZONE) / (1-DEAD_ZONE)
delay_us = DELAY_MIN_US + (DELAY_MAX_US- DELAY_MIN_US) * (1-normalized**GAMMA)
sleep_us(int(delay_us))
else:
sleep(0.01)
if time() - now > TIMEOUT:
for motor in motors:
motor.off()
# sleep(0.0025)

12
shell.nix Normal file
View file

@ -0,0 +1,12 @@
with import <nixpkgs> {} ;
mkShell {
buildInputs = [
rshell
esptool
(python3.withPackages (p: with p;[
pyserial
black
]))
];
}