Передача по радиканалу array of float

d00m
Offline
Зарегистрирован: 21.02.2013

привет.

использую две anarduino+MW RF96(LoRa) http://www.anarduino.com/miniwireless/#

к одной подключены 7 термосенсоров  DS18B20.

нужно передавать данные от этих сенсоров на вторую anarduino по радиоканалу.

как уже было проверено - эти MW модули могут работать в двух диапазонах - 433MHz и 915Mhz в зависимости от настроек модуля (setFrequency(915.0); или setFrequency(434.0);

пока все работает на 433Mhz.

для передачи использую стандарный пример rf95_reliable_datagram_server от единственной библиотеки LoRa для Arduino - RadioHead http://www.airspayce.com/mikem/arduino/RadioHead/index.html

 

сам пример работает нормально (в связке с вторым девайсом на котором работает ответная часть - rf95_reliable_datagram_client)

немного поправил код сервера (отправляет данные) и клиента (принимает данные).

на сервере формируется массив float значений для хранения температуры от сенсоров.

10 потому что в идеале должно быть 10 сенсоров. пока есть 7.

float tdata[10];  

Server:

void loop()
{

//sensors >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
getTemp();
Serial.print("T0=");
tdata[0]=temp0/16.0;
Serial.print(tdata[0]);
Serial.print(" T1=");
tdata[1]=temp1/16.0;
Serial.print(tdata[1]);
Serial.print(" T2=");
tdata[2]=temp2/16.0;
Serial.print(tdata[2]);
Serial.print(" T3=");
tdata[3]=temp3/16.0;
Serial.print(tdata[3]);
Serial.print(" T4=");
tdata[4]=temp4/16.0;
Serial.print(tdata[4]);
Serial.print(" T5=");
tdata[5]=temp5/16.0;
Serial.print(tdata[5]);
Serial.print(" T6=");
tdata[6]=temp6/16.0;
Serial.println(tdata[6]);

//int i;
//for (i=0;i<10;i++) {
//Serial.print(tdata[i]);
//}

delay(1000);
//sensors <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  if (manager.available())
  {
    Serial.println(">>>>> manager available");
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (manager.recvfromAck(buf, &len, &from))
    {
      Serial.print("got request from : 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);

      // Send a reply back to the originator client
      //if (!manager.sendtoWait(data, sizeof(data), from))
      //  Serial.println("sendtoWait failed");

      if (!manager.sendtoWait((uint8_t*)&tdata, sizeof(tdata), from))
        Serial.println("sendtoWait failed");
    }
  }
  else Serial.println(">>>>> manager not available");

  /////////////////////////////
      Serial.print("sizeof(buf): ");
      Serial.println(sizeof(buf));

    for (byte i = 0; i < 10; i++)
      {
      //Serial.println(*(float *)&buf[i]);
      //Serial.print('\t');
      Serial.print("T");
      Serial.print(i);
      Serial.print(": ");
      Serial.println(tdata[i]);
      }
  /////////////////////////////

}

 

вывод сервера на консоль такой:

T0=25.94 T1=23.25 T2=23.25 T3=23.50 T4=23.50 T5=24.25 T6=85.00
                
>>>>> manager available
                                                       
got request from : 0x1: Hello World!
                                          
sizeof(buf): 251
                                                              
T0: 25.94
                                                                     
T1: 23.25
                                                                     
T2: 23.25
                                                                     
T3: 23.50
                                                                     
T4: 23.50
                                                                     
T5: 24.25
                                                                     
T6: 85.00
                                                                     
T7: 0.00
                                                                      
T8: 0.00
                                                                      
T9: 0.00
         

 

тут не совсем понятно почему размер буфера 251 байт.

ведь сама tdata должна занимать 10*4 байта - то есть 40 байт

отсюда и растут дальнейшие непонятки - мне нужно передать этот массив, получить на Клиенте и там вывести в консоль для начала.

 

 

d00m
Offline
Зарегистрирован: 21.02.2013

впрочем код для Client который номрально принимает и выводит данные:

float rtdata[10];

void loop()
{
  Serial.println("Sending to rf95_reliable_datagram_server");

  // Send a message to manager_server
  if (manager.sendtoWait(data, sizeof(data), SERVER_ADDRESS))
  {
    // Now wait for a reply from the server
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (manager.recvfromAckTimeout(buf, &len, 2000, &from))
    {
      Serial.print("got reply from : 0x");
      Serial.println(from, HEX);
//      Serial.print(": ");
//      Serial.println((char*)buf);
//      Serial.println(*(float*)buf);
//      Serial.println(*(float*)buf[1]);

      Serial.print("sizeof(buf): ");
      Serial.println(sizeof(buf));

/*// memcpy variant >>>>>>>>>>
    memcpy(rtdata,buf,sizeof(buf));
    for (byte i = 0; i < 10; i++)
      {
      Serial.print("T");
      Serial.print(i);
      Serial.print(":");
      Serial.println(rtdata[i]);
      }
// memcpy variant <<<<<<<<<<
*/

// direct via for loop >>>>>>>>>>
    for (byte i = 0; i < 40; i=i+4)
      {
      Serial.print("T");
      Serial.print(i);
      Serial.print(":");
      Serial.println(*(float *)&buf[i]);
      //Serial.print('\t');
      }
// direct via for loop <<<<<<<<<<

// direct >>>>>>>>>>
/*    Serial.print(*(float *)&buf[0]);
    Serial.print(", ");
    Serial.print(*(float *)&buf[1]);
    Serial.print(", ");
    Serial.print(*(float *)&buf[2]);
    Serial.print(", ");
    Serial.println(*(float *)&buf[3]);

    Serial.print(*(float *)&buf[4]);
    Serial.print(", ");
    Serial.print(*(float *)&buf[5]);
    Serial.print(", ");
    Serial.print(*(float *)&buf[6]);
    Serial.print(", ");
    Serial.println(*(float *)&buf[7]);
// direct <<<<<<<<<< */ }  

else { Serial.println("No reply, is rf95_reliable_datagram_server running?"); } } else Serial.println("sendtoWait failed"); delay(500); }

 

sizeoff показывает, что в буфере принято тоже 251 байт, ok.

как видно из кода я пытался несколькими способами выводить данные:

Sending to rf95_reliable_datagram_server
goSending to rf95_reliable_datagram_server
sendtoWait failed                                                             
Sending to rf95_reliable_datagram_server                                      
sendtoWait failed                                                             
Sending to rf95_reliable_datagram_server                                      
sendtoWait failed                                                             
Sending to rf95_reliable_datagram_server                                      
çoSending to rf95_reliable_datagram_server    
 
в начале некоторый строк было видно некий мусор.
причем если закоментить в коде эту часть:
      //Serial.print("T");
      //Serial.print(i);
      //Serial.print(":");

то сами данные о температуре  Serial.println(rtdata[i]); печатались нормально.

с чего я и сделал вывод, что тут проблема с какимито задержками.

 

далее был вариант direct - обращение напрямую к каждой ячейке полученного массива, тут и начались странности с размером буфера, о которых я и пишу этот топик:

Sending to rf95_reliable_datagram_server                                      
got reply from : 0x2                                                          
26.94, 0.00, -0.00, -1073750144.00                                            
25.81, 0.00, 0.00, -134218768.00                                              
Sending to rf95_reliable_datagram_server                                      
got reply from : 0x2                                                          
26.94, 0.00, -0.00, -1073750144.00                                            
25.81, 0.00, 0.00, -134218768.00                                              
Sending to rf95_reliable_datagram_server                                      
got reply from : 0x2                                                          
27.19, 0.00, -0.00, ovf                                                       
26.06, 0.00, -0.00, -1073750144.00                                            
Sending to rf95_reliable_datagram_server                                      
got reply from : 0x2                                                          
27.19, 0.00, -0.00, ovf                                                       
26.06, 0.00, -0.00, -1073750144.00            

как видно ячейки, которые содержат данные о температуре - это buf[0], buf[4], а остальные - это какойто мусор, причем динамично меняющийся..

это меня и натолкнуло на  вариант direct via for loop, вывод которого дал все нужные значения сенсоров:

Sending to rf95_reliable_datagram_server                                      
got reply from : 0x2                                                          
sizeof(buf): 251                                                              
T0:36.31                                                                      
T4:35.75                                                                      
T8:35.63                                                                      
T12:34.81                                                                    
T16:35.19                                                                     
T20:24.19                                                                     
T24:85.00                                                                     
T28:0.00                                                                      
T32:0.00                                                                      
T36:0.00       

цикл до 40 - 40 это как раз те 40 байт, что занимает наш буфер, согласно объявленной переменно массива. и каждая 4-я ячейка хранит нужное значение.

но это все было установлено эмпирическим путем, а хочется понимать что это все значит..

d00m
Offline
Зарегистрирован: 21.02.2013

интересный факт - если в код сервера, в начало цикла loop() добавить задержку delay(5000), то передача данных не срабатывает.

почемуто  участок кода, который и передает буфер с данными

      if (!manager.sendtoWait((uint8_t*)&tdata, sizeof(tdata), from))
        Serial.println("sendtoWait failed");
 
переходит на вывод "sendtoWait failed"
значит manager.sendtoWait становится false..
но почему?
в описании этого метода
сказано вот что:

bool RHReliableDatagram::sendtoWait	(	uint8_t * 	buf,
uint8_t 	len,
uint8_t 	address 
)		
Send the message (with retries) and waits for an ack. Returns true if an acknowledgement is received. Synchronous: any message other than the desired ACK received while waiting is discarded. Blocks until an ACK is received or all retries are exhausted (ie up to retries*timeout milliseconds). If the destination address is the broadcast address RH_BROADCAST_ADDRESS (255), the message will be sent as a broadcast, but receiving nodes do not acknowledge, and sendtoWait() returns true immediately without waiting for any acknowledgements.

 

то есть он должен дождаться ответа от клиента, и ДО добавления этого delay(5000)  ВЫШЕ этого кода все же работало!

я не пойму как оно могло помешать...

код сервера сейчас:

void loop()
{

Serial.println("delay start");
delay(1000);
Serial.println("delay end");

//sensors >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
getTemp();
tdata[0]=temp0/16.0;
tdata[1]=temp1/16.0;
tdata[2]=temp2/16.0;
tdata[3]=temp3/16.0;
tdata[4]=temp4/16.0;
tdata[5]=temp5/16.0;
tdata[6]=temp6/16.0;

byte i;
for (i=0;i<10;i++) {
Serial.print("T");
Serial.print(i);
Serial.print(":");
Serial.print(tdata[i]);
}
Serial.print('\n');

delay(1000);
//sensors <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  if (manager.available())
  {
    Serial.println(">>>>> manager available");
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (manager.recvfromAck(buf, &len, &from))
    {
      Serial.print("got request from client: 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);

      // Send a reply back to the originator client
      //if (!manager.sendtoWait(data, sizeof(data), from))
      //  Serial.println("sendtoWait failed");
      Serial.print("send reply to client#: 0x");
      Serial.println(from, HEX);
      if (!manager.sendtoWait((uint8_t*)&tdata, sizeof(tdata), from))
        Serial.println("sendtoWait failed");
    }
  }
  else Serial.println(">>>>> manager not available");

}

 

 

вывод сервера:

delay start                                                                   
delay end                                                                     
T0:24.81T1:24.44T2:24.37T3:24.50T4:24.62T5:24.62T6:85.00T7:0.00T8:0.00T9:0.00  
                                                                              >>
>>> manager available
                                                         
got request from client: 0x1: *** start ***                                   
send reply to client#: 0x1                                                    
sendtoWait failed
                                                             
delay start                                                                   
delay end                                                                     
T0:24.81T1:24.44T2:24.37T3:24.50T4:24.62T5:24.62T6:85.00T7:0.00T8:0.00T9:0.00  
                                                                              >>
>>> manager available
                                                         
got request from client: 0x1: *** start ***                                   
send reply to client#: 0x1                                                    
sendtoWait failed
                                                             
delay start                                                                   
delay end                                                                     
T0:24.87T1:24.44T2:24.44T3:24.50T4:24.62T5:24.62T6:85.00T7:0.00T8:0.00T9:0.00  
                                                                              >>
>>> manager available
                                                         
got request from client: 0x1: *** start ***                                   
send reply to client#: 0x1                                                    
sendtoWait failed
             

 

d00m
Offline
Зарегистрирован: 21.02.2013

если меняю задержку с 5 сек на 1 сек - delay(1000), то оооочень редко передача все же проходит..

чтото я не понимаю как работает это цикл loop(), раз в нем такие косяки с таймингами..

как может задержка выполнения, по сути процессор поставлен на паузу в начале цикла - как оно может помешать коду, который уже должен выполнятся после этой паузы??

еще странности с другй задержкой - delay(1000) после определения температуры - если ее убрать, то температура не определяется.

тот же феномен, только чуть наоборот - задержка УЖЕ ПОСЛЕ выполнения кода как-то влияет на этот код.. фигня какаято.

может ктото объяснить что это происходит?

nevkon
Offline
Зарегистрирован: 20.01.2015

Переходите с delay на millis. Скорей всего у вас не одним проходом все работает. Или из-за delay возникает проблема сдвига времени реакции.

d00m
Offline
Зарегистрирован: 21.02.2013

спасибо за совет, я про millis уже второй день читаю разные статьи и мануалы.

но все же интересно, почему сейчас все происходит именно так.

можете чутьчуть подробнее рассказать, что вы имеете ввиду под "сдвигом времени реакции" ? 

И как это возможно чтобы оно работало не за один проход (последовательно, я так понял) ?

nevkon
Offline
Зарегистрирован: 20.01.2015

Вместо if (manager.available())

Ставьте что-то вида while (manager.available())

Тогда у вас пока есть соединение цикл будет крутиться.

dimagoreev
Offline
Зарегистрирован: 13.02.2018

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

b707
Offline
Зарегистрирован: 26.05.2017

Дима, вы на даты постов посмотрели? Думаете, через 3 года вам кто-то ответит?

Создайте свою отдельную тему и задайте вопрос.

d00m
Offline
Зарегистрирован: 21.02.2013

обратите внимание на тайминги, если пользуетесь тоже либой RadioHead.

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

так же учтите, что на измерение данных от сенсоров потребуется некоторое время.

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

 

dimagoreev
Offline
Зарегистрирован: 13.02.2018

Спасибо большое за ответ. Я новичок в теме ардуино, но мне нужно разработать свой датчик на лоре, начал работаь в декабре. Использую модули Dragino на 868 МГц. 

Подскажите пожалуйста есть ли адекватное описание на русском языке по библиотеке RH_95 ?

По вашему мнению какой библиотекой для передачи данные посредством LoraWAN лучше всего пользоваться ?

d00m
Offline
Зарегистрирован: 21.02.2013

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

описание либы на русском? а зачем?

в общем я не искал такого, и уверен, что его нет.

на инглише там все понятно и даже с гугл переводчиком.

я использую именно RadiHead и насколько знаю, все ее юзают. даже Dragino своем github сделал форк радиохеад либы и чтото изменил по себя, поэтому лучше ее и скачать.

для LoRaWAN надо еще lmic-стек реализовать на ардуино, а он там весь скромный.

я таким не занимался, но есть и репы и мануалы как это сделать, поищите - их полно.

на TTN например такого добра валом. у меня нет LoRaWAN, только LoRa, я сам делаю в своей сети блекджек со шлюзом)