Разбор протокола передачи с метеостанции MiSOL WH2310

Gex7772

✩✩✩✩✩✩✩
21 Май 2019
22
1
А увидел уже протокол) не по глазам было
 

efko

✩✩✩✩✩✩✩
22 Июн 2019
2
3
всё нормально работало, а тут холода пошли и на отрицательных значениях муть показывает
Пусть и через пару лет, но все равно выложу исправленный чуть код, может кому пригодится.

C++:
#include <TimeLib.h>
#include <Wire.h>

float METEO_TEMP = 0;
uint8_t METEO_HUM = 0;
float METEO_wind_speed = 0;
uint8_t METEO_wind_dir = 0;
uint8_t count = 0;
volatile uint8_t res[225];
volatile uint8_t flag = 0;
uint8_t head_flag = 0;
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen, state;

int intValue;
char header;
boolean recievedFlag, startParse;
unsigned long parseTime;

time_t lasttime_receive_meteo;

#define rxPin_meteo 2 //пин от приемника 433MHz
#define MAX_DELTA 140

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  ;
  pinMode(rxPin, INPUT_PULLUP);
  attachInterrupt(0, read_input, CHANGE);

}


void loop() {
  // put your main code here, to run repeatedly:
  if (flag == 1) //если были данные
  {
    //Serial.println("\n");
    uint16_t tmp = 0;
    for (uint8_t i = 0; i < 8; i++)
    {
      tmp <<= 1;
      tmp |= res[i] & 1;
    };
    //Serial.println(tmp);

    uint8_t crc = 0;
    for (uint8_t i = 96; i < 104; i++)
    {
      crc <<= 1;
      crc |= res[i] & 1;
    };
    //    Serial.print("\ncalc_CRC: ");
    //    Serial.println(calc_CRC());
    //    Serial.print("received CRC: ");
    //    Serial.println(crc);

    if (tmp == 0xF5 && crc == calc_CRC()) { //первый байт должен быть 0xF5 и верный CRC
      //Температура
      int16_t temp_tmp = 0;
      int16_t temp_tmp1 = 0;
      for (uint8_t i = 36; i < 48; i++) //биты температуры
      {
        temp_tmp <<= 1; //смещаем влево
        temp_tmp |= res[i] & 1; //прибавляем младший бит
        temp_tmp1 <<= 1;
        temp_tmp1 |= res[i + 112] & 1; //прибавляем младший бит
      };
      //сверяем значение из двух посылок, если не ок, то пропускаем
      if (temp_tmp == temp_tmp1) {
        if (temp_tmp >= 2048) {
          METEO_TEMP = METEO_TEMP * (1 - KF) + (float)(temp_tmp - 2048) / -10.0 * KF ; //фильтрация скользящее среднее
        }
        else {
          METEO_TEMP = METEO_TEMP * (1 - KF) + (float)(temp_tmp) / 10.0 * KF; //фильтрация скользящее среднее
        }
      }


      //Влажность
      uint8_t hum1 = 0;
      uint8_t hum2 = 0;
      for (uint8_t i = 48; i < 56; i++) //биты влажности
      {
        hum1 <<= 1;
        hum1 |= res[i] & 1;
        hum2 <<= 1;
        hum2 |= res[i + 112] & 1;
      };
      if (hum1 == hum2) {
        METEO_HUM = hum1;
      }


      //скорость ветра
      uint16_t ch_wind1 = 0;
      uint16_t ch_wind2 = 0;

      for (uint8_t i = 56; i < 72; i++) //скорость ветра
      {
        ch_wind1 <<= 1;
        ch_wind1 |= res[i] & 1;
        ch_wind2 <<= 1;
        ch_wind2 |= res[i + 112] & 1;
      };
      if (ch_wind1 == ch_wind2) {
        METEO_wind_speed = METEO_wind_speed * (1 - KF) + ((float)ch_wind1 / 588) * KF; //фильтрация скользящее среднее

      }


      //направление ветра
      uint8_t wind_dir1 = 0;
      uint8_t wind_dir2 = 0;
      for (uint8_t i = 32; i < 36; i++)
      {
        wind_dir1 <<= 1;
        wind_dir1 |= res[i] & 1;
        wind_dir2 <<= 1;
        wind_dir2 |= res[i + 112] & 1;
      };
      if (wind_dir1 == wind_dir2) {
        METEO_wind_dir = wind_dir1;
      }

      //Батарея - не у всех работает почему то, возможно, нужный юит в другом месте посылки, изменить 21 на другое чуть ниже
            if (res[21] == res[21 + 112])
            {
              Serial.print("; Low battery!!!");
            }
lasttime_receive_meteo = RTC.get();
      SerialPrintf("\n\r%i-%02i-%02i %02i:%02i:%02i ", year(), month(), day(), hour(), minute(), second());
      Serial.print(F("Temperature: "));
      Serial.print((METEO_TEMP), 1);
      Serial.print(F("C; Humidity: "));
      Serial.print(METEO_HUM);
      Serial.print(F("%; Wind: "));
      Serial.print(METEO_wind_speed);
      Serial.print(F("m/s; Direction: "));
      switch (METEO_wind_dir) {
        case 0: Serial.print("N"); break;
        case 2: Serial.print("NE"); break;
        case 4: Serial.print("E"); break;
        case 6: Serial.print("SE"); break;
        case 8: Serial.print("S"); break;
        case 10: Serial.print("SW"); break;
        case 12: Serial.print("W"); break;
        case 14: Serial.print("NW"); break;
        default: Serial.print("Error"); break;
      }
    }
    res[0] = 0;
    flag = 0;
    count = 0;
    //sei();


  }
}

