Официальный сайт компании Arduino по адресу arduino.cc
Реализация алгоритма Замбретти для предсказания погоды
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
В рускоязычном сегменте почему то очень мало готовых реализаций данного алгоритма предсказания погоды, да и те на не удобоваримых языках вроде php)) В результате предлагаю версию, сделанную на основе https://github.com/fandonov/weatherstation.
Основной код:
#include "math.h" #define SEALEVELPRESSURE_HPA (1013.25) // Аналог давления 760 мм.рт.ст. int pressureArray[10]={0}; unsigned char counter=0; int altitude=170; unsigned char delta_time=0; #define WeatherClear 1 #define WeatherCloud 2 #define WeatherRain 3 #define WeatherClearCloud 4 #define WeatherWorsening 5 //*************************************************** int calc_zambretti(int curr_pressure, int prev_pressure, int mon){ if (curr_pressure<prev_pressure){ //FALLING if (mon>=4 && mon<=9) //summer { if (curr_pressure>=1030) return 2; else if(curr_pressure>=1020 && curr_pressure<1030) return 8; else if(curr_pressure>=1010 && curr_pressure<1020) return 18; else if(curr_pressure>=1000 && curr_pressure<1010) return 21; else if(curr_pressure>=990 && curr_pressure<1000) return 24; else if(curr_pressure>=980 && curr_pressure<990) return 24; else if(curr_pressure>=970 && curr_pressure<980) return 26; else if(curr_pressure<970) return 26; } else{ //winter if (curr_pressure>=1030) return 2; else if(curr_pressure>=1020 && curr_pressure<1030) return 8; else if(curr_pressure>=1010 && curr_pressure<1020) return 15; else if(curr_pressure>=1000 && curr_pressure<1010) return 21; else if(curr_pressure>=990 && curr_pressure<1000) return 22; else if(curr_pressure>=980 && curr_pressure<990) return 24; else if(curr_pressure>=970 && curr_pressure<980) return 26; else if(curr_pressure<970) return 26; } } else if (curr_pressure>prev_pressure){ //RAISING if (mon>=4 && mon<=9){ //summer if (curr_pressure>=1030) return 1; else if(curr_pressure>=1020 && curr_pressure<1030) return 2; else if(curr_pressure>=1010 && curr_pressure<1020) return 3; else if(curr_pressure>=1000 && curr_pressure<1010) return 7; else if(curr_pressure>=990 && curr_pressure<1000) return 9; else if(curr_pressure>=980 && curr_pressure<990) return 12; else if(curr_pressure>=970 && curr_pressure<980) return 17; else if(curr_pressure<970) return 17; } else //winter { if (curr_pressure>=1030) return 1; else if(curr_pressure>=1020 && curr_pressure<1030) return 2; else if(curr_pressure>=1010 && curr_pressure<1020) return 6; else if(curr_pressure>=1000 && curr_pressure<1010) return 7; else if(curr_pressure>=990 && curr_pressure<1000) return 10; else if(curr_pressure>=980 && curr_pressure<990) return 13; else if(curr_pressure>=970 && curr_pressure<980) return 17; else if(curr_pressure<970) return 17; } } else { if (curr_pressure>=1030) return 1; else if(curr_pressure>=1020 && curr_pressure<1030) return 2; else if(curr_pressure>=1010 && curr_pressure<1020) return 11; else if(curr_pressure>=1000 && curr_pressure<1010) return 14; else if(curr_pressure>=990 && curr_pressure<1000) return 19; else if(curr_pressure>=980 && curr_pressure<990) return 23; else if(curr_pressure>=970 && curr_pressure<980) return 24; else if(curr_pressure<970) return 26; } return 0; } //*************************************************** int station2sealevel(int p, int height, int t){ return (int) ((double) p*pow(1-0.0065*(double)height/(t+0.0065*(double)height+273.15),-5.275)); } //*************************************************** // Вызывать раз в минуту int Weather_Calc(int pressure,int temperature, unsigned char month) { int Z=0; int seapressure = station2sealevel(pressure,altitude,temperature); delta_time++; if (delta_time>10) { delta_time=0; if (counter==10) { for (int i=0; i<9;i++) pressureArray[i]=pressureArray[i+1]; pressureArray[counter-1]=seapressure; } else { pressureArray[counter]=seapressure; counter++; } } Z=calc_zambretti((pressureArray[9]+pressureArray[8]+pressureArray[7])/3,(pressureArray[0]+pressureArray[1]+pressureArray[2])/3, month); // if (pressureArray[9]>0 && pressureArray[0]>0) { if (pressureArray[9]+pressureArray[8]+pressureArray[7]-pressureArray[0]-pressureArray[1]-pressureArray[2]>=3) { //RAISING if (Z<3) return WeatherClear; else if (Z>=3 && Z<=9) return WeatherClearCloud; else if (Z>9 && Z<=17) return WeatherCloud; else if (Z>17) return WeatherRain; } else if (pressureArray[0]+pressureArray[1]+pressureArray[2]-pressureArray[9]-pressureArray[8]-pressureArray[7]>=3) { //FALLING if (Z<4) return WeatherClear; else if (Z>=4 && Z<14) return WeatherClearCloud; else if (Z>=14 && Z<19) return WeatherWorsening; else if (Z>=19 && Z<21) return WeatherCloud; else if (Z>=21) return WeatherRain; } else { //STEADY if (Z<5) return WeatherClear; else if (Z>=5 && Z<=11) return WeatherClearCloud; else if (Z>11 && Z<14) return WeatherCloud; else if (Z>=14 && Z<19) return WeatherWorsening; else if (Z>19) return WeatherRain; } } else { if (seapressure<1005) return WeatherRain; else if (seapressure>=1005 && seapressure<=1015) return WeatherCloud; else if (seapressure>1015 && seapressure<1025) return WeatherClearCloud; else return WeatherRain; } return WeatherWorsening; }
Основная вызываемая функция - Weather_Calc(int pressure,int temperature, unsigned char month) с параметрами pressure - давление в hPa, temperature - температура в цельсиях, целое значение, month - текущий месяц. Вызывать данную функцию нужно раз в минуту. Так же надо указать высоту над уровнем моря в altitude.
Обрабатывать полученное значение можно так:
if(weather==WeatherClear) { if(night) // Вывод луны else // Вывод солнца } if(weather==WeatherCloud) // Вывод только облака if(weather==WeatherRain) { if(temp<2) // Вывод снег else // Вывод дождь } if(weather==WeatherClearCloud) { if(night) // Вывод месяц и облака else // Вывод солнце и облака } if(weather==WeatherWorsening) { if(night) { if(temp<2) // Вывод луна,облака, снег else // Вывод луна, облака, дождь } else { if(temp<2) // Вывод солнце,облака, снег else // Вывод солнце, облака, дождь } }
Где "night==1" признак, что сейчас ночь и "temp==температура на улице". Я temp использую от 0 до значения датчика. По результатам сравнения с прогнозом от станции vitek результаты как правило одинаковые, разница в скорости реакции на изменения и разнице в измерении давлений (у витька давление всегда ниже, чем у bme280). В общем алгоритм вполне жизнеспособен и может применяться на практике. Чудес от него ждать конечно не следует, но вполне вменяемые результаты получить можно.