Доброго времени суток, год назад приобрёл на Али метеостанцию MiSOL WH2310, у неё имеются выносные датчики дождя, освещённости, уровня ультрафиолетового излучения, скорости и направления ветра, а так же стандартные датчики температуры и влажности, барометр находится в приёмной части, как и в большинстве метеостанций(барометр соберу отдельно).


Она стабильно работает и почти нормально записывает показания в память, раз в неделю, если нужна статистика, приходится подключать её к компьютеру, скачивать данные и обнулять память. И всё бы ничего, но примерно через полгода при достижении уровня памяти более 80% станция начала удалять почти все показания, записать ничего нормально не получалось, а записывать данные каждый день было не очень хорошей идеей, поэтому начал изучать что можно с ней сделать. А предложений было не много, в основном станцию подключали к RaspberryPI по USB и периодически считывали данные, но такой подход мне не подходит, поскольку станция должна быть автономной.
Поэтому я пошёл другим путём - купил на Али приёмник RXB6(изначально пробовал другие, но этот оказался самый стабильный, так же пробовал считывать с Si4432 в режиме RAW, но так и не вышло отфильтровать полезный сигнал). Поскольку осциллограф Hantek 6104BC у меня нормально не смог принять пакетную передачу и буфер у него всего 4кб, пришлось купить китайский логический анализатор, клон Saeale Logic pro, с помощью него и, сначала штатной программы, а затем PulseView, удалось вычислить биты передаваемой информации, где, скорее всего, первые 7 бит это преамбула, здесь единица это импульс 500микросекунд, а ноль 1500микросекунд.


После этого начались поиски примера кода, который учитывает преамбулу, или который даже мог бы расшифровать этот протокол, но он не подходил ни к одному по описанию, RCSwitch его не видел, поскольку тут нет бита синхронизации - вместо него преамбула для подстройки приёмника. В итоге нашёл похожий код, подстроил под себя количество бит преамбулы и данные пошли.
Данные приходили в таком виде: через каждые 59-60 секунд шли 3 пакета, вида:
01110011010001110101010100001011010001011001010001111101 - 56бит данных
каждые 42-43 секунды шел либо один пакет, либо 2, вида:
10101110111100101000100000101001000000100000001100000001001011000000101000110110 - 80 бит данных
____________________________________________________
Вооружившись калькулятором, начал изучать приходящие данные и вычислил следующее - сначала идёт тип датчика, затем его ID, которое меняется при каждой перезагрузке внешнего блока, затем данные отличаются в разных пакетах, приведу их так:
Тип: 10(какой-то внутренний тип)
ID: EF(на самом приёмнике отображается зеркально-FE)
Температура: 648 - надо из суммы вычесть цифру 400(предел измерений от -40 до +50) и разделить на 10, получим +24,8°C
Влажность: 41%
Ветер: 2 - тут сложнее, по формуле надо это значение умножить на 0.34 и затем округлить 2*0.34=0.68=~0.7м/с
Порыв ветра: 3 это 3*0,34=1.02=~1.0м/с
Дождь: 300 - просто счётчик, при достижении предела 0,3мм увеличивается на 1, если за какой-то промежуток времени прошёл дождь, то значение увеличится, если было значение 300, а через час значение 303, значит выпало 0,9мм осадков
Направление ветра: 10 - SW-ЮЗ(Юго-Западный ветер) - пишем таблицу соответствия направления ветра, поскольку индикаторов 16:

0° - 0 n
23° - 1 n-ne
45° - 2 ne
68° - 3 ne-e
90° - 4 e
113° - 5 e-se
135° - 6 se
158° - 7 se-s
180° - 8 s
203° - 9 s-sw
225° - 10 sw
248° - 11 sw-w
270° - 12 w
293° - 13 w-nw
315° - 14 nw
338° - 15 nw-n
CRC: 00110110 = 36 HEX
Следующий пакет:
Тип - 7; ID - 34(HEX)(на самом приёмнике отображается зеркально-43);
Индекс ультрафиолетового освещения: 7, просто показывает индекс, по разным таблицам в интернете разные степени высокого и низкого излучения
??????? - пока непонятная последовательность, всегда одинаковая даже после перезагрузки, возможно, батарейка, но в мануале не заявлена функция отображения разряженной батареи, хоть на экране и имеется соответствующий символ
Освещенность: 738708(Lux) - значение в люксах, на экране отображаются килолюксы,есть внутреннее преобразование в w/m2,но оно не совпадает с формулами
CRC: 01111101 - 7D HEX
____________________________________________________
С данными разобрались, теперь самое интересное - помогите высчитывать CRC, до сих пор ни нашёл ни одного калькулятора, который правильно может это сделать, нашёл документацию, где анализировался похожий датчик, там предлагалась функция CRC8, и, судя по всему, CRC-8-Dallas/Maxim, поскольку там говорилось "The CRC-8 polynomial used is x8 + x5 + x4+ 1". Но почти ни один калькулятор не выдал правильный ответ. И только на единственном cайте при заведении полинома результат совпадает
Исходные данные:
01110011010000000101010100000000000000000000000010111101 > 734055000000 BD последние 2 - CRC
Откидываем CRC, вставляем полином x8 + x5 + x4+ 1 > 100110001(131 в HEX, но как я понял первый бит откидываем, получаем 31, как раз CRC-8-Dallas/Maxim по википедии)
011100110100000001010101000000000000000000000000 > 734055000000, подставляем 16ричное число в онлайн калькулятор и он нам выдаёт BD
Пытаемся повторить в других калькуляторах, получаем всё что угодно, но не BD...............
Помогите разобраться, без CRC из-за помех периодически приходит информация от каких-то левых устройств между посылками, и информация получается неверная