boolean CheckValue(unsigned int base, unsigned int value) {
  return ((value == base) || ((value > base) && ((value - base) < MAX_DELTA)) || ((value < base) && ((base - value) < MAX_DELTA)));
}

void read_input() {
  state = digitalRead(rxPin_meteo);
  if (state == HIGH)
    lolen = micros() - prevtime;
  else
    hilen = micros() - prevtime;
  prevtime = micros();

  if (state == LOW)  {
    // по спаду начинаем анализ
    if (CheckValue(240, hilen) && CheckValue(1520, lolen) && head_flag != 2) { //нашли короткий импульс
      head_flag = 1;
    } else if (head_flag != 2) head_flag = 0; //если нет - все заново
    if (CheckValue(2000, hilen) && CheckValue(1520, lolen) && head_flag != 2) { //нашли длинный импульс
      head_flag = 2;
    } else if (head_flag != 2) head_flag = 0; //если нет - все заново
    // голова посылки найдена начинаем прием полезных 224 бит данных
    if (CheckValue(960, hilen) && head_flag == 2) //бит 1 - 960 мс
    {
      res[count] = 1;
      count++;
      //Serial.print("1");
    }
    else if (CheckValue(480, hilen) && head_flag == 2) // бит 0 - 480 мс
    {
      res[count] = 0;
      count++;
      //Serial.print("0");
    }
    if (count == 223) { // отсчитали нужное число бит, все сбрасываем и запрещаем прерывания
      //Serial.print("\n");
      //cli();
      head_flag = 0;
      flag = 1; //уходим в парсинг пакета
      count = 0;
      lolen = 0;
      hilen = 0;
    }
  }
}

int calc_CRC() {
  uint8_t tmp_byte = 0;
  uint16_t tmp_result = 0;
  for (uint8_t j = 0; j < 12; j++) {
    tmp_byte = 0;
    for (uint8_t i = 0; i < 8; i++) {
      tmp_byte <<= 1; //смещаем влево
      tmp_byte |= res[8 * j + i] & 1; //прибавляем младший бит
    }
    tmp_result = tmp_result + tmp_byte;
  }
  return (tmp_result & 0xFF);
}
 
  • Лойс +1
Реакции: Gex7772

DMA8

✩✩✩✩✩✩✩
16 Мар 2024
1
0
Здравствуйте!
Помогите, пожалуйста, разобраться. Есть такая станция TS-6210 c 3 беспроводными датчиками температуры и влажности. Ничего, кроме самого первого кода из первого сообщения в теме, не перехватывало сигналы с этих датчиков. При помощи первого кода удалось хотя бы уловить факт приёма сигнала с датчиков, но приходят они в таком виде, как на картинке. Это порция сообщений за 1 раз от одного датчика. Одна сработка датчика - принята посылка из 6 сообщений. Принимает стабильно с приёмом базы станции. Ничего лишнего не сыпется в эфир. Что с этим сделать можно, как настроится на получение данных?
 

Вложения

Изменено: