Decoder für das Auriol-Protokoll auf Raspberry Pico
Nachdem das Decodieren des Prologue-Protokolls gut geklappt hat machte ich mich ans Protokoll für den Auriol AFT 77 B2.
Die Hardware ist genau gleich wie beim letzten Projekt:
Die Software stellte sich als schwieriger heraus, weil das Timing in Micropython unberechenbar ist. Schlussendlich habe ich es geschafft indem ich das Ende des letzten Pulses als Startpunkt des nächsten Pulses genommen habe. Deshalb wird im Code die Variable te durch das ganze Programm geschleppt.
Das Python-Programm
""" Decodes the signal from the auriol aft 77 b2 sensor Setup: GPIO 16 is connected to tho output pin of an AM-RX12E-433P The output is sent to the serial port on USB. """ import time from machine import Pin p = Pin( 16, Pin.IN ) def check_pulse( ts ): """ Verifies that the pin is high for 450 to 650us """ while p.value() == 1: pass te = time.ticks_us() return 450 < te - ts < 650, te def measure( ts ): """ Determines how long the pin is low """ while p.value() == 0: pass te = time.ticks_us() return te - ts, te def wait_for_start(): """ Waits for the start sequence """ while True: diff, te = measure( time.ticks_us() ) if diff < 1800 or diff > 2600: continue counter = 1 while True: valid, te = check_pulse( te ) if not valid: break diff, te = measure( time.ticks_us() ) if diff > 2600: break if diff < 1800: if counter > 8: return diff, te break counter += 1 def check_sum( signal ): sum = 0 tmp = signal >> 16 for _ in range( 6 ): sum += tmp & 0xFF tmp >>= 8 return ((signal >> 8) & 0xFF) == (sum & 0xFF) def check_lsrc( signal ): mask = 0x8000000000000000 key = 0xEC result = 0x00 while mask > 0x8000: if signal & mask != 0: result ^= key if key & 0x01: key = (key >> 1) ^ 0x83 else: key = (key >> 1) mask >>= 1 return (result & 0xFF) == (signal & 0xFF) def auriol(): """ Decodes the signal """ while True: diff, te = wait_for_start() if 450 < diff < 550: signal = 0 elif 870 < diff < 985: signal = 1 else: continue while True: valid, te = check_pulse( te ) if not valid: break diff, te = measure( te ) if 450 < diff < 550: signal <<= 1 elif 870 < diff < 985: signal = (signal << 1) | 1 else: if signal & 0xa0000000000000000 == 0xa0000000000000000: if check_sum(signal) and check_lsrc(signal): print( hex(signal) ) break # Start the decoder auriol()
Es ist erstaunlich dass der Integer signal so lang werden kann. Das hatte ich wirklich nicht erwartet.
Auspacken des Messwerts auf dem PC
from datetime import datetime, timedelta def log_temperature( line ): temperature = float( line[10:13] ) / 10 sensor = line[4:6] with open("temperature.csv","a") as logfile: logfile.write( f"{datetime.now().strftime('%d.%m.%Y %H:%M:%S')},{sensor},{temperature}\n" ) seconds = datetime.now() ds = timedelta( seconds=20 ) previous = "" with open( "/dev/ttyACM0" ) as input: for line in input: now = datetime.now() if line != previous: log_temperature( line ) seconds = now else: if now > seconds + ds: seconds = now log_temperature( line ) previous = line
Wenn sich das Programm sofort beendet muss die Schnittstelle konfiguriert werden:
stty -F /dev/ttyACM0 raw -echo cread 115200