Глюки библиотеки VirtualWire или что то я делаю не так.

selan61
Offline
Зарегистрирован: 15.12.2017

Здравствуйте. Провожу эксперименты по передаче данных на частоте  433 МГц передатчиками WL102-341 и приемниками WL101-341, с китайскими спиральными антеннами. Начал с библиотеки RCSwitch. С ней связь была очень устойчивой и не прерывалась на расстоянии  по прямой порядка 10 метров, но через 3 бетонные стены. А вот с библиотекой VirtualWire начались какие то глюки. На столе на расстоянии около метра связь не устойчива, и есть закономерность в обрыве приема. Но в чем причина не могу понять.

Это я передаю.

Send Z,A,57
Send Z,A,58
Send Z,A,59
Send Z,A,60
Send Z,A,61
Send Z,A,62
Send Z,A,63
Send Z,A,64
Send Z,A,65
Send Z,A,66
Send Z,A,67
Send Z,A,68
Send Z,A,69
Send Z,A,70
Send Z,A,71
Send Z,A,72
Send Z,A,73
Send Z,A,74
Send Z,A,75
Send Z,A,76
Send Z,A,77
Send Z,A,78
Send Z,A,79
Send Z,A,80
Send Z,A,81
Send Z,A,82
Send Z,A,83
Send Z,A,84
Send Z,A,85
Send Z,A,86
Send Z,A,87
Send Z,A,88
Send Z,A,89
Send Z,A,90

Код передатчика

/* Передача кода счетчика секунд через VirtualWire
  *  с использованием SimpleTimer
 */
//----------------------------------------------------------- 
#include <VirtualWire.h>
#include <SimpleTimer.h>
//----------------------------------------------------------- 
#define LED_PIN 13           // LED_PIN
#define timer1_Interval 1000 // время (1*1000) милисекунд многократно выполнять функцию Send()
//-----------------------------------------------------------
int count = 0;   //AZ
unsigned int timer1;  // номер таймера
//----------------------------------------------------------- 
 SimpleTimer timer;
//----------------------------------------------------------- 
void setup() {
//настройка virtualWire
   vw_set_tx_pin(12); // пин передачи
   vw_set_rx_pin(11); // пин приема
   vw_set_ptt_inverted(true);
   vw_setup(2000); // скорость передачи данных(бит/с)
   
    Serial.begin(9600);
    
// запускаем таймеры   
   timer1 = timer.setInterval (timer1_Interval, Send); //каждые timer1_Interval выполнять функцию Send()
} 
//----------------------------------------------------------- 
void Send(){    
// формирование данных для для отправки
    char msg[255];  
    String strMsg = "Z";
    strMsg = strMsg + ",";
    strMsg = strMsg + "A";
    strMsg = strMsg + ",";
    strMsg = strMsg + count;
    strMsg = strMsg + "\0";
    strMsg.toCharArray(msg,255);
    digitalWrite(LED_PIN, HIGH);
     Serial.print("Send "); 
     Serial.println(msg);
    vw_send((uint8_t*)msg, strlen(msg)+1);
    vw_wait_tx(); // Ждем пока передача будет окончена
    digitalWrite(LED_PIN, LOW);
    kount ++;
}    
//----------------------------------------------------------- 
void loop(){
     timer.run();
} 
//END--------------------------------------------------------

Это принимаю

kount: 51
kount: 52
kount: 53
kount: 54
ERROR
ERROR
kount: 57
kount: 58
kount: 59
kount: 60
ERROR
kount: 62
kount: 63
kount: 64
kount: 65
ERROR
kount: 67
kount: 68
kount: 69
kount: 70
ERROR
kount: 72
kount: 73
kount: 74
kount: 75
ERROR
kount: 77
kount: 78
kount: 79
kount: 80
ERROR
kount: 82
kount: 83
kount: 84
kount: 85
ERROR
kount: 87
kount: 88
kount: 89
kount: 90

Код приемника

/*Приемник кода по 433МГц
 * с использованием SimpleTimer
*/
#include <VirtualWire.h>
#include <SimpleTimer.h>
//-----------------------------------------------------------
#define timer1_Interval 1000   // время (1*1000) милисекунд многократно выполнять функцию Receiver()
//----------------------------------------------------------- 
uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения
uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера
const int transmit_pin = 12;
const int receive_pin = 11;

char data[20];
char mode[2];
char paramA[2];
char valueA[6];

int count;   //AZ
unsigned int timer1;  // номера таймеров
//----------------------------------------------------------- 
 SimpleTimer timer;