Она стабильно работает и почти нормально записывает показания в память, раз в неделю, если нужна статистика, приходится подключать её к компьютеру, скачивать данные и обнулять память. И всё бы ничего, но примерно через полгода при достижении уровня памяти более 80% станция начала удалять почти все показания, записать ничего нормально не получалось, а записывать данные каждый день было не очень хорошей идеей, поэтому начал изучать что можно с ней сделать. А предложений было не много, в основном станцию подключали к RaspberryPI по USB и периодически считывали данные, но такой подход мне не подходит, поскольку станция должна быть автономной.
Поэтому я пошёл другим путём - купил на Али приёмник RXB6(изначально пробовал другие, но этот оказался самый стабильный, так же пробовал считывать с Si4432 в режиме RAW, но так и не вышло отфильтровать полезный сигнал). Поскольку осциллограф Hantek 6104BC у меня нормально не смог принять пакетную передачу и буфер у него всего 4кб, пришлось купить китайский логический анализатор, клон Saeale Logic pro, с помощью него и, сначала штатной программы, а затем PulseView, удалось вычислить биты передаваемой информации, где, скорее всего, первые 7 бит это преамбула, здесь единица это импульс 500микросекунд, а ноль 1500микросекунд.


После этого начались поиски примера кода, который учитывает преамбулу, или который даже мог бы расшифровать этот протокол, но он не подходил ни к одному по описанию, RCSwitch его не видел, поскольку тут нет бита синхронизации - вместо него преамбула для подстройки приёмника. В итоге нашёл похожий код, подстроил под себя количество бит преамбулы и данные пошли.
C++:
static int pin = 2;
int data[81];
unsigned long sec;
int i1;
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
boolean HCS301_message(){
int duration[7];
byte PreamblePulseCount;
int rs = digitalRead(pin);
if(rs == 0){
return false;
}
// что то поймали, будем анализировать
//Serial.println("Ok");
unsigned long TimeStartReading = micros();
unsigned long PulseStart = TimeStartReading;
unsigned long curpoz = TimeStartReading;
int stat = 1;
int tdur = 0;
PreamblePulseCount = 0;
int i,j;
// ловим преамбулу //////////////////////////////////////////////////////////////////////
// Преамбула состоит из 12 импульсов, типичная длительность 9200 мкс
// Длительность преамбулы 23 базовых импульсов Те, типичный импульс Те 400 мкс
while((curpoz - TimeStartReading) < 20000){
rs = digitalRead(pin);
if (stat != rs) { // состояние изменилось
if(stat == 1 && rs == 0){
// окончание импульса
tdur = curpoz - PulseStart;
if(tdur < 300 || tdur > 600){
break;
}
duration[PreamblePulseCount] = tdur;
PreamblePulseCount ++;
stat = 0;
if(PreamblePulseCount == 7){
break;
}
} else {
// начало импульса
stat = 1;
PulseStart = curpoz;
}
}
curpoz = micros();
}
if(PreamblePulseCount != 7){
return false;
}
Serial.println();
Serial.println("Catch preamble");
// Найдена преамбула/////
int PreambleDuration = micros() - TimeStartReading;
int Te = PreambleDuration / 23;
int mass[81];
bool Reading;
bool Success;
int dur;
// Начинаем читать данные
for(i = 80;i >= 0; i--){
Reading = false;
TimeStartReading = 0;
Success = false;
for(int j=0;j<1000;j++){
rs = digitalRead(pin);
if (rs == 1 && Reading == false){
// начали чтение бита
TimeStartReading = micros();
Reading = true;
};
if (rs == 0 && Reading == true){
// окончили чтение бита
dur = micros() - TimeStartReading;
mass[i] = (dur > (Te / 2 * 3)) ? 0 : 1;
data[i]=mass[i];
Success = true;
Serial.print(mass[i]);
break;
};
};
if(Success == false){
return true;
};
};
}
char *MakeCRC(char *BitString) //не работает, не считает правильно
{
static char Res[9]; // CRC Result
char CRC[8];
int i;
char DoInvert;
for (i=0; i<8; ++i) CRC[i] = 0; // Init before calculation
for (i=0; i<strlen(BitString); ++i)
{
DoInvert = ('1'==BitString[i]) ^ CRC[7]; // XOR required?
CRC[7] = CRC[6];
CRC[6] = CRC[5];
CRC[5] = CRC[4] ^ DoInvert;
CRC[4] = CRC[3] ^ DoInvert;
CRC[3] = CRC[2];
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = DoInvert;
}
for (i=0; i<8; ++i) Res[7-i] = CRC[i] ? '1' : '0'; // Convert binary to ASCII
Res[8] = 0; // Set string terminator
return(Res);
}
void loop() {
// if (millis() - sec > 10000){
// sec = millis();
// char *Data, *Result;
// Data = "01110011010000000101010100000000000000000000000010111101"; //Это пример ночных данных, CRC=BD
// Result = MakeCRC(Data);
// Serial.println(Result);
// }
if (HCS301_message() == true){
// Serial.println(); ////////////////писать обработку данных с датчиков тут
// Serial.println();
// Serial.println("Data:");
// for (i1=80;i1>0;i1--) {Serial.print(data[i1]); data[i1]=0; }
// Serial.println();
// memset(data, 0, 80);
}
}
01110011010001110101010100001011010001011001010001111101 - 56бит данных
каждые 42-43 секунды шел либо один пакет, либо 2, вида:
10101110111100101000100000101001000000100000001100000001001011000000101000110110 - 80 бит данных
____________________________________________________
Вооружившись калькулятором, начал изучать приходящие данные и вычислил следующее - сначала идёт тип датчика, затем его ID, которое меняется при каждой перезагрузке внешнего блока, затем данные отличаются в разных пакетах, приведу их так:
C++:
1010|11101111|001010001000|00101001|00000010|00000011|0000000100101100|00001010|00110110
тип^--ID^--температура^--влажность^----ветер^--порыв^ветра-дождь^--направление^ветра----^CRC(контрольная сумма)
ID: EF(на самом приёмнике отображается зеркально-FE)
Температура: 648 - надо из суммы вычесть цифру 400(предел измерений от -40 до +50) и разделить на 10, получим +24,8°C
Влажность: 41%
Ветер: 2 - тут сложнее, по формуле надо это значение умножить на 0.34 и затем округлить 2*0.34=0.68=~0.7м/с
Порыв ветра: 3 это 3*0,34=1.02=~1.0м/с
Дождь: 300 - просто счётчик, при достижении предела 0,3мм увеличивается на 1, если за какой-то промежуток времени прошёл дождь, то значение увеличится, если было значение 300, а через час значение 303, значит выпало 0,9мм осадков
Направление ветра: 10 - SW-ЮЗ(Юго-Западный ветер) - пишем таблицу соответствия направления ветра, поскольку индикаторов 16:

