Официальный сайт компании Arduino по адресу arduino.cc
Протокол UDP для обмена данными между Arduino
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пт, 25/01/2019 - 20:21
Просьба сильно не пинать :) это мой первый проект. UDP протокол выбран как самый простой и быстрый для обмена в стабильных сетях. Пример написан для Arduino Nano + сетевой модуль W5500.
/* Шаблон для обмена данными с помощью UDP пакетов между двумя контроллерами или взаимодествия с мастер контроллером (для Ардуино Нано + сетевой модуль W5500). Можно отправляти и получать биты (флаги 0-1) и байты (целочисленные беззнаковые 0-255), более длинные данные необходмо преобразовывать в байты и обратно. В закоментированных строках взаимосвязанные по скетчу примеры использования передачи данных (управление реле на этом контроллере, отправка флага срабатывания цифрового датчика, отправка данных от датчика температура\влажность и отправка сигнала от нажатия кнопки */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока подключения библиотек */ #include <SPI.h> //для SPI устройств #include <Ethernet2.h> // для сетевого модуля #include <EthernetUdp2.h> // для UDP протокола #include <MsTimer2.h> // для внутреннего времени //#include "DHT.h" //для модулей DHT11,21,22 //#include <OneWire.h> //для 1-wire устройств типа датчика температуры DS18B20 //#include <DallasTemperature.h> // для датчика температуры DS18B20 //#include <Bounce.h> //для кнопок //#include <SD.h> //для SD карты //#include <DS1307RTC.h> //для модуля времени //#include <Time.h> //для работы с датой и веменем //#include <Wire.h> //для I2C /* Конец блока подключения библиотек */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока сетевых настроек */ byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x00}; // мак адрес этого модуля IPAddress ip(192, 168, 1, 2); //ip этого модуля IPAddress ipw(192, 168, 1, 1); //ip второго модуля /* Конец блока сетевых настроек */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока настроек UDP */ EthernetUDP Udp; // объект для приема UDP пакетов. EthernetUDP Udpw; // объект для отправки UDP пакетов. int udp_port = 8888; // порт для UDP #define CON_PACKET_SIZE 10 //размер пакета для обмена данными, количество байтов byte Buffin0[CON_PACKET_SIZE]; // первичный буфер приёма udp пакетов byte Buffin[CON_PACKET_SIZE]; // буфер приема udp пакетов для сравнения /* описание принимаемых данных (// - примеры) in(x) - байт целиком, in(x,y) - бит y в байте x, 0 байт для приема служебных флагов in(0,0) - подтверждение связи //in(1,0) - флаг на включение реле от второго контроллера */ byte Buff[CON_PACKET_SIZE]; // буфер для отправки udp пакетов byte Buff0[CON_PACKET_SIZE]; // буфер udp пакетов для проверки изменений /* описание отправляемых данных (// - примеры) (x) - байт целиком, (x,y) - бит y в байте x, 0 байт для отправки служебных флагов (0,0) - контроль связи //(1,0) - флаг положения реле //(1,1) - флаг цифрового датчика //(1,2) - флаг кнопки //(3) - температура //(4) - влажность (CON_PACKET_SIZE - 1) - идентификатор модуля (последний байт в UDP пакете, значения от 0 до 255) */ boolean otpr; //флаг для отправки UDP пакета byte conok=0; //счетчик минут для проверки связи /* Конец блока настроек UDP */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока выбора пинов */ /* Для использования дополнительных функций смотрите даташит конкретной версии модуля Цифровые пины (D): 0 - RX0; 1 - TX1; 2 - INT0; 3 - INT1,PWM (2,3 "продвинутые" прерывания) 4 - T0; 5 - T1,PWM 6 - AIN0,PWM 7 - AIN1 (6,7 высокочастотный компаратор) 8 - CLKO 9 - PWM 10 - SS 11 - MOSI 12 - MISO 13 - SCK (10,11,12,13 для подключения по SPI) Аналоговые пины на прием (A): A0 - циф-ой 14 A1 - циф-ой 15 A2 - циф-ой 16 A3 - циф-ой 17 A4 - SDA,циф-ой 18 A5 - SCL,циф-ой 19 (A4,A5 для подключения по I2C) A6 A7 (A6,A7 только аналоговые входы) */ //#define PIN_L1 2 // пин на реле управления лампой //#define PIN_DATCH 3 // пин цифрового датчика //#define BUTTON1 4 // пин кнопки //#define DHTPIN A0 // пин датчика температура/влажность /* Конец блока выбора пинов */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока выбора датчика температура/влажность */ //#define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) //DHT dht(DHTPIN, DHTTYPE); //объект датчика температура/влажность /* Конец блока выбора датчика температура/влажность */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока настройки кнопок */ //создаем объект класса Bounce. Указываем пин, к которому подключена кнопка, и время дребезга в мс. //Bounce bouncer1 = Bounce(BUTTON1,5); /* Конец блока настройки кнопок */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока настройки внутренних часов */ byte my_h=0, my_m=0, my_s=0, lmy_h=1, lmy_m=1, lmy_s=1; // внутренние часы, минуты, секунды void mytime() // функция внутренниех часов { my_s++; if (my_s > 59) {my_s = 0; my_m++;} if (my_m > 59) {my_m = 0; my_h++;} if (my_h > 23) my_h = 0; } /* Конец блока настройки внутренних часов */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ void setup() { /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока установки режимов пинов */ //pinMode(PIN_L1,OUTPUT); digitalWrite(PIN_L1, HIGH); //реле //pinMode(PIN_DATCH,INPUT); //датчик //pinMode(BUTTON1,INPUT); //кнопка /* Конец блока установки режимов пинов */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ Ethernet.begin(mac, ip); // запуск сетевого модуля Udp.begin(udp_port); // объект для приема UDP пакетов Udpw.begin(udp_port); // объект для отправки UDP пакетов //dht.begin(); // запуск датчика температура/влажность //Активация внутреннего времени MsTimer2::set(1000, mytime); // прерывание каждую секунду MsTimer2::start(); // первичное заполнение буферов (другие по необходимости) Buff[CON_PACKET_SIZE-1] = 0; //идентификатор модуля (последний байт в UDP пакете, значения от 0 до 255) } void loop() { /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока приема UDP пакетов */ int packetSize = Udp.parsePacket(); if (packetSize) { Udp.read(Buffin0,CON_PACKET_SIZE); if (byte(Buffin0[CON_PACKET_SIZE-1]) == 1) { //если от контроллера с идентификатором 1 /* здесь можно "отлавливать" конкретные изменения во входящих пакетах в момент приема пакета */ //if (bitRead(Buffin0[1],0) && !bitRead(Buffin[1],0)) digitalWrite(PIN_L1, LOW); //включение реле //if (!bitRead(Buffin0[1],0) && bitRead(Buffin[1],0)) digitalWrite(PIN_L1, HIGH); //отключение реле } for (byte i=0; i < CON_PACKET_SIZE; i++) Buffin[i] = Buffin0[i]; // сохранение первичного буфера в буфер для сравнения } /* Конец блока приема UDP пакетов */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Пример для работы с кнопкой */ //if ( bouncer1.update() ) { //если сменилось состояние кнопки // if ( bouncer1.read() == HIGH) { } //если кнопка нажата // if ( bouncer1.read() == LOW) { //если кнопка отпущена // if (bitRead(Buff[1],2)) bitWrite(Buff[1],2,LOW); else if (!bitRead(Buff[1],2)) bitWrite(Buff[1],2,HIGH); //смена значения флага кнопки по нажатию //} //} /* Конец примера для работы с кнопкой */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока работы с внутренним временем */ if (my_s != lmy_s) { // каждую секунду lmy_s = my_s; } if (my_m != lmy_m) { // каждую минуту lmy_m = my_m; if ((bitRead(Buffin[0],0) == 0) && (conok < 255)) conok++; else conok = 0;//сколько минут прошло от последней проверки связи со вторым контроллером if (bitRead(Buffin[0],0)) bitWrite(Buff[0],0,LOW); // флаг для проверки связи на этом модуле bitWrite(Buff[0],0,HIGH); bitWrite(Buff0[0],0,LOW); //флаг для отправки подтверждение связи на второй модуль //Buff[3] = dht.readTemperature(); //чтение c дальнейшей отправкой температуры с датчика DHT //Buff[4] = dht.readHumidity(); //чтение c дальнейшей отправкой влажности с датчика DHT } if (my_h != lmy_h) { // каждый час lmy_h = my_h; } /* Конец блока работы с внутренним временем */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Место для кода "условий" и др.*/ //if (digitalRead(PIN_DATCH)) bitWrite(Buff[1],1,HIGH); else bitWrite(Buff[1],1,LOW); //отправляем значение флага цифрового датчика //if (digitalRead(PIN_L1)) bitWrite(Buff[1],0,HIGH); else bitWrite(Buff[1],0,LOW); //отправляем значение пина реле /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Начало блока отправки пакета если буфер изменился */ for (byte i=0; i < CON_PACKET_SIZE; i++) if (Buff0[i] != Buff[i]) otpr = 1; if (otpr) { Udpw.beginPacket(ipw, udp_port); Udpw.write(Buff, CON_PACKET_SIZE); Udpw.endPacket(); for (byte i=0; i < CON_PACKET_SIZE; i++) Buff0[i] = Buff[i]; otpr = 0; } /* Конец блока отправки пакета если буфер изменился */ /*---------------------------------------------------------------------------------------------------------------------------------------------------*/ delay(100); // задержка от "дребезга". }