Blog der Heimetli Software AG

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:

Raspberry Pico mit 433 Mhz Receiver

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