Глюки библиотеки VirtualWire или что то я делаю не так.
- Войдите на сайт для отправки комментариев
Сб, 25/04/2020 - 14:23
Здравствуйте. Провожу эксперименты по передаче данных на частоте 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, ¶mA, &valueA); kount = atoi(valueA); Serial.print("count: "); Serial.println(count); } } else { Serial.println("ERROR"); // ошибка приема } } //----------------------------------------------------------- void loop(){ timer.run(); } //END--------------------------------------------------------
Наблюдается четкая закономерность, что через 4 принятых сообщений идет разрыв связи. Может кто то знающий подскажет, в чем может быть причина.
У Вас и то, и другое работает с таймером. Кто или что гарантирует синхронизацию? Может в приёмнике выбросить таймер, а пользоваться vw_have_message?
Спасибо Евгений. Всегда ценю Ваши советы. Попробую.
Сделал вот так
стало гораздо лучше, но одиночные ошибки всё равно проскакивают. RCSwitch работает гораздо устойчивей.
Н...да. Стало гораздо лучше в условиях гарантированного приема. В реальных условиях, на границе уверенного приема стало хуже, непонятно принимаются данные или нет. Всё таки считаю что надо оставить опрос по таймеру, и вести учет попыток неполучения данных и выводить ошибку приема. Буду дальше думать.
Н...да. Стало гораздо лучше в условиях гарантированного приема. В реальных условиях, на границе уверенного приема стало хуже, непонятно принимаются данные или нет. Всё таки считаю что надо оставить опрос по таймеру, и вести учет попыток неполучения данных и выводить ошибку приема. Буду дальше думать.
Виртуал-вайр проверяет контрольную сумму и если хоть один символ принят неправильно - сообщение отбрасывается. Естесственно, что в условиях неустойчивого приема вероятность принять сообщение целиком снижается практически до нуля - что вы и наблюдаете. Таймер в ваших условиях прием не улучшит никак, а может только ухудшить.
Таймер можно использовать для учета числа попыток передачи, но не привязывайте к таймеру работу приемника. В приемнике оставьте работу по признаку vw_have_message, а таймером просто считайте интервалы.
Ну и в целом - В условиях неустойчивого приема кардинально улучшить ситуацию можно только аппаратно, никакие программные ухищрения вам не помогут. Если вы пытаетесь связаться из Москвы в Саратов просто вопя из окна - то устраиваете вы сеансы по рассписанию или переходите на аглийский - адресат вас все равно не услвшит :) Воспользуйтесь телефоном...
Ну и в целом - В условиях неустойчивого приема кардинально улучшить ситуацию можно только аппаратно, никакие программные ухищрения вам не помогут. Если вы пытаетесь связаться из Москвы в Саратов просто вопя из окна - то устраиваете вы сеансы по расписанию или переходите на английский - адресат вас все равно не услышит :) Воспользуйтесь телефоном...
Благодарю за развернутый ответ. Но проблема именно в VirtualWire, тот же самый комплект передатчик\приемник в тех же самых условиях но с RCSwitch работает абсолютно устойчиво, за полдня работы ни одного пропуска. Так что дело не в железе.
Блин, ну Вы сравните скорости передачи! Поиграйте этим.
Блин, ну Вы сравните скорости передачи! Поиграйте этим.
Тоже идея. Благодарю.
И по поводу vw_have_message, чем оно принципиально лучше чем vw_get_message. Первое просто сообщает, что есть сообщение(любое, даже мусор), а второе тоже проверяет наличие сообщения, его контрольную сумму и тогда копирует в буфер.
Благодарю за развернутый ответ. Но проблема именно в VirtualWire, тот же самый комплект передатчик\приемник в тех же самых условиях но с RCSwitch работает абсолютно устойчиво, за полдня работы ни одного пропуска. Так что дело не в железе.
RCSwitch не проверят достоверность сообщения. Он просто выводит все подряд, поэтому вам кажется, что он принимает лучше. И за счет отсуствия этой проверки его пакеты в несколько раз короче, что улучшает прием.
Чтобы достоверно сравнить два метода - передавайте заранее определенные комбинации байт и на приемнике проверяйте, принято ли то, что надо. Так вы сможете проверить реальное качество работы RCSwitch - впрлне возможно вы увидите, что он принимает больше пакетов за счет того, что данные передаются с ошибками.
Я передаю через RCSwitch коды пультов 24 бита и работает абсолютно устойчиво.
И по поводу vw_have_message, чем оно принципиально лучше чем vw_get_message.
Исходник посмотрите.