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