#!/usr/bin/env python3 """Helligkeitsregelung anhand eines LDR-Werts. Portierung von DoDimmen_V aus dem alten MSP430-Programm (GrossAnzeige/main.c, Konstanten aus main.h): gleitender Mittelwert, 3 Helligkeitsstufen mit Hysterese, Prozentwerte aus hellTafel_ub. Der Fotowiderstand (LDR) liefert einen Rohwert (alte Hardware: 12-bit-ADC, 0..4095) -- je heller die Umgebung, desto hoeher der Wert und desto heller die Anzeige. Reines Python, laeuft auch unter MicroPython (dort spaeter vom ADC gespeist). python3 brightness.py --ldr 1500 # Stufe/Prozent berechnen und senden python3 brightness.py --ldr 200 --dry-run """ import argparse import sys # -- Werte aus dem alten Programm (main.h) -------------------------------- HELL_LOW = 300 # Stufengrenze 0<->1 (aus dem alten Code) HELL_HIGH = 2500 # Stufengrenze 1<->2 (aus dem alten Code) HELL_MAX = 3500 # Stufengrenze 2<->3: NEU, nicht aus dem alten Code. # Anpassen, sobald der reale LDR-Wertebereich bekannt ist. HELL_HYST = 30 # Basis-Hysterese AVERAGE_WINDOW = 8 # MAXHELLARRAY: gleitender Mittelwert ueber 8 Werte # Helligkeits-Prozente je Stufe, aus hellTafel_ub (main.h): 5/15/50/100 %. PERCENTS = (5, 15, 50, 100) # Mittelpunkte der Stufengrenzen und deren Hysterese (Stufe i <-> i+1). # Der alte Code nutzte am unteren Uebergang +/-HYST, am oberen +/-5*HYST; das # uebernehmen wir und ergaenzen die neue obere Grenze mit derselben Breite. _CENTERS = (HELL_LOW, HELL_HIGH, HELL_MAX) _HYSTS = (HELL_HYST, HELL_HYST * 5, HELL_HYST * 5) class BrightnessController: """Rechnet aus LDR-Rohwerten die Anzeigehelligkeit -- wie DoDimmen_V. update() gibt die neue Helligkeit in Prozent nur zurueck, wenn sich die Stufe geaendert hat (sonst None). So wird -- wie im alten Programm -- nur bei tatsaechlicher Aenderung ein Helligkeitstelegramm gesendet. """ def __init__(self): self._buf = [] self._level = None # entspricht oldHellStufe_ub = 0xFF (>=2-Zweig) @property def level(self): return self._level def _next_level(self, val, old): """Stufe mit Hysterese bestimmen (verallgemeinert auf beliebig viele Stufen). Hochschalten, solange der Wert die obere Kante (Mitte + Hysterese) der naechsten Grenze ueberschreitet; herunterschalten, solange er die untere Kante (Mitte - Hysterese) unterschreitet. Beim ersten Aufruf (old=None) wird von Stufe 0 aus hochgeschaltet -- die Anzeige startet also gedimmt und hellt sich passend zum Messwert auf. """ level = 0 if old is None else old while level < len(PERCENTS) - 1 and val >= _CENTERS[level] + _HYSTS[level]: level += 1 while level > 0 and val < _CENTERS[level - 1] - _HYSTS[level - 1]: level -= 1 return level def update(self, ldr): """Einen LDR-Rohwert einspeisen. Liefert (stufe, prozent, geaendert).""" self._buf.append(ldr) if len(self._buf) > AVERAGE_WINDOW: self._buf.pop(0) avg = sum(self._buf) // len(self._buf) level = self._next_level(avg, self._level) changed = level != self._level self._level = level return level, PERCENTS[level], changed def main(argv=None): p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) p.add_argument("--ldr", type=int, required=True, help="LDR-Rohwert (0..4095)") p.add_argument("--port", default=None, help="serieller Port (Vorgabe aus config.py)") p.add_argument("--dry-run", action="store_true", help="nur berechnen/anzeigen, nicht senden") args = p.parse_args(argv) level, percent, _ = BrightnessController().update(args.ldr) print("LDR %d -> Stufe %d -> %d %%" % (args.ldr, level, percent)) import config import migra from display import open_display d = open_display(port=args.port or config.PORT, fake=args.dry_run) try: d.set_brightness(percent) except migra.MigraError as e: print("Fehler: %s" % e, file=sys.stderr) return 1 finally: d.close() print("OK") return 0 if __name__ == "__main__": sys.exit(main())