0° - 0 n
23° - 1 n-ne
45° - 2 ne
68° - 3 ne-e
90° - 4 e
113° - 5 e-se
135° - 6 se
158° - 7 se-s
180° - 8 s
203° - 9 s-sw
225° - 10 sw
248° - 11 sw-w
270° - 12 w
293° - 13 w-nw
315° - 14 nw
338° - 15 nw-n
CRC: 00110110 = 36 HEX
Следующий пакет:
C++:
0111|00110100|0111|01010101|000010110100010110010100|01111101
Тип^--ID^-Индекс^UV--???^????---Освещённость^----------------^CRC(Контрольная сумма)
Индекс ультрафиолетового освещения: 7, просто показывает индекс, по разным таблицам в интернете разные степени высокого и низкого излучения
??????? - пока непонятная последовательность, всегда одинаковая даже после перезагрузки, возможно, батарейка, но в мануале не заявлена функция отображения разряженной батареи, хоть на экране и имеется соответствующий символ
Освещенность: 738708(Lux) - значение в люксах, на экране отображаются килолюксы,есть внутреннее преобразование в w/m2,но оно не совпадает с формулами
CRC: 01111101 - 7D HEX
____________________________________________________
С данными разобрались, теперь самое интересное - помогите высчитывать CRC, до сих пор ни нашёл ни одного калькулятора, который правильно может это сделать, нашёл документацию, где анализировался похожий датчик, там предлагалась функция CRC8, и, судя по всему, CRC-8-Dallas/Maxim, поскольку там говорилось "The CRC-8 polynomial used is x8 + x5 + x4+ 1". Но почти ни один калькулятор не выдал правильный ответ. И только на единственном cайте при заведении полинома результат совпадает
Исходные данные:
01110011010000000101010100000000000000000000000010111101 > 734055000000 BD последние 2 - CRC
Откидываем CRC, вставляем полином x8 + x5 + x4+ 1 > 100110001(131 в HEX, но как я понял первый бит откидываем, получаем 31, как раз CRC-8-Dallas/Maxim по википедии)
011100110100000001010101000000000000000000000000 > 734055000000, подставляем 16ричное число в онлайн калькулятор и он нам выдаёт BD
Пытаемся повторить в других калькуляторах, получаем всё что угодно, но не BD...............
Помогите разобраться, без CRC из-за помех периодически приходит информация от каких-то левых устройств между посылками, и информация получается неверная
Изменено: