Всем хороша погодная станция Buro H146G с внешним беспроводным термометром H999. Но вот только чтобы увидеть показания на её блеклом ЖК-дисплее требуется хорошее освещение. А мне было бы лучше, если бы вывод температуры и влажности за окном отображался на достаточно ярких индикаторах (например, совместив отображение температуры и влажности с часами на газоразрядных индикаторах ИН-12). Сделать такую поделку несложно, но нужно знать протокол обмена с беспроводным термометром. Здесь уже были статьи про использование беспроводного термометра метеостанций для получения температуры и влажности по радиоканалу. Но для станций Buro протокол обмена ещё не был описан. Значит, надо это исправить: возможно, кому-то он может пригодиться.
В интернете описания протокола обмена станций BURO я не нашёл. А это значит, что придётся вскрывать протокол обмена этого беспроводного датчика.
Мой внешний термометр выглядит так:

Подключив к осциллографу китайский сверхрегенеративный приёмник на 433,92 МГц и нажав кнопку TEST на термометре, было отчётливо видно, как бегут импульсы передачи. Ну а так как частота там небольшая, выход приёмника был подключён к входу звуковой карты через резистивный делитель. После обработки записанного звукового файла компаратором получилась следующая картинка:

Как и у других погодных станций модуляция осуществляется изменением скважности. Начинается передача с блока синхросигналов, потом идёт ещё один синхросигнал, а потом идут данные, после которых идёт завершающий синхросигнал. Два ноля после синхросигнала, по-видимому, являются идентификатором начала данных – во всяком случае, я ни разу не заметил их изменения. Данные с начальным и конечным синхросигналом дублируются шесть раз. Обмен данными ведётся нибблами.
Для декодирования я решил начинать приём по первому синхросигналу и двум нулям, а завершать по последнему синхросигналу.
Чтобы такой сигнал декодировать, достаточно посчитать длительности между перепадами сигнала.
Я для этого написал простенькую тестовую программу для контроллера Atmega8:
Выход приёмника подключается к выводу 13 (AIN1). Atmega через max232 подключается к COM-порту компьютера (ну или к переходнику USB-COM). Скорость работы порта 9600 бод.
После декодирования получится следующий поток данных (два начальных ноля я выбрасываю):
//без кнопки, канал 1
1100 1100 0000 1110 1000 0110 1100 0001 0000 1001 Влажность:28% Температура:25.4
//без кнопки, канал 2
1100 1100 0001 1110 1000 0110 1101 0001 0000 0110 Влажность:29% Температура:25.4
Итого, пакет выглядит так:

I0-I7 – идентификатор термометра. При каждом новом включении термометра идентификатор меняется.
C0-C1 — канал (всего их возможно 3). Каналы нумеруются с нуля.
H0-H7 — влажность. Влажность в процентах считывается как есть, а вот температура (T0-T11) почему-то задана в необычном для метеостанций формате. Судя по найденным мной описаниям протоколов обмена различных метеостанций, можно было бы ожидать температуру в десятых долях градуса и со смещением нижнего предела измерения термометра. Так вот, нет. Эксперименты показали, что код температуры данной метеостанции переводится в градусы Цельсия как (T-1220)/18. Откуда эти магические числа знают только китайцы, придумавшие этот протокол обмена.
Как подсказал wolowizard в комментариях, станция передаёт температуру в десятых долях градусов Фаренгейта, поэтому осмысленный перевод в градусы Цельсия будет 0.1*(T-320)*5/9-500=0.1*(T-1220)/1.8.
Бит K соответствует нажатию на кнопку TEST.
Назначение остальных полей установить не удалось, но выяснилось, что значение переключателя Фаренгейты/Цельсии на термометре в протокол обмена не попадает. Предположительно так же последний ниббл (а может, и часть предпоследнего) является CRC, но вычислить алгоритм мне пока не удалось (есть подозрение, что в вычислении участвуют строки и столбцы нибблов). Если кто-нибудь сумеет разгадать эту загадку, соо��щите, пожалуйста, алгоритм вычисления.
Для желающих поломать голову, но не имеющих такого термометра, привожу таблицу принятых данных.
В интернете описания протокола обмена станций BURO я не нашёл. А это значит, что придётся вскрывать протокол обмена этого беспроводного датчика.
Мой внешний термометр выглядит так:

