Основой данной публикации являются два ранее разработанных скетча: Перехват данных от метеостанции Misol Arduino и Передача данных базовой станции Misol Arduino в локальную сеть и Интернет (Народный мониторинг). Требуется объединить эти два скетча в один и обеспечить отправку метеоданных, перехватываемых из пакета метеостанции Misol, в локальную сеть широковещательным пакетом и на сервер народного мониторинга.
Объединенный скетч
/*
Cкетч:
перехватывает пакеты данных метеостанции Misol;
конфигурирует контроллер W5100 Arduino для работы с протоколом UDP и
передает строку широковещательным пакетом в локальную сеть
и на сервер Народного мониторинга.
*/
#include <Ethernet.h>
#include <EthernetUdp.h>
// ----- ***** ----- ***** ----- NET DATA ----- ***** ----- ***** -----
// ----- ***** ----- LOCAL DATA ----- ***** -----
byte MyMAC[] = { 0x3A, 0xF1, 0x7F, 0xA4, 0x56, 0x7E }; // MAC для идентификации устройства
// сервером народного мониторинга
IPAddress MyIP ( 192, 168, 0, 199 );
IPAddress MyDNS ( 192, 168, 0, 1 );
IPAddress MyGateway ( 192, 168, 0, 1 );
IPAddress MySubnet ( 255, 255, 255, 0 );
unsigned int localPort = 9999; // Порт для приема пакетов UDP
IPAddress NMDNS;
// ----- End LOCAL DATA -----
// ----- ***** ----- Broadcast udp message ----- ***** -----
IPAddress IPBC( 192, 168, 0, 255 );
const unsigned int PORTBC = 8887; // Порт для отправки пакетов UDP
// ----- End Broadcast -----
// ----- ***** ----- NM ----- ***** -----
byte IPNMDNS[4]; //Для DNS
byte IPNM[] = { 185, 245, 187, 136 }; // IP сервера народного мониторинга.
// Не требуется при включении DNS
int portNM = 8283;
String mac, mac_d;
// ----- End NM -----
// ----- ***** ----- End NET DATA ----- ***** -----
EthernetUDP Udp; // Определение UDP
#define LUTime 60000; // Периодичность передачи пакетов локальным пользователям миллисекунды (1 минута)
#define NMTime 300000; // Периодичность передачи пакетов на народный мониторинг миллисекунд (5 минут)
long TxLUTime, TxNMTime;
// ----- ***** ----- Определения перехвата пакета ----- ***** -----
volatile byte bitmas[528];
volatile byte tetramas[132];
byte rxb; // Значение принятого бита
volatile int nbit = 0;
byte nbyte = 0;
byte rxpin = 2; // Назначен пин 2 ExtInt0
volatile byte rxpinold, rxpinnew; // Значения входа
volatile unsigned long timpb, timpe, timp, tpause, timpem ; //Время начала, конца импульса, паузы
volatile byte imprx;
float Temp, TempAv, Hum, AW, GW, RnC;
float TempI[4];
bool TempValid = false;
String RW;
byte DW;
int NDW;
uint16_t Illum;
bool dataHWSRecive = false;
bool dataPreparation = false;
#define CRC3B 40 // Контрольная сумма первых трех байт. Отличается для каждого устройства! Считается по строке приема.
// ----- Конец Определения перехвата пакета -----
// ----- ***** ----- ***** ----- Setup ----- ***** ----- ***** -----
void setup() {
// ----- ***** ----- W5100 ----- ***** -----
Ethernet.begin(MyMAC, MyIP); // Инициализация контроллера W5100 с заданными параметрами
Serial.begin(115200); // Инициализация последовательного порта
while (!Serial) { // Ожидание инициализации последовательного порта
;
}
if (Ethernet.hardwareStatus() == EthernetNoHardware) { // Проверка наличия контроллера W5100
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // Остановка исполнения при отсутствии контроллера W5100
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
Udp.begin(localPort); // Запуск службы UDP
// ----- End W5100 -----
attachInterrupt(0, int0rxreceive, CHANGE); //Подпрограмма обработки принимаемого импульса на 2 DPIN (Interrupt 0)
Serial.begin(115200);
//Разметка для экранного вывода данных
Serial.println(" Sync__ Serial__ Tempera_ Humid AvWin GstWn UK RC_____ LB DW CRC__");
} // ----- End Setup -----
// ----- ***** ----- ***** ----- Loop ----- ***** ----- ***** -----
void loop() {
// ----- ***** ----- Перехват пакета ----- ***** -----
// *** Count Pause ***
tpause = millis() - timpem;
if (imprx == 1 && tpause > 200) {
//****** Вывод пакета данных по тетрадам
Serial.print(": ");
//Сброс массива байтов
for (int i = 0; i < 132; i++) {
tetramas[i] = 0;
}
// *** Преобразование массива бит в массив тетрад
byte nbyte = 0;
byte j = 0;
byte l = 0;
byte k = 8;
for (int i = 0; i < nbit; i++ ) {
tetramas[l] = tetramas[l] + bitmas[i] * k;
k = k / 2;
j++;
if (j == 4) {
j = 0;
l++;
k = 8;
Serial.print(tetramas[l - 1]);
Serial.print(", ");
}
}
Serial.println("***** ");
//***
//Контрольная сумма первых трех тетрад
int sum = 0;
for (byte i = 0; i < 3; i++) {
sum = sum + tetramas[i];
}
//***** Рабочий цикл
if ( sum == CRC3B) {
//Преобразование тетрадных значений в float
//Температура Temp
int q = 256;
byte s = 5;
float Temp = 0;
for (byte i = 0; i < 3; i++) {
Temp = Temp + q * tetramas[i + s];
q = q / 16;
}
Temp = (Temp - 400) / 10;
Serial.print("Temperature = ");
Serial.print(Temp);
Serial.println(" *C");
//Влажность Hum
q = 16;
s = 8;
float Hum = 0;
for (byte i = 0; i < 2; i++) {
Hum = Hum + q * tetramas[i + s];
q = q / 16;
}
Serial.print("Humidity = ");
Serial.print(Hum);
Serial.println(" %");
//Средняя скорость ветра AW
q = 16;
s = 10;
float AW = 0;
for (byte i = 0; i < 2; i++) {
AW = AW + q * tetramas[i + s];
q = q / 16;
}
AW = AW * 0.34;
Serial.print("AW = ");
Serial.print(AW);
Serial.println(" mps");
//Скорость ветра в порыве GW
q = 16;
s = 12;
float GW = 0;
for (byte i = 0; i < 2; i++) {
GW = GW + q * tetramas[i + s];
q = q / 16;
}
GW = GW * 0.34;
Serial.print("GW = ");
Serial.print(GW);
Serial.println(" mps");
// Счетчик осадков Rn
q = 256;
s = 15;
float RnC = 0;
for (byte i = 0; i < 3; i++) {
RnC = RnC + q * tetramas[i + s];
q = q / 16;
}
RnC = RnC * 0.3;
Serial.print("Rain = ");
Serial.print(RnC);
Serial.println(" mm");
// Направление ветра
byte DW = tetramas[19];
Serial.print("DW = ");
Serial.print(DW);
Serial.println(" N");
switch (DW) {
case 0: RW = "N"; break;
case 1: RW = "NNE"; break;
case 2: RW = "NE"; break;
case 3: RW = "ENE"; break;
case 4: RW = "E"; break;
case 5: RW = "ESE"; break;
case 6: RW = "SE"; break;
case 7: RW = "SSE"; break;
case 8: RW = "S"; break;
case 9: RW = "SSW"; break;
case 10: RW = "SW"; break;
case 11: RW = "WSW"; break;
case 12: RW = "WSW"; break;
case 13: RW = "W"; break;
case 14: RW = "NW"; break;
case 15: RW = "NNW"; break;
default: RW = "ND";
}
Serial.print("RW = ");
Serial.println(RW);
NDW = DW * 22.5; //Преобразование к градусам
} //*** Окончание рабочего цикла
//Подготовка нового цикла приема пакета данных
nbit = 0;
imprx = 0;
} // ----- Конец Перехват пакета -----
// ----- ***** ----- Отправка пакета локальным пользователям ----- ***** -----
if (TxLUTime < millis()) { // Передача пакета локальным пользователям
// ----- ***** ----- Формирование строки локальным пользователям ----- ***** -----
String strlip;
strlip = String(Temp) + '#' + String(Hum) + '#' + //Метео параметры
String(AW) + '#' + String(GW) + '#' + String(DW) + '#' + //Ветер
String(RnC); //Осадки
Serial.print("StrLip=: ");
Serial.print(strlip);
// ----- Конец Формирование строки локальным пользователям -----
// ----- ***** ----- Преобразование строки в массив символов ----- ***** -----
uint16_t lenBClip = strlip.length();
Serial.print("\tLen LIP=: ");
Serial.println(lenBClip);
char ttsBClip[lenBClip + 1];
strcpy(ttsBClip, strlip.c_str());
// ----- Конец Преобразование строки в массив символов -----
// ----- ***** ----- Отправка пакета (массива символов) ----- ***** -----
Udp.beginPacket(IPBC, PORTBC);
Udp.write(ttsBClip);
Udp.endPacket();
// ----- Конец Отправка пакета (массива символов) локальным пользователям -----
// ----- ***** ----- Задание времени отправки очередного пакета ----- ***** -----
TxLUTime += LUTime;
// ----- Конец Задание времени отправки очередного пакета -----
} // ---- Конец Передача пакета локальным пользователям ---- -
// ----- Конец Отправка пакета локальным пользователям -----
// ----- ***** ----- Отправка пакета серверу народного мониторинга ----- ***** -----
if (TxNMTime < millis()) {
Serial.println("\nString to NM: ");
String strNM;
strNM = "#" + mac_d + "\n" +
"#MIS_T#" + String(Temp) + "\n"
"#MIS_H#" + String(Hum) + "\n"
"#MIS_AW#" + String(AW) + "\n"
"#MIS_GW#" + String(GW) + "\n"
"#MIS_DW#" + String(NDW) + "\n"
"#MIS_RNC#" + String(RnC) + "\n"
+ "##";
Serial.println(strNM);
uint16_t lenNM = strNM.length();
Serial.print("Len strNM=: ");
Serial.println(lenNM);
char ttsNM[lenNM + 1];
strcpy(ttsNM, strNM.c_str());
Udp.beginPacket(IPNM, portNM);
Udp.write(ttsNM);
Udp.endPacket();
TxNMTime += NMTime;
}
// ----- Конец Отправка пакета серверу народного мониторинга -----
} // ----- Конец Loop -----
// ----- ***** ----- ***** ----- Подпрограммы ----- ***** ----- ***** -----
// ----- ***** ----- Прием импульса ----- ***** -----
void int0rxreceive() {
rxpinold = rxpinnew; //Сохранение предшествующего состояния
rxpinnew = digitalRead(rxpin); //Получение нового значения
//Анализ состояний
if (rxpinold == LOW && rxpinnew == HIGH) { // *** Фронт импульса
//Старт приема импульса
timpb = micros();
}
else if (rxpinold == HIGH && rxpinnew == LOW) // *** Спад импульса
{ //Окончание приема импульса
timpe = micros();
timpem = millis();
timp = timpe - timpb;
if (timp > 450 && timp < 550) {
rxb = 1;
}
else if ( timp > 1250 && timp < 1550) {
rxb = 0;
} //Окончание принятия решения
else {
Serial.print("/ \n");
goto noimp;
}
bitmas[nbit] = rxb; //Присвоение значения бита элементу массива
nbit++; //Определение позиции следующего бита
imprx = 1; // Флаг вывода данных
noimp: {
}
}
} // ------ Конец Прием импульса -----
// ---- ***** ---- Окончание подпрограмм ---- ***** ----
Дальнейшим направлением развития проекта является расширение функциональных возможностей метеостанции MiSol Arduino за счет измерения значений дополнительных параметров: освещенности, индекса ультрафиолетового измерения, плотности пыли и т.д., а также, сопряжение с приемником GPS с целью получения координат и точного времени.