Передача температуры с датчиков DHT11, DS18B20 через NRF24L01.

ales2k
Offline
Зарегистрирован: 25.02.2013
Casper17
Offline
Зарегистрирован: 21.06.2013

Подскажите пожалуйста какие библиотеки лучше и проще использовать для этого модуля, что бы организовать сбор информации с нескольких устройст, а так же отправлять на них команды. Планируется организовать один главный блог на Меге и 2-3 устройства с дачиками. Если подскажите уже готовый код с хорошими пояснениями буду очень благодарен вам.

arturmon
Offline
Зарегистрирован: 02.07.2011

ustas пишет:

spa-sam, спасибо - обязательно попробую (как только немного времени свободного появится).

Мне кажется, что коду нехватает немного гибкости - сейчас количество передаваемых данных строго ограничено, а как быть, если у "датчика" больше данных? Можно, конечно, создать длинную структуру и грузить туда все, но это как-то не очень.

Может, взять идею из скетчей в начале ветки?

Поясню, что там:

1. Двусторонний обмен ("база" спрашивает "датчик", а "датчик" потом отвечает).

2. Одна команда позволяет "спросить", сколько датчиков.

3. Дальше можно уже давать "адресный" запрос (т.е. "датчик, какое значение параметра номер ххх")

P.S. в скетчах выше есть еще доп.команда - "сделать измерение", а потом уже "пришли данные", тут уже избыточность.. имхо, "датчик" уже должен иметь значение "наготове".

И еще... датчик, думаю, лучше "будить" для измерения через регулярные промежутки времени (для температуры, например, раз в 10 минут, имхо, будет достаточно)... но только "будить", чтобы измерить и запомнить текущие значения и сразу "спать"... а "отдавать" данные уже тогда, когда база их запросила (nrf24 можно завести на прерывание и по нему уже "будить" МК).

Что скажете? 

Добрый день.

http://habrahabr.ru/post/171613/ это случаем не ваш пост?

очень интересует ваша реализация обмена между датчиком и приемником, но только не через мирф билиотеку, а интересно именно реализация чере NF24.

И если не секрет может покажете как все это работает, а то хабре не очень понятна полная картина к сожалению (

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

http://arduino.ru/forum/programmirovanie/nrf24l01

тут уже обсудили все что только можно и нельзя... со всех сторон и даже разучили движения танца с бубном..:)

arturmon
Offline
Зарегистрирован: 02.07.2011

Puhlyaviy пишет:

http://arduino.ru/forum/programmirovanie/nrf24l01

тут уже обсудили все что только можно и нельзя... со всех сторон и даже разучили движения танца с бубном..:)

Вы мою ссылку на хабр читали? там принцип образования пакета не такой как у маньяка вот я и не вкуриваю как сделать как там, и в той теме ни чего толкового между прочим нет. или как послать данные через мирф или как подлючить nf к ардуино.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

arturmon пишет:

Вы мою ссылку на хабр читали? там принцип образования пакета не такой как у маньяка вот я и не вкуриваю как сделать как там, и в той теме ни чего толкового между прочим нет. или как послать данные через мирф или как подлючить nf к ардуино.

а в мою ссылку читали? там 6 страниц и все расписано :)

ustas
Offline
Зарегистрирован: 12.03.2012

arturmon пишет:

Добрый день.

http://habrahabr.ru/post/171613/ это случаем не ваш пост?

очень интересует ваша реализация обмена между датчиком и приемником, но только не через мирф билиотеку, а интересно именно реализация чере NF24.

