#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);
}