nRF24L01+ передача структуры
- Войдите на сайт для отправки комментариев
Вс, 08/02/2015 - 11:51
Всем привет!
Понимаю, что тема очень избитая, но может ли кто выложить сюда РАБОЧИЙ пример скетчей передатчик + приемник для передачи структуры с произвольными полями (ну или хотяб int,byte,char).
Как дополнение можно проверку получения.
Думаю, многим будет полезна тема, с одной страницей, на которой рабочий ответ на вопрос.
Всем большое спасибо.
Хм...Похоже тема совсем не интересная.
Ладно, вот код передатчика:
#include <SPI.h> #include "RF24.h" #include <digitalWriteFast.h> #include <avr/sleep.h> #include <avr/wdt.h> #define CNT 30 // количество циклов по 8 секунд между "посылками" (30 = 4 минуты между посылками) int count; //переменная для счётчика циклов volatile boolean wdt_tripped=1; // описание параметров модуля #define SID 500 // идентификатор датчика Внешний 1 #define NumSensors 4 // количество сенсоров (и еще одно обязательное занчение - имя датчика) boolean mode = 0; // 0 - нормальный режим (редко отправляем данные и не моргаем), 1 - тестовый режим (данные отправляем раз в 8 секунд и моргаем светодиодом) ///////////////////////////////////////////////////////////////////////////// // создаём структуру для передачи значений typedef struct{ int SensorID; // идентификатор датчика int ParamID; // идентификатор параметра float ParamValue; // значение параметра char Comment[16]; // комментарий } Message; #define LED 9 #define BUTTON 4 // создаем структуру для описания параметров typedef struct{ float Value; // значение char Note[16]; // комментарий } Parameter; int tests=0; ///////////////////////////////////////////////////////////////////////////// Parameter MySensors[NumSensors+1] = { // описание датчиков (и первичная инициализация) NumSensors, "SN3 (in&out)", // в поле "комментарий" указываем пояснительную информацию о датчике и количество сенсоров 0, "TempIN, C", // температура со встроенного датчика 0, "VCC, V", // напряжение питания (по внутренним данным МК) 0, "BATT, Flag", // статус того, что ионистр в порядке (0 - "мертвый", 1 - "живой") 0, "NonameSens" // Данные с любого датчика //0, "TempOUT, C" // температура со внешнего датчика }; Message sensor; ///////////////////////////////////////////////////////////////////////////// //RF24 radio(CE,CSN); RF24 radio(8,7); // выберем две "трубы" (выбираем свои) const uint64_t pipes[2] = { 0xF0F0F0F0A1LL, 0xF0F0F0F0A2LL }; ///////////////////////////////////////////////////////////////////////////// //режим сна для МК void system_sleep() { delay(2); // Wait for serial traffic _SFR_BYTE(ADCSRA) &= ~_BV(ADEN); // Switch ADC off set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); // System sleeps here sleep_disable(); _SFR_BYTE(ADCSRA) |= _BV(ADEN); // Switch ADC on } void wdt_interrupt_mode() { wdt_reset(); WDTCSR |= _BV(WDIE); // Restore WDT interrupt mode } ISR(WDT_vect) { wdt_tripped=1; // set global volatile variable } void setup() { wdt_disable(); wdt_reset(); wdt_enable(WDTO_8S); //пробуждение каждые 8 сек count = 0; // светик pinMode(LED, OUTPUT); radio.begin(); //radio.setPALevel(RF24_PA_HIGH); // Уровень мощности (работает только с версией RF + PA) radio.setDataRate(RF24_250KBPS); // Скорость передачи radio.setRetries(15,15); // номер канала, на котором работаем (подобрать свой) radio.setChannel(ххх); radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); radio.stopListening(); // отключаем режим приёма // при старте включаем "тестовый" режим - данные отправляем часто и моргаем светодиодом mode = 1; } void loop(void) { //тут можно увеличить интервал времени между отправками данных по RF24 за счёт счётчика циклов wdt_interrupt_mode(); if (wdt_tripped) { count++; wdt_tripped = 0; // отправим данные, если уже "пора" if (count == ((mode==1) ? (count) : (CNT))) { calculateValue(); // зажжем светодиод if (mode == 1) { digitalWrite(LED, HIGH); } radio.powerUp(); //подаём питание на NRF24 delay(20); for (int i=1; i<=NumSensors; i++){ sendSensorMessage(i); } radio.powerDown(); // отключаем питание RF24 delay(20); count = 0; // погасим светодиод if (mode == 1) { digitalWrite(LED, LOW); } } } if(tests<10) { mode = 1; tests++; } else { mode = 0; } // спать! system_sleep(); //МК засыпает } // функция вычисления всех значений датчиков void calculateValue(){ // код для получения данных // напряжение питания MySensors[2].Value = ((float) readVcc())/1000.0; // температура встроенного датчика (подлючен на А2) MySensors[1].Value = (((float)analogRead(A2) * MySensors[2].Value / 1024.0) - 0.5)/0.01; // если напряжение больше 2.67В - ионистр "жив" (1) // если меньше - "скоро помрет" (0) MySensors[3].Value = (MySensors[2].Value > 2.67) ? 1 : 0; // температура внешнего датчика (подключен на А1 через разъем "Analog") //MySensors[4].Value = (((float)analogRead(A0) * MySensors[2].Value / 1024.0) - 0.5)/0.01; MySensors[4].Value = 0; return; } // отправить сообщение (идентификатор параметра) void sendSensorMessage(int ParamID) { //подготовим данные в структуру для передачи sensor.SensorID = SID; sensor.ParamID = ParamID; sensor.ParamValue = MySensors[ParamID].Value; memcpy(&sensor.Comment,(char*)MySensors[ParamID].Note, 16); //отправляем данные по RF24 bool ok = radio.write( &sensor, sizeof(sensor) ); delay (20); return; } long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(75); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }Взято тут
Может, кто подскажет структуру в приемнике, функцию приема и передачи принятой информации в структуру?
Спасибо за помощь!
Почитай вот тут http://devicter.blogspot.ru/2013/12/shield-matrix-sensor-node.html
Создание\обьявление структуры для данных
struct struct_data { byte adress; byte data[16]; }; struct_data send_data;Отправка в передатчике: radio.write( &send_data, sizeof(send_data) );
Прием в приемнике: radio.read( &send_data, sizeof(send_data) );
обращение к элементам
send_data.adress, send_data.data[0..16]
Все :)
Создание\обьявление структуры для данных
struct struct_data { byte adress; byte data[16]; }; struct_data send_data;Отправка в передатчике: radio.write( &send_data, sizeof(send_data) );
Прием в приемнике: radio.read( &send_data, sizeof(send_data) );
обращение к элементам
send_data.adress, send_data.data[0..16]
Все :)
До этого я ес-но пробовал, не прокатило так просто. Сейчас еще разок попробую, может, чего из виду упустил.
Проблема была следующая:
в структуре были int и массив, инт приходил нормально, а вот в массиве - мусор.
Ща оживлю в памяти
Хм, получилось. До этого я мучался с mirf, там были напряги с переменной буфера приема (тут на форуме обсуждалось вроде).
А вот с RF24 все завелось, спасибо, roman2712@ma
Вот, у меня работает метеостанция. Библиотека EasyTransferVirtualWire
Внешний блок, передатчик
#include <avr/wdt.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <BH1750FVI.h> //датчик освещенности #include <HTU21D.h> //датчик влажности HTU21C #include <VirtualWire.h> #include <EasyTransferVirtualWire.h> #define TX_PIN 7 // пин подключения передатчика //******************************************************************* BH1750FVI myBH1750; // датчик освещенности BH1750FVI I2C HTU21D myHTU21D; // датчик влажности HTU21D I2C //********************************************************************* float OutTemperature = 0; // Температура на улице float OutHumidity = 0; // Влажность на улице float OutLight = 0; // Освещенность на улице bool interval = true; // переменные и константы для таймеров long timePreviousWDT = 0; // таймер для сброса сторожевого таймера long timePreviousSendInfo = 0; // таймер для отправки данных на локальный экран long PeriodWDT = 4000; // интервал сброса таймера 4 секунды long PeriodSendInfo = 30000; // интервал отправки информации на дисплей 30 секунд EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE{ byte ID; // Идентификатор устройства float OutTemperature; // Температура снаружи float OutHumidity; // Влажность снаружи float OutLight; // Освещенность }; SEND_DATA_STRUCTURE broadcast; void setup() { // Инициализация сторожевого таймера (Watchdog timer) wdt_disable(); delay(8000); wdt_enable(WDTO_8S); // ********************************************************************************** // Инициализация консоли Serial.begin(9600); Serial.println(F("Serial Init")); // Инициализация модуля 433 мГц ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_tx_pin(TX_PIN); // для передачи нога № 7 vw_setup(2000); Serial.println(F("Radio Init")); // Инициализация датчика HTU21D myHTU21D.begin() != true; // Инициализация датчика BH1750 myBH1750.begin() != true; myBH1750.setSensitivity(1.0); sensor_read(); send_info(); } // end setup //******************************************************************** void loop(){ // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера if (millis()-timePreviousWDT >=PeriodWDT) { wdt_reset(); timePreviousWDT = millis(); } // Каждые 30 секунд читаем данные с датчиков и отсылаем данные в эфир 433 if (millis()-timePreviousSendInfo >= PeriodSendInfo) { sensor_read(); send_info(); timePreviousSendInfo = millis(); } } // end loop //************************************************************************************* // функция опроса датчиков void sensor_read() { // Получение освещенности с датчика BH1750 снаружи OutLight = myBH1750.readLightLevel(); // Получение влажности и температуры с датчика HTU21D снаружи OutHumidity = myHTU21D.readHumidity(); OutTemperature = myHTU21D.readTemperature(); // отправка в последовательный порт (строки храняться во флэш-памяти контроллера) Serial.print(F("OutTemperature=")); Serial.println(OutTemperature); // Температура снаружи Serial.print(F("OutHumidity=")); Serial.println(OutHumidity); // Влажность снаружи Serial.print(F("Light=")); Serial.println(OutLight); // Освещенность Serial.println(F("=======================================")); // разделитель Serial.println(); delay(250); } // end sensor_read //************************************************************************************* // функция отправки информации по радио void send_info() { // Отправляем данные в эфир 433 мГц broadcast.ID = 60; broadcast.OutTemperature = OutTemperature; // Температура снаружи broadcast.OutHumidity = OutHumidity;; // Влажность снаружи broadcast.OutLight = OutLight; // Освещенность ET.sendData(); delay(1000); //delay(1000); } //end send_info //*************************************************************************************Приемник:
#include <avr/wdt.h> #include <VirtualWire.h> #include <EasyTransferVirtualWire.h> #include <Wire.h> //#include <LiquidCrystal_I2C.h> #include <Adafruit_BMP280.h> //датчик давления #include <DHT.h> //датчик влажности DHT22 #include <Ethernet.h> #include <Adafruit_Sensor.h> #include <SPI.h> #define TX_PIN 7 // пин подключения приемника #define DHTPIN 6 // пин подключения датчика влажности DHT22 #define DHTTYPE DHT22 // тип датчика влажности DHT22/DHT11 //******************************************************************* Adafruit_BMP280 bme; // датчик давления BMP280 I2C DHT dht(DHTPIN, DHTTYPE); // ассоциация датчика влажности DHT22 //BH1750FVI myBH1750; // датчик освещенности BH1750FVI I2C //HTU21D myHTU21D; // датчик влажности HTU21D I2C //********************************************************************* byte mac[] = {0x44, 0x74, 0x00, 0x00, 0x00, 0x00}; //MAC-адрес Arduino char server[] = "narodmon.ru"; int port = 8283; IPAddress ip(192,168,1,202); EthernetClient client; //********************************************************************* float OutTemperature = 0; // Температура на улице float InTemperature = 0; // Температура в помещении float BlockTemperature; // Температура в блоке float Pressure = 0; // Атмосферное давление float InHumidity = 0; // Влажность в помещении float OutHumidity = 0; // Влажность на улице float OutLight = 0; // Освещенность на улице // 433 reciever data EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE{ byte ID; // Идентификатор устройства float OutTemperature; // Температура снаружи float OutHumidity; // Влажность снаружи float OutLight; // Освещенность }; SEND_DATA_STRUCTURE broadcast; // переменные и константы для таймеров long timePreviousWDT = 0; // таймер для сброса сторожевого таймера long timePreviousSendNarodmon = 0; // таймер для отправки данных на NarodMon long timePreviousReadSensor = 0; // таймер для чтения датчиков long PeriodWDT = 4000; // интервал сброса таймера - 4 секунды long PeriodReadSensor = 30000; // интервал чтения датчиков - 30 секунд long PeriodSendNarodmon = 360000; // интервал отправки информации на Narodmon - 6 минут // Set the LCD address to 0x3F for a 20 chars and 4 line display //LiquidCrystal_I2C lcd(0x3F, 20, 4); void setup(){ // Инициализация сторожевого таймера (Watchdog timer) wdt_disable(); delay(8000); wdt_enable(WDTO_8S); Serial.begin(9600); // initialize the LCD //lcd.begin(); //lcd.backlight(); // Инициализация модуля 433 мГц ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_rx_pin(TX_PIN); vw_setup(2000); vw_rx_start(); // Стартуем сеть, если не дождались данных с DHCP сервера то // присваеваем себе адрес самостоятельно if (Ethernet.begin(mac) == 0) Ethernet.begin(mac, ip); // Инициализация 1-Wire Wire.begin(); delay(200); // Инициализация BMP280 с корректировкой высоты // dps.init(MODE_STANDARD, 3200, true); // Инициализация BMP280 bme.begin(); // Инициализация датчика DHT-22 dht.begin(); } void loop() { // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера if (millis()-timePreviousWDT >=PeriodWDT) { wdt_reset(); timePreviousWDT = millis(); } // Каждые 30 секунд читаем данные с датчиков и отсылаем данные в эфир 433 if (millis()-timePreviousReadSensor >= PeriodReadSensor) { In_sensor_read(); send_console(); timePreviousReadSensor = millis(); } if(ET.receiveData()){ // получение данных с внешних датчиков // происходит по инициативе внешнего блока if(broadcast.ID == 60) { OutTemperature = broadcast.OutTemperature; // Температура на улице OutHumidity = broadcast.OutHumidity; // Влажность на улице OutLight = broadcast.OutLight; // Освещенность на улице } } // Каждые 6 минут отправляем данные на "Народный мониторинг" if (millis() - timePreviousSendNarodmon >= PeriodSendNarodmon) { send_narodmon(); timePreviousSendNarodmon = millis(); } } //******************************************************************************************* void In_sensor_read() { // получение данных с внутренних датчиков // Получение давления и температуры с датчика BMP280 внутри блока Pressure = bme.readPressure()*0.007500637554192; // давление в мм рт.ст. BlockTemperature = bme.readTemperature(); // Получение влажности и температуры с датчика DHT22 внутри помещения InHumidity = dht.readHumidity(); InTemperature = dht.readTemperature(); } //****************************************************************************************** void send_narodmon() { // Подключаемся к серверу "Народный мониторинг" if(client.connect(server, port)) { Serial.print(F("Sending info to Narodmon")); // Начинаем передачу данных // адрес_устройства_в_проекте, имя_устройства, GPS широта, GPS долгота client.print(F("#44-74-00-00-00-00#Meteo\n")); // Температура снаружи client.print(F("#T1#")); client.print(OutTemperature); client.print(F("#Температура\n")); // Влажность снаружи client.print(F("#H1#")); client.print(OutHumidity); client.print(F("#Влажность\n")); // Давление client.print(F("#P1#")); client.print(Pressure); client.print(F("#Давление\n")); // Освещенность client.print(F("#L1#")); client.print(OutLight); client.print(F("#Освещенность\n")); // Влажность в помещении client.print(F("#H2#")); client.print(InHumidity); client.print(F("#Влажность в помещении\n")); // Температура в помещении client.print("#T2#"); client.print(InTemperature); client.print(F("#Температура в помещении\n")); // Температура внутри блока client.print("#T3#"); client.print(BlockTemperature); client.print(F("#Температура в блоке\n")); // Отправляем конец телеграммы client.print(F("##")); Serial.print(F("End sending")); // Даем время отработать Ethernet модулю и разрываем соединение delay(250); client.stop(); } }// end send_narodmon //*********************************************************************** void send_console() { // отправка в последовательный порт (строки храняться во флэш-памяти контроллера) Serial.print(F("OutTemperature=")); Serial.println(OutTemperature); // Температура снаружи Serial.print(F("OutHumidity=")); Serial.println(OutHumidity); // Влажность снаружи Serial.print(F("Pressure=")); Serial.println(Pressure); // Давление Serial.print(F("Light=")); Serial.println(OutLight); // Освещенность Serial.print(F("InTemperature=")); Serial.println(InTemperature); // Температура внутри Serial.print(F("InHumidity=")); Serial.println(InHumidity); // Влажность внутри Serial.print(F("BlockTemperature=")); Serial.println(BlockTemperature); // Температура внутри Serial.println(F("=======================================")); // разделитель Serial.println(); //delay(250); } // end sensor_read