И если не секрет может покажете как все это работает, а то хабре не очень понятна полная картина к сожалению (

Да, это мой пост. А что там не понятно? 

Как раз используется библиотека maniacbug, и я там ничего особенно нового не придумал - просто сделал две структуры, с которыми лично мне проще работать.

Какие фунции используются - я подсказал (дал их определение). Реально внутри фукнции отправки стандартное библиотечное:

//отправляем данные по RF24
  bool ok = radio.write( &sensor, sizeof(sensor) ); 

Задавайте конкретные вопросы (но полный код сейчас не покажу - следите за обновлениями тут: http://devicter.blogspot.ru/2013/03/blog-post.html - будет побольше времени, продолжу там "уроки").

arturmon
Offline
Зарегистрирован: 02.07.2011

Ну вот совсем не как в RF24 ) например где у вас заголовок...

bool ok = network.write(header,&message,sizeof(message));

вот из таких мелочей и не могу представить полную картину, если не затруднит покажите пожалуйста как у вас работает сама отправка на мастер устройство...

Наклепал по вашим записям код для клиента... он даже компиилруется но сомнения у меня очень дольшие что это работать будет )

#include <SPI.h>

#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

RF24 radio(9,10);

// структура для параметров и значений
typedef struct{
  float Value;         // значение 
  boolean Status;      // статус - 0-ошибка (false), 1-ок (true)
  char Note[16];       // комментарий
} 
Parameter;

// структура для передачи значений
typedef struct{         
  int SensorID;        // идентификатор датчика
  int CommandTo;       // команда модулю номер ...
  int Command;         // команда
                            // 0 - нет команды или ответ
                            // 1 - получить значение
                            // 2 - установить значение
  int ParamID;         // идентификатор параметра 
  float ParamValue;    // значение параметра
  boolean Status;      // статус 0 - ошибка, 1 - ок
  char Comment[16];    // комментарий
}
Message;

// описание параметров модуля
#define SID 100                        // идентификатор датчика
#define NumSensors 3                   // количество сенсоров (и еще одно обязательное занчение - имя датчика)

Parameter MySensors[NumSensors+1] = {    // описание датчиков (и первичная инициализация)
  NumSensors,1,"Sensor 100: LED",        // в поле "комментарий" указываем пояснительную информацию о датчике и количество сенсоров, 1 в статусе означает "отвечаем на запросы"
  0,0,"value A0",
  0,0,"counter",
  0,0,"set_value",
};
Message sensor; 

boolean sendMasterMessage(int From, int To, int Command, int ParamID, float Value, char* Comment, Message* answer);
//boolean sendSlaveMessage(int From, int ParamID);
bool timeout=0;
unsigned long send_time = 0;

void setup() {
  // put your setup code here, to run once:

}

void loop() {


  if (radio.available()) {
    bool done = false;
    while (!done)
    {
      done = radio.read( &sensor, sizeof(sensor) );
      // если команда этому датчику - обрабатываем
      if (sensor.CommandTo == SID) {
        // исполнить команду (от кого, команда, парметр, комментарий)
        doCommand(sensor.SensorID, sensor.Command, sensor.ParamID, sensor.ParamValue, sensor.Status, sensor.Comment);
      }
    }
  }  
}



void doCommand(int From, int Command, int ParamID, float ParamValue, boolean Status, char* Comment) {
  switch (Command) {
    case 0:
      // ничего не делаем 
      break;
    case 1:
      // читаем и отправляем назад
      sendSlaveMessage(From, ParamID);
      break;
    case 2:
      // устанавливаем
      setValue(From, ParamID, ParamValue, Comment);
      break;
    default:
      break; 
  }
  // ответим "командующему"
  sendSlaveMessage(From, ParamID);

  return;
}

void setValue(int From, int ParamID, float ParamValue, char* Comment) {
}



void sendSlaveMessage(int From, int ParamID) {

  send_time = millis();
  radio.stopListening();
    if ( radio.write( &sensor, sizeof(sensor)) ) {
       printf("Send successful\n\r");
    }
    else {
       printf("Send failed\n\r");
    }

  radio.startListening();
  delay(20);  
    
  while ( radio.available() && !timeout ) {

         radio.read( &sensor, sizeof(sensor));
   
    // Check for timeout and exit the while loop
    if ( millis() - send_time > radio.getMaxTimeout() ) {
         Serial.println("Timeout!!!");
         timeout = 1;
 //        sensor.Status = 1;
     }
      
     delay(10);  
  } 
}

