Added local counter functionality via pin input
This commit is contained in:
parent
97a56063ed
commit
7c0d2d114a
96
counter.py
Normal file
96
counter.py
Normal file
@ -0,0 +1,96 @@
|
||||
from machine import Pin
|
||||
from time import sleep
|
||||
from utime import ticks_ms
|
||||
|
||||
class Counter:
|
||||
def __init__(self, name="C1", value = 0): # init_value may be smaller than 0
|
||||
self.value = int(value)
|
||||
self.name = str(name)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name);
|
||||
|
||||
|
||||
def __int__(self):
|
||||
return int(self.value);
|
||||
|
||||
|
||||
def __add__(self, x):
|
||||
counter = Counter(value=self.value+int(x))
|
||||
return counter
|
||||
|
||||
|
||||
def __sub__(self, x):
|
||||
counter = Counter(value=self.value-int(x))
|
||||
return counter
|
||||
|
||||
def increment(self):
|
||||
self.value += 1
|
||||
|
||||
|
||||
"""
|
||||
CounterArray:
|
||||
provides an easy-to-use interface for the counter class.
|
||||
"""
|
||||
class CounterArray:
|
||||
def __init__(self, counter_number = 1, counter_names = ["Counter 1"]):
|
||||
self._counters = {}
|
||||
|
||||
if len(counter_names) < counter_number:
|
||||
raise IndexError("counter_names list MUST contain names for all counters.")
|
||||
elif len(counter_names) > counter_number:
|
||||
print("[WARN] [CounterArray] More counter names are given than counters wanted. Ignoring the overflow.")
|
||||
|
||||
for i in range(counter_number):
|
||||
self._counters[i] = Counter(counter_names[i])
|
||||
|
||||
|
||||
def add_counter(self, counter: Counter):
|
||||
self._counters[len(self._counters)] = counter
|
||||
return True
|
||||
|
||||
|
||||
def remove_counter(self, key):
|
||||
self._counters.pop(key)
|
||||
return True
|
||||
|
||||
|
||||
def get_counter(self, key):
|
||||
return self._counters[key]
|
||||
|
||||
|
||||
def register_listener(self, pins: dict, changed_callback=lambda: None):
|
||||
# Function:
|
||||
# listens for btn presses on specified pins
|
||||
# Parameter: pins
|
||||
# should be a dict of the form {COUNTER_ID:PIN, ...}
|
||||
# where COUNTER_ID is the key of the counter to increment in the
|
||||
# internal _counters dict and PIN is the pin to listen on
|
||||
# Parameter: changed_callback
|
||||
# is called without parameters, every time a button was pressed
|
||||
inputs = {}
|
||||
|
||||
for counter_id, pin in pins.items():
|
||||
inputs[counter_id] = Pin(pin, Pin.IN, Pin.PULL_DOWN)
|
||||
|
||||
|
||||
self.last_time = 0
|
||||
def press_handler(pin, inputs, _counters, counterarray, changed_callback):
|
||||
for counter_id, p in inputs.items():
|
||||
if p == pin: # now we have the pin where the button got pressed
|
||||
new_time = ticks_ms()
|
||||
if (new_time - counterarray.last_time) > 150:
|
||||
_counters[counter_id] += 1
|
||||
counterarray.last_time = new_time
|
||||
changed_callback()
|
||||
|
||||
|
||||
for counter_id, pin in inputs.items():
|
||||
try:
|
||||
self._counters[counter_id]
|
||||
pin.irq(trigger=Pin.IRQ_FALLING, handler=lambda p: press_handler(p, inputs, self._counters, self, changed_callback))
|
||||
except KeyError:
|
||||
print("[ERROR] [Counter().register_listener] Error while registering counter-pin-pair (counter_id=" + str(counter_id) + ", pin=" + str(pin) + "). Ignoring this pair.")
|
||||
|
||||
|
@ -26,7 +26,6 @@ SHIFT_DATA = 4 # P4-P7
|
||||
|
||||
|
||||
class LCD_API:
|
||||
|
||||
# Implements the API for talking with HD44780 compatible character LCDs.
|
||||
# This class only knows what commands to send to the LCD, and not how to get
|
||||
# them to the LCD.
|
||||
|
95
lcd_screen.py
Normal file
95
lcd_screen.py
Normal file
@ -0,0 +1,95 @@
|
||||
from machine import I2C, Pin, Timer
|
||||
import time
|
||||
|
||||
|
||||
class CounterScreen:
|
||||
def __init__(self, lcd, counterArray):
|
||||
self.lcd = lcd
|
||||
self.lcd.clear()
|
||||
self.counterArray = counterArray
|
||||
self._zfill = lambda s, length: '{:0>{w}}'.format(s, w=length)
|
||||
self.last_line1 = ""
|
||||
self.last_line2 = ""
|
||||
self.too_many_counters_warning_shown = False
|
||||
|
||||
def _too_many_counters_warning(self):
|
||||
# Function:
|
||||
# show a short message saying that not more that 5 counters can be displayed.
|
||||
# WARNING:
|
||||
# This is a INTERNAL class function, don't call from outside!
|
||||
# Stops program flow for approx. 15s
|
||||
|
||||
self.lcd.move_to(0,0)
|
||||
self.lcd.putstr(" WARNING! ")
|
||||
message = "Can't display more than 5 counters. Cutting the overflow. "
|
||||
message = message + " +++ " + message
|
||||
while message != " ":
|
||||
self.lcd.move_to(0,1)
|
||||
self.lcd.putstr(message[:16])
|
||||
message = message[1:]
|
||||
time.sleep(0.07)
|
||||
|
||||
self.lcd.clear()
|
||||
self.too_many_counters_warning_shown = True
|
||||
|
||||
def show_screen(self):
|
||||
# Function:
|
||||
# show a screen on the lcd, table layout: row 1 shows the short names of the counters,
|
||||
# row 2 shows the values.
|
||||
# WARNING:
|
||||
# This function SHALL be called once at init of the class as it can stop execution for
|
||||
# approx. 15s at first run!
|
||||
|
||||
line1 = ""
|
||||
line2 = ""
|
||||
number_counters = len(self.counterArray._counters)
|
||||
if number_counters > 5:
|
||||
if not self.too_many_counters_warning_shown:
|
||||
self._too_many_counters_warning()
|
||||
number_counters = 5
|
||||
|
||||
|
||||
## show different views depending on how many counters exist
|
||||
if number_counters < 1:
|
||||
line1 = " WARNING! "
|
||||
line2 = " No counters. "
|
||||
|
||||
elif number_counters == 1:
|
||||
line1 = "* C1 "
|
||||
line2 = "* " + str(list(self.counterArray._counters.items())[0][1].value)
|
||||
|
||||
elif number_counters == 2:
|
||||
v0 = str(list(self.counterArray._counters.items())[0][1].value)
|
||||
v1 = str(list(self.counterArray._counters.items())[1][1].value)
|
||||
line1 = "* C1 * C2 "
|
||||
line2 = "* " + v0 + (6-len(v0))*" " + "* " + v1 + (6-len(v1)) * " "
|
||||
|
||||
elif number_counters == 3:
|
||||
v0 = str(list(self.counterArray._counters.items())[0][1].value)
|
||||
v1 = str(list(self.counterArray._counters.items())[1][1].value)
|
||||
v2 = str(list(self.counterArray._counters.items())[2][1].value)
|
||||
line1 = "C1 * C2 * C3 "
|
||||
line2 = v0 + (3-len(v0))*" " + " * " + v1 + (3-len(v1))*" " + " * " + v2 + (4-len(v2))*" "
|
||||
|
||||
elif number_counters == 4:
|
||||
line1 = "|C1 |C2 |C3 |C4 "
|
||||
for i in range(4):
|
||||
line2 += "|" + self._zfill(list(self.counterArray._counters.items())[i][1].value, 3)[:3]
|
||||
|
||||
else:
|
||||
line1 = "|C1|C2|C3|C4|C5|"
|
||||
for i in range(5):
|
||||
line2 += "|" + self._zfill(list(self.counterArray._counters.items())[i][1].value, 2)[:2]
|
||||
line2 += "|"
|
||||
|
||||
|
||||
# check if something changed, if so, redraw it
|
||||
if line1 != self.last_line1:
|
||||
self.lcd.putstr(line1[:16])
|
||||
self.last_line1 = line1
|
||||
self.lcd.move_to(0,1)
|
||||
if line2 != self.last_line2:
|
||||
self.lcd.putstr(line2[:16])
|
||||
self.last_line2 = line2
|
||||
|
||||
|
22
micronec.py
Normal file
22
micronec.py
Normal file
@ -0,0 +1,22 @@
|
||||
from lcd_driver import I2C_LCD
|
||||
from machine import I2C, Pin
|
||||
from welcome import WelcomeScreen
|
||||
from counter import CounterArray
|
||||
from lcd_screen import CounterScreen
|
||||
import time
|
||||
|
||||
|
||||
I2C_ADDR = 0x27
|
||||
I2C_NUM_ROWS = 2
|
||||
I2C_NUM_COLS = 16
|
||||
|
||||
_i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
|
||||
lcd = I2C_LCD(_i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
|
||||
counterArray = CounterArray(2, ["Counter 1", "Counter 2"])
|
||||
ws = WelcomeScreen(lcd)
|
||||
cs = CounterScreen(lcd, counterArray)
|
||||
|
||||
# Real program
|
||||
ws.show_welcome(1)
|
||||
cs.show_screen()
|
||||
counterArray.register_listener({0:2,1:3}, cs.show_screen)
|
14
welcome.py
14
welcome.py
@ -1,18 +1,8 @@
|
||||
from lcd_driver import I2C_LCD
|
||||
from machine import I2C, Pin, Timer
|
||||
import time
|
||||
import machine
|
||||
|
||||
|
||||
class WelcomeScreen:
|
||||
def __init__(self):
|
||||
self.I2C_ADDR = 0x27
|
||||
self.I2C_NUM_ROWS = 2
|
||||
self.I2C_NUM_COLS = 16
|
||||
|
||||
self._i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
|
||||
self.lcd = I2C_LCD(self._i2c, self.I2C_ADDR, self.I2C_NUM_ROWS, self.I2C_NUM_COLS)
|
||||
|
||||
def __init__(self, lcd):
|
||||
self.lcd = lcd
|
||||
|
||||
def show_welcome(self, loops=1): # loops says how often the Starting text goes through
|
||||
if loops < 1: loops = 1
|
||||
|
Loading…
Reference in New Issue
Block a user