//----------------------------------------------------------- 
void setup() {
   Serial.begin(9600);
  vw_set_tx_pin(transmit_pin);
  vw_set_rx_pin(receive_pin);
  vw_set_ptt_inverted(true); 
  vw_setup(2000);       
  vw_rx_start(); // Начинаем мониторинг эфира

// запускаем таймеры   
    timer1 = timer.setInterval (timer1_Interval, Receiver); // каждые timer1_Interval выполнять функцию Receiver()
}
//----------------------------------------------------------- 
 void Receiver(){
  uint8_t buflen =  VW_MAX_MESSAGE_LEN ;
  
  if (vw_get_message(buf, &buflen)){ // Если принято сообщение
    if (buf[0] == 'Z'){ // Если сообщение Z
       strcpy(data,buf);
       sscanf(data, "%[^','],%[^','],%s",&mode, &paramA, &valueA);
       kount = atoi(valueA);
        Serial.print("count: ");
        Serial.println(count);
       }
    }
    else {
        Serial.println("ERROR"); // ошибка приема
        }  
}
//----------------------------------------------------------- 
void loop(){
     timer.run();
} 
//END--------------------------------------------------------

Наблюдается четкая закономерность, что через 4 принятых сообщений идет разрыв связи. Может кто то знающий подскажет, в чем может быть причина.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

selan61
Offline
Зарегистрирован: 15.12.2017

Спасибо Евгений. Всегда ценю Ваши советы. Попробую.

selan61
Offline
Зарегистрирован: 15.12.2017

Сделал вот так

/*Приемник кода по 433МГц
 * V2-убрал SimpleTimer, вставил vw_have_message
*/
#include <VirtualWire.h>
//----------------------------------------------------------- 
uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения
uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера
const int transmit_pin = 12;
const int receive_pin = 11;

char data[20];
char mode[2];
char paramA[2];
char valueA[6];

int count;   //AZ
//----------------------------------------------------------- 
void setup() {
   Serial.begin(9600);
  vw_set_tx_pin(transmit_pin);
  vw_set_rx_pin(receive_pin);
  vw_set_ptt_inverted(true); 
  vw_setup(2000);       
}
//----------------------------------------------------------- 
 void loop(){
  vw_rx_start(); // начинаем мониторинг эфира
  buflen =  VW_MAX_MESSAGE_LEN ;
  if (vw_have_message()) {  
    if (vw_get_message(buf, &buflen)){ // Если принято сообщение
      vw_rx_stop(); // останавливаем прием и парсим
      if (buf[0] == 'Z'){ // если сообщение Z
         strcpy(data,buf);
         sscanf(data, "%[^','],%[^','],%s",&mode, &paramA, &valueA);
         count = atoi(valueA);
          Serial.print("count: ");
          Serial.println(count);
         }
    }
    else {
        Serial.println("ERROR"); // ошибка приема
        }  
   }
}
//END--------------------------------------------------------

стало гораздо лучше, но одиночные ошибки всё равно проскакивают. RCSwitch работает гораздо устойчивей.

selan61
Offline
Зарегистрирован: 15.12.2017

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

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

selan61 пишет:

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

Виртуал-вайр проверяет контрольную сумму и если хоть один символ принят неправильно - сообщение отбрасывается. Естесственно, что в условиях неустойчивого приема вероятность принять сообщение целиком снижается практически до нуля - что вы и наблюдаете. Таймер в ваших условиях прием не улучшит никак, а может только ухудшить.

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

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

selan61
Offline
Зарегистрирован: 15.12.2017

b707 пишет:

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

Благодарю за развернутый ответ. Но проблема именно в VirtualWire, тот же самый комплект передатчик\приемник в тех же самых условиях но с RCSwitch работает абсолютно устойчиво, за полдня работы ни одного пропуска. Так что дело не в железе.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Блин, ну Вы сравните скорости передачи! Поиграйте этим.

selan61
Offline
Зарегистрирован: 15.12.2017

ЕвгенийП пишет:

Блин, ну Вы сравните скорости передачи! Поиграйте этим.

Тоже идея. Благодарю.

И по поводу vw_have_message, чем оно принципиально лучше чем vw_get_message. Первое просто сообщает, что есть сообщение(любое, даже мусор), а второе тоже проверяет наличие сообщения, его контрольную сумму и тогда копирует в буфер.

 

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

selan61 пишет:

Благодарю за развернутый ответ. Но проблема именно в VirtualWire, тот же самый комплект передатчик\приемник в тех же самых условиях но с RCSwitch работает абсолютно устойчиво, за полдня работы ни одного пропуска. Так что дело не в железе.

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

Чтобы достоверно сравнить два метода - передавайте заранее определенные комбинации байт и на приемнике проверяйте, принято ли то, что надо. Так вы сможете проверить реальное качество работы RCSwitch  - впрлне возможно вы увидите, что он принимает больше пакетов за счет того, что данные передаются с ошибками.

selan61
Offline
Зарегистрирован: 15.12.2017

Я передаю через RCSwitch коды пультов 24 бита и работает абсолютно устойчиво.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

selan61 пишет:
.

И по поводу vw_have_message, чем оно принципиально лучше чем vw_get_message. 

Исходник посмотрите.