и еще вопрос может более подробно опишете как у вас работают функции sendMasterMessage, sendSlaveMessage.

Буду очень признателен. т.к. у вас еще не готоры уроки 5 и 6 )

ustas
Offline
Зарегистрирован: 12.03.2012

arturmon пишет:

Ну вот совсем не как в RF24 ) например где у вас заголовок...

bool ok = network.write(header,&message,sizeof(message));

вот из таких мелочей и не могу представить полную картину, если не затруднит покажите пожалуйста как у вас работает сама отправка на мастер устройство...

у маньяка было две версии библиотеки - RF24 и RF24network, я использовал первую и там как раз никаких заголовков :) формально я на его базовой библиотеке написал "свою версию сетевого обмена", но это слишком громко сказано.

arturmon
Offline
Зарегистрирован: 02.07.2011

ustas пишет:

arturmon пишет:

Ну вот совсем не как в RF24 ) например где у вас заголовок...

bool ok = network.write(header,&message,sizeof(message));

вот из таких мелочей и не могу представить полную картину, если не затруднит покажите пожалуйста как у вас работает сама отправка на мастер устройство...

у маньяка было две версии библиотеки - RF24 и RF24network, я использовал первую и там как раз никаких заголовков :) формально я на его базовой библиотеке написал "свою версию сетевого обмена", но это слишком громко сказано.

Продуманностью и двухсторонним обменом мне "ваша версия сетевого обмена" и понравилась, но тот простор для творчества который вы оставили слишком велик остался для моего понимания (

Может если не хотите сильно давать огласти то приватно сможете подсказать ? как реаливать ваш фирменный протокол?

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

arturmon пишет:

Продуманностью и двухсторонним обменом мне "ваша версия сетевого обмена" и понравилась, но тот простор для творчества который вы оставили слишком велик остался для моего понимания (

Может если не хотите сильно давать огласти то приватно сможете подсказать ? как реаливать ваш фирменный протокол?

в любой библиотеке для этого чипа есть примеры пинга.. там вроде бы наглядно все показано, как осуществляется послание в любое место :) и в две стороны и в три и метод ретрасляции.. вам нужен конкретно разжеваный код?

arturmon
Offline
Зарегистрирован: 02.07.2011

Puhlyaviy пишет:

arturmon пишет:

Продуманностью и двухсторонним обменом мне "ваша версия сетевого обмена" и понравилась, но тот простор для творчества который вы оставили слишком велик остался для моего понимания (

Может если не хотите сильно давать огласти то приватно сможете подсказать ? как реаливать ваш фирменный протокол?

в любой библиотеке для этого чипа есть примеры пинга.. там вроде бы наглядно все показано, как осуществляется послание в любое место :) и в две стороны и в три и метод ретрасляции.. вам нужен конкретно разжеваный код?


Разжеванный код.... идеальное решение :-) а если серьезно, то посмотрите пожалуйста код который я писал выше помоему в нем чегото не хватает, а чего просто понять не могу... Вроде и не на столько туп так как примеры все у меня работают на базе них сотворил обмен между девайсами, но у меня получается по структуре на устройство. Не очень удобно, а ваш способ идеален , а описание только только кусочки на хабре, вот и обратился к вам...

dmw
Offline
Зарегистрирован: 24.03.2013

Помогите разобраться с NRF24L01+ и Arduino Pro Mini? Здесь описал подробно: http://arduino.ru/forum/apparatnye-voprosy/nrf24l01meganano#comment-36745

Если вкрадце, то проблема в следующем: Код для приемника и передатчиков брал из этой ветки. Однако если в роли передатчика использую Mega2560 - все работает прекрасно, но если заменить на Pro Mini - в эфире тишина.

Схема при этом одна и таже, менял только пины SPI (у меги и минипро они разные). Даже конденсатор припоял, все равно не работает. В чем дело не пойму.

uscr
Offline
Зарегистрирован: 17.08.2012