Подключив к осциллографу китайский сверхрегенеративный приёмник на 433,92 МГц и нажав кнопку TEST на термометре, было отчётливо видно, как бегут импульсы передачи. Ну а так как частота там небольшая, выход приёмника был подключён к входу звуковой карты через резистивный делитель. После обработки записанного звукового файла компаратором получилась следующая картинка:

Как и у других погодных станций модуляция осуществляется изменением скважности. Начинается передача с блока синхросигналов, потом идёт ещё один синхросигнал, а потом идут данные, после которых идёт завершающий синхросигнал. Два ноля после синхросигнала, по-видимому, являются идентификатором начала данных – во всяком случае, я ни разу не заметил их изменения. Данные с начальным и конечным синхросигналом дублируются шесть раз. Обмен данными ведётся нибблами.
Для декодирования я решил начинать приём по первому синхросигналу и двум нулям, а завершать по последнему синхросигналу.
Чтобы такой сигнал декодировать, достаточно посчитать длительности между перепадами сигнала.
Я для этого написал простенькую тестовую программу для контроллера Atmega8:
Программа для Atmega8
//----------------------------------------------------------------------------------------------------
//библиотеки
//----------------------------------------------------------------------------------------------------
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
//----------------------------------------------------------------------------------------------------
//частота контроллера
//----------------------------------------------------------------------------------------------------
#define F_CPU 8000000UL
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//макроопределения
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//скорость передачи данных UART, бит/с
#define UART_SPEED 9600UL
//----------------------------------------------------------------------------------------------------
//перечисления
//----------------------------------------------------------------------------------------------------
//тип блока
enum BLOCK_TYPE
{
BLOCK_TYPE_UNKNOW,//неизвестный блок
BLOCK_TYPE_DIVIDER,//разделитель
BLOCK_TYPE_SYNCHRO,//синхросигнал
BLOCK_TYPE_ONE,//единица
BLOCK_TYPE_ZERO//ноль
};
//режим декодирования
enum MODE
{
MODE_WAIT_SYNCHRO,//ожидание синхросигнала
MODE_WAIT_ZERO_FIRST,//ожидание первого нуля
MODE_WAIT_ZERO_SECOND,//ожидание второго нуля
MODE_RECEIVE_DATA//приём данных
};
//----------------------------------------------------------------------------------------------------
//глобальные переменные
//----------------------------------------------------------------------------------------------------
static const uint16_t MAX_TIMER_INTERVAL_VALUE=0xFFFF;//максимальное значение интервала таймера
static volatile bool TimerOverflow=false;//было ли переполнение таймера
static uint8_t Buffer[20];//буфер сборки полубайта
static uint8_t BitSize=0;//количество принятых бит
static uint8_t Byte=0;//собираемый байт
//----------------------------------------------------------------------------------------------------
//прототипы функций
//----------------------------------------------------------------------------------------------------
void InitAVR(void);//инициализация контроллера
void UART_Write(unsigned char byte);//передача символа в COM-порт
void SendText(const char *text);//отправить текст в COM-порт
void RF_Init(void);//инициализация
void RF_SetTimerOverflow(void);//установить флаг переполнения таймера
void RF_ResetTimerOverflow(void);//сбросить флаг переполнения таймера
bool RF_IsTimerOverflow(void);//получить, есть ли переполнение таймера
uint16_t RF_GetTimerValue(void);//получить значение таймера
void RF_ResetTimerValue(void);//сбросить значение таймера
BLOCK_TYPE RF_GetBlockType(uint32_t counter,bool value);//получить тип блока
void RF_AddBit(bool state);//добавить бит данных
void RF_ResetData(void);//начать сборку данных заново
void RF_AnalizeCounter(uint32_t counter,bool value,MODE &mode);//анализ блока
//----------------------------------------------------------------------------------------------------
//основная функция программы
//----------------------------------------------------------------------------------------------------
int main(void)
{
InitAVR();
_delay_ms(200);
SendText("Thermo unit\r\n");
_delay_ms(200);
sei();
while(1);
cli();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//общие функции
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//----------------------------------------------------------------------------------------------------
//инициализация контроллера
//----------------------------------------------------------------------------------------------------
void InitAVR(void)
{
//настраиваем порты
DDRB=0;
DDRD=0;
DDRC=0;
//задаём состояние портов
PORTB=0;
PORTD=0;
PORTC=0;
//устанавливаем режим передачи данных UART
UCSRB=(1<<RXEN)|(1<<TXEN)|(0<<RXCIE);
//RXCIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по завершению приёма по UART разрешено
//TXCIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по завершению передачи по UART разрешено
//UDRIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по опустошению регистра данных UART разрешено
//RXEN=1 : активация приёмника, вывод D0 становится входом UART.
//TXEN=1 : активация передатчика, вывод D1 становится выходом UART.
//CHR9=1 : длина передаваемой посылки с становится равной 11 бит (9 бит данных + старт-стоповый бит + стоп-бит).
//RXB8-расширенный стоп-бит
//TXB8-расширенный стоп-бит
//вычисляем значение регистра скорости передачи данных
unsigned long speed=F_CPU/(16UL);
speed=(speed/UART_SPEED)-1UL;
UBRRH=(speed>>8)&0xff;
UBRRL=speed&0xFF;
RF_Init();
}
//----------------------------------------------------------------------------------------------------
//передача символа в COM-порт
//----------------------------------------------------------------------------------------------------
void UART_Write(unsigned char byte)
{
while(!(UCSRA&(1<<UDRE)));
UDR=byte;
}
//----------------------------------------------------------------------------------------------------
//отправить текст в COM-порт
//----------------------------------------------------------------------------------------------------
void SendText(const char *text)
{
while((*text))
{
UART_Write(*text);
text++;
}
}
//----------------------------------------------------------------------------------------------------
//инициализация
//----------------------------------------------------------------------------------------------------
void RF_Init(void)
{
//настраиваем аналоговый компаратор
ACSR=(0<<ACD)|(1<<ACBG)|(0<<ACO)|(0<<ACI)|(1<<ACIE)|(0<<ACIC)|(0<<ACIS1)|(0<<ACIS0);
//ACD - включение компаратора (0 - ВКЛЮЧЁН!)
//ACBG - подключение к неинвертрирующему входу компаратора внутрреннего ИОН'а
//ACO - результат сравнения (выход компаратора)
//ACI - флаг прерывания от компаратора
//ACIE - разрешение прерываний от компаратора
//ACIC - подключение компаратора к схеме захвата таймера T1
//ACIS1,ACID0 - условие генерации прерывания от компаратора
//настраиваем таймер T1 на частоту 31250 Гц
TCCR1A=(0<<WGM11)|(0<<WGM10)|(0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0);
//COM1A1-COM1A0 - состояние вывода OC1A
//COM1B1-COM1B0 - состояние вывода OC1B
//WGM11-WGM10 - режим работы таймера
TCCR1B=(0<<WGM13)|(0<<WGM12)|(1<<CS12)|(0<<CS11)|(0<<CS10)|(0<<ICES1)|(0<<ICNC1);
//WGM13-WGM12 - режим работы таймера
//CS12-CS10 - управление тактовым сигналом (выбран режим деления тактовых импульсов на 256 (частота таймера 31250 Гц))
//ICNC1 - управление схемой подавления помех блока захвата
//ICES1 - выбор активного фронта сигнала захвата
TCNT1=0;//начальное значение таймера
TIMSK|=(1<<TOIE1);//прерывание по переполнению таймера (таймер T1 шестнадцатибитный)
}
//----------------------------------------------------------------------------------------------------
//установить флаг переполнения таймера
//----------------------------------------------------------------------------------------------------
void RF_SetTimerOverflow(void)
{
cli();
TimerOverflow=true;
sei();
}
//----------------------------------------------------------------------------------------------------
//сбросить флаг переполнения таймера
//----------------------------------------------------------------------------------------------------
void RF_ResetTimerOverflow(void)
{
cli();
TimerOverflow=false;
sei();
}
//----------------------------------------------------------------------------------------------------
//получить, есть ли переполнение таймера
//----------------------------------------------------------------------------------------------------
bool RF_IsTimerOverflow(void)
{
cli();
bool ret=TimerOverflow;
sei();
return(ret);
}
//----------------------------------------------------------------------------------------------------
//получить значение таймера
//----------------------------------------------------------------------------------------------------
uint16_t RF_GetTimerValue(void)
{
cli();
uint16_t ret=TCNT1;
sei();
return(ret);
}
//----------------------------------------------------------------------------------------------------
//сбросить значение таймера
//----------------------------------------------------------------------------------------------------
void RF_ResetTimerValue(void)
{
cli();
TCNT1=0;
sei();
RF_ResetTimerOverflow();
}
//----------------------------------------------------------------------------------------------------
//получить тип блока
//----------------------------------------------------------------------------------------------------
BLOCK_TYPE RF_GetBlockType(uint32_t counter,bool value)
{
static const uint32_t DIVIDER_MIN=(31250UL*12)/44100UL;
static const uint32_t DIVIDER_MAX=(31250UL*25)/44100UL;
static const uint32_t ZERO_MIN=(31250UL*80)/44100UL;
static const uint32_t ZERO_MAX=(31250UL*100)/44100UL;
static const uint32_t ONE_MIN=(31250UL*160)/44100UL;
static const uint32_t ONE_MAX=(31250UL*200)/44100UL;
static const uint32_t SYNCHRO_MIN=(31250UL*320)/44100UL;
static const uint32_t SYNCHRO_MAX=(31250UL*400)/44100UL;
if (counter>DIVIDER_MIN && counter<DIVIDER_MAX) return(BLOCK_TYPE_DIVIDER);//разделитель
if (counter>ZERO_MIN && counter<ZERO_MAX) return(BLOCK_TYPE_ZERO);//ноль
if (counter>ONE_MIN && counter<ONE_MAX) return(BLOCK_TYPE_ONE);//один
if (counter>SYNCHRO_MIN && counter<SYNCHRO_MAX) return(BLOCK_TYPE_SYNCHRO);//синхросигнал
return(BLOCK_TYPE_UNKNOW);//неизвестный блок
}
//----------------------------------------------------------------------------------------------------
//добавить бит данных
//----------------------------------------------------------------------------------------------------
void RF_AddBit(bool state)
{
if ((BitSize>>2)>=19) return;//буфер заполнен
Byte<<=1;
if (state==true) Byte|=1;
BitSize++;
if ((BitSize&0x03)==0)
{
Buffer[(BitSize>>2)-1]=Byte;
Byte=0;
}
}
//----------------------------------------------------------------------------------------------------
//начать сборку данных заново
//----------------------------------------------------------------------------------------------------
void RF_ResetData(void)
{
BitSize=0;
Byte=0;
}
//----------------------------------------------------------------------------------------------------
//анализ блока
//----------------------------------------------------------------------------------------------------
void RF_AnalizeCounter(uint32_t counter,bool value,MODE &mode)
{
//узнаем тип блока
BLOCK_TYPE type=RF_GetBlockType(counter,value);
if (type==BLOCK_TYPE_UNKNOW)
{
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
return;
}
if (type==BLOCK_TYPE_DIVIDER) return;//разделитель бесполезен для анализа
//посылка должна начинаться и завершаться синхросигналом
if (mode==MODE_WAIT_SYNCHRO)//ждём синхросигнала
{
if (type==BLOCK_TYPE_SYNCHRO)
{
mode=MODE_WAIT_ZERO_FIRST;
return;
}
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
return;
}
if (mode==MODE_WAIT_ZERO_FIRST || mode==MODE_WAIT_ZERO_SECOND)//ждём два нуля
{
if (type==BLOCK_TYPE_SYNCHRO && mode==MODE_WAIT_ZERO_FIRST) return;//продолжается синхросигнал
if (type==BLOCK_TYPE_ZERO && mode==MODE_WAIT_ZERO_FIRST)
{
mode=MODE_WAIT_ZERO_SECOND;
return;
}
if (type==BLOCK_TYPE_ZERO && mode==MODE_WAIT_ZERO_SECOND)
{
mode=MODE_RECEIVE_DATA;
return;
}
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
return;
}
//принимаем данные
if (type==BLOCK_TYPE_SYNCHRO)//приём окончен
{
uint8_t size=(BitSize>>2);
char str[30];
if (size!=10)
{
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
return;
}
//выдаём блок
for(uint8_t n=0;n<size;n++)
{
uint8_t b=Buffer[n];
uint8_t mask=(1<<3);
for(uint8_t m=0;m<4;m++,mask>>=1)
{
if (b&mask) SendText("1");
else SendText("0");
}
SendText(" ");
}
uint8_t channel=Buffer[2]&0x03;
uint8_t key=(Buffer[8]>>3)&0x01;
uint8_t h=(Buffer[7]<<4)|(Buffer[6]);//влажность
int16_t temp=(Buffer[5]<<8)|(Buffer[4]<<4)|(Buffer[3]);//температура
int16_t k=18;
int16_t t=(10*(temp-1220))/k;
sprintf(str,"%i",key);
SendText("Key:");
SendText(str);
sprintf(str,"%i",channel+1);
SendText(" Ch:");
SendText(str);
sprintf(str,"%i",h);
SendText(" H:");
SendText(str);
SendText("%, T:");
if (t<0)
{
t=-t;
sprintf(str,"-%i.%i",(int)(t/10),(int)(t%10));
}
else
{
sprintf(str,"%i.%i",(int)(t/10),(int)(t%10));
}
SendText(str);
SendText(" C\r\n");
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
return;
}
//приём данных
if (type==BLOCK_TYPE_ONE)
{
RF_AddBit(true);
return;
}
if (type==BLOCK_TYPE_ZERO)
{
RF_AddBit(false);
return;
}
mode=MODE_WAIT_SYNCHRO;
RF_ResetData();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//обработчики векторов прерываний
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//----------------------------------------------------------------------------------------------------
//обработчик вектора прерывания таймера T1 (16-ми разрядный таймер) по переполнению
//----------------------------------------------------------------------------------------------------
ISR(TIMER1_OVF_vect)
{
RF_SetTimerOverflow();
}
//----------------------------------------------------------------------------------------------------
//обработчик вектора прерывания от компаратора
//----------------------------------------------------------------------------------------------------
ISR(ANA_COMP_vect)
{
ACSR&=0xFF^(1<<ACIE);//запрещаем прерывания
ACSR|=(1<<ACI);//сбрасываем флаг прерывания компаратора
static MODE mode=MODE_WAIT_SYNCHRO;
//узнаём длительность интервала
uint16_t length=RF_GetTimerValue();
if (RF_IsTimerOverflow()==true) length=MAX_TIMER_INTERVAL_VALUE;//было переполнение, считаем интервал максимальным
RF_ResetTimerValue();
//отправляем на анализ
bool value=true;
if (ACSR&(1<<ACO)) value=false;
RF_AnalizeCounter(length,value,mode);
ACSR|=(1<<ACIE);//разрешаем прерывания
}
Выход приёмника подключается к выводу 13 (AIN1). Atmega через max232 подключается к COM-порту компьютера (ну или к переходнику USB-COM). Скорость работы порта 9600 бод.
После декодирования получится следующий поток данных (два начальных ноля я выбрасываю):
//без кнопки, канал 1
1100 1100 0000 1110 1000 0110 1100 0001 0000 1001 Влажность:28% Температура:25.4
//без кнопки, канал 2
1100 1100 0001 1110 1000 0110 1101 0001 0000 0110 Влажность:29% Температура:25.4
Итого, пакет выглядит так:

I0-I7 – идентификатор термометра. При каждом новом включении термометра идентификатор меняется.
C0-C1 — канал (всего их возможно 3). Каналы нумеруются с нуля.
H0-H7 — влажность. Влажность в процентах считывается как есть, а вот температура (T0-T11) почему-то задана в необычном для метеостанций формате. Судя по найденным мной описаниям протоколов обмена различных метеостанций, можно было бы ожидать температуру в десятых долях градуса и со смещением нижнего предела измерения термометра. Так вот, нет. Эксперименты показали, что код температуры данной метеостанции переводится в градусы Цельсия как (T-1220)/18. Откуда эти магические числа знают только китайцы, придумавшие этот протокол обмена.
Как подсказал wolowizard в комментариях, станция передаёт температуру в десятых долях градусов Фаренгейта, поэтому осмысленный перевод в градусы Цельсия будет 0.1*(T-320)*5/9-500=0.1*(T-1220)/1.8.
Бит K соответствует нажатию на кнопку TEST.
Назначение остальных полей установить не удалось, но выяснилось, что значение переключателя Фаренгейты/Цельсии на термометре в протокол обмена не попадает. Предположительно так же последний ниббл (а может, и часть предпоследнего) является CRC, но вычислить алгоритм мне пока не удалось (есть подозрение, что в вычислении участвуют строки и столбцы нибблов). Если кто-нибудь сумеет разгадать эту загадку, соо��щите, пожалуйста, алгоритм вычисления.
Для желающих поломать голову, но не имеющих такого термометра, привожу таблицу принятых данных.
Таблица
1001 0110 0101 1011 1000 0110 1000 0010 0001 1111 Key:0 Ch:2 H:40%, T:25.2 C
1001 1001 0000 1101 1010 0100 0101 0101 0000 0110 Key:0 Ch:1 H:85%, T:-1.2 C
1001 0110 0101 1100 1000 0110 1010 0010 0001 0100 Key:0 Ch:2 H:42%, T:25.3 C
1001 0110 1001 0110 0111 0110 1101 0001 0010 1111 Key:0 Ch:2 H:29%, T:24.1 C
1001 0110 1001 0000 0111 0110 1101 0001 0010 1000 Key:0 Ch:2 H:29%, T:23.7 C
1001 0110 1001 0010 0101 0110 1110 0001 0010 1111 Key:0 Ch:2 H:30%, T:22.1 C
1001 0110 1001 1001 0011 0110 1110 0001 0010 1100 Key:0 Ch:2 H:30%, T:20.7 C
1001 0110 1001 1111 0001 0110 1111 0001 0010 1010 Key:0 Ch:2 H:31%, T:19.2 C
1001 0110 0101 1001 0000 0110 0001 0010 0010 1000 Key:0 Ch:2 H:33%, T:18.0 C
1001 0110 0101 0010 1111 0101 0010 0010 0010 0111 Key:0 Ch:2 H:34%, T:16.7 C
1001 0110 0101 0100 1110 0101 0010 0010 0010 0010 Key:0 Ch:2 H:34%, T:16.0 C
1001 0110 0101 0100 1101 0101 0011 0010 0010 0001 Key:0 Ch:2 H:35%, T:15.1 C
1001 0110 0101 1100 1100 0101 0100 0010 0010 1110 Key:0 Ch:2 H:36%, T:14.6 C
1001 0110 0101 1111 1011 0101 0101 0010 0010 1111 Key:0 Ch:2 H:37%, T:13.9 C
1001 0110 0101 0011 1011 0101 0101 0010 0010 0001 Key:0 Ch:2 H:37%, T:13.2 C
1001 0110 0101 1001 1010 0101 0110 0010 0010 0101 Key:0 Ch:2 H:38%, T:12.7 C
1001 0110 0101 0100 1010 0101 0111 0010 0010 1000 Key:0 Ch:2 H:39%, T:12.4 C
1001 0110 0101 1011 1001 0101 0111 0010 0010 1010 Key:0 Ch:2 H:39%, T:11.9 C
1001 0110 0101 0011 1001 0101 1000 0010 0010 1001 Key:0 Ch:2 H:40%, T:11.5 C
1001 0110 0101 1011 1000 0101 1000 0010 0010 1110 Key:0 Ch:2 H:40%, T:11.0 C
1001 0110 0101 0111 1000 0101 1001 0010 0010 0101 Key:0 Ch:2 H:41%, T:10.8 C
1001 0110 0101 1111 0111 0101 1001 0010 0010 1101 Key:0 Ch:2 H:41%, T:10.3 C
1001 0110 0101 0111 0111 0101 1010 0010 0010 0111 Key:0 Ch:2 H:42%, T:9.9 C
1001 0110 0101 0001 0111 0101 1011 0010 0010 0101 Key:0 Ch:2 H:43%, T:9.6 C
1001 0110 0101 1011 0110 0101 1100 0010 0010 0110 Key:0 Ch:2 H:44%, T:9.2 C
1001 0110 0101 1000 0110 0101 1100 0010 0010 1100 Key:0 Ch:2 H:44%, T:9.1 C
1001 0110 0101 0011 0110 0101 1101 0010 0010 0110 Key:0 Ch:2 H:45%, T:8.8 C
1001 0110 0101 1001 0101 0101 1110 0010 0010 0110 Key:0 Ch:2 H:46%, T:8.2 C
1001 0110 0101 0101 0101 0101 1111 0010 0010 1101 Key:0 Ch:2 H:47%, T:8.0 C
1001 0110 0101 0010 0101 0101 1111 0010 0010 1100 Key:0 Ch:2 H:47%, T:7.8 C
1001 0110 0101 1110 0100 0101 1111 0010 0010 0000 Key:0 Ch:2 H:47%, T:7.6 C
1001 0110 0101 1100 0100 0101 1111 0010 0010 1100 Key:0 Ch:2 H:47%, T:7.5 C