Не буду создавать новую тему, спрошу здесь.

В сообщении #11 подглядел способ с memcpy для упаковкой строки в структуру для передачи через NRF24L01. Решил научиться передавать структуры, это действительно удобно. Написал два скетча. Передатчик:

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <Communicator.h>

#define SendCommandTimeout 3000
#define ScanTimeout 100

void setup(){
  Serial.begin(115200);
  Mirf.cePin = 9;
  Mirf.csnPin = 10;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();  
  Mirf.setRADDR((byte *)"serv");
  Mirf.payload = sizeof(unsigned long);
  Mirf.config();
  Serial.println("Beginning..."); 
}

void loop() {
  SendRequestStruct request;
  request.Status=0;
  request.Request=123;
  memcpy(&request.Comment, &"test", StringLen);
  Serial.print("Sending ");
  Serial.println((char*)request.Comment);
  Mirf.setTADDR((byte*)"0001");
  Mirf.send((byte *)&request);
  while(Mirf.isSending()){};
  delay(1000);
}

Приёмник:

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <Communicator.h>

#define SendCommandTimeout 3000
#define ScanTimeout 100

void setup(){
  Serial.begin(115200);
  Mirf.cePin = 9;
  Mirf.csnPin = 10;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte*)"0001");
  Mirf.payload = sizeof(unsigned long);
  Mirf.config();
  Serial.println("Beginning ... ");
}

void loop() {
  if(!Mirf.isSending() && Mirf.dataReady()){
    SendRequestStruct request;

    Mirf.getData((byte*)&request);
    Serial.print("Get command: ");
    Serial.print(request.Request);
    Serial.print(" with string: ");
    Serial.println((char*)request.Comment);
    delay(100);
  }

}

В Communicator.h описываются просто структуры, но покажу и его:

#ifndef Communicator
#define Communicator

#define StringLen 20 //Длина строк в структурах

typedef struct _REQUEST_STRUCTS { //Структура запроса

  int Status; //0 - всё ок, 1- ошибка;
  int Request;
  byte Comment[StringLen];

}SendRequestStruct;

typedef struct _ANSWER_STRUCTS { //Структура ответа

 int Status; //0 - всё ок, 1- ошибка;
 int Answer;
 byte Comment[StringLen];

}SendAnswerStruct;

#endif // Communicator

В монитор порта передатчика всё как надо:

Beginning...
Sending test
Sending test
Sending test
Sending test
Sending test
Sending test
Sending test

Приёмник пишет вот что: 

Beginning ... 
Get command: 0 with string:  
Get command: 123 with string: 
Get command: 123 with string: 
Get command: 123 with string: 
Get command: 123 with string: 
Get command: 123 with string: 
Get command: 123 with string: 
Get command: 123 with string: 

После string в мониторе порта отображается пустой квадратик, просто он не скопировался. В первой строке действительно 0, это не ошибка. Что я делаю не так?

 

uscr
Offline
Зарегистрирован: 17.08.2012

uscr пишет:

После string в мониторе порта отображается пустой квадратик, просто он не скопировался. В первой строке действительно 0, это не ошибка. Что я делаю не так?

Увеличение payload дало получить строку до конца. Думал, что payload - это, грубо говоря, размер пакета. Считал, что ардуина общается с модулем на высоких уровнях. Но...нет. Прочитал в комментариях к коду ТС, что: Payload-максимальный размер буфера в байтах. Должен быть не меньше максимальной длинны передаваемых данных и не больше 32(железное ограничение). Но, честно говоря, понятнее не стало. Если бы я передавал массив байтов, то "максимальная длинна передаваемых данных" - один байт, угадал? А если этот массив в структуре, то буфер должен быть уже размером с структуру?

axill
Offline
Зарегистрирован: 05.09.2011

Вы все верно написали - в одном пакете можно передать до 32 байт. Стало быть вне зависимости от того как вы эти байты оформляете в программе - массивом или структурой - за раз можно передать до 32 байт