NRF не передает редкие пакеты
- Войдите на сайт для отправки комментариев
Пт, 02/06/2017 - 17:09
Как только ставлю delay(1000) , NRF перестает работать - статус виден по светодиодам. Это же подтверждается со стороны RX.
IDE версии 1.0.5 r2
#include "nRF24L01.h"
#include <SPI.h>
#include "RF24.h"
const uint64_t pipe = 'ABCDEFG';
uint8_t B_32bytes[32];
// для Mega2560:
RF24 ModuleToTest(49,53); // CE_PIN,SS_PIN
//для Uno другие CE_PIN,SS_PIN:
// RF24 ModuleToTest(8,10);
// для Mega2560:
#define GR_LED 14 // Tx Ok
#define RED_LED 16 // Tx fail
// для UNO другие номера выводов LED:
//#define GR_LED 2
//#define RED_LED 4
void setup(void)
{
ModuleToTest.begin();
//ModuleToTest.setAutoAck(true);
ModuleToTest.setAutoAck(false);
ModuleToTest.setDataRate(RF24_1MBPS);
ModuleToTest.setCRCLength(RF24_CRC_16);
ModuleToTest.setChannel(66);
ModuleToTest.openWritingPipe(pipe);
//ModuleToTest.printDetails();
pinMode(RED_LED, OUTPUT);
pinMode(GR_LED, OUTPUT);
}
void loop(void)
{
switch(ModuleToTest.write(B_32bytes,32))
{ case false: digitalWrite(GR_LED,HIGH); digitalWrite(RED_LED,LOW); break;
case true: digitalWrite(RED_LED,HIGH); digitalWrite(GR_LED,LOW); break;
}
delay(1000); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
Может быть delay() задействует те же прерывания и таймеры, что и библиотека для этого устройства? При delay() < 5 мсек проблема не проявляется.
?? делей - программавообще останавливается в микрконтроллере, а нрф шлет инфу.. и куда он шлет, на деревню дедушке?
// ModuleToTest.setAutoAck(true); ModuleToTest.setAutoAck(false);Поэтому для демонстрации ошибки не важно наличие-отсутствия приемника. В случае AutoAckn(false) считается, что доставлено в любом случае (tx_ok). Но если внести задержку между посылками больше чем delay(15), передача прекращается и включается красный LED "tx_fail".
IDE версии 1.0.5 r2
Может нечаянно сотворили импульный блок питания? Прочтите это: http://arduino.ru/forum/obshchii/lozhnoe-srabatyvanie-pir-datchika-pri-p...
Нет осциллографа, чтобы проверить напряжение питания
Помогите пожалуйста понять в каком направлении искать причину
Short Circuit вам указал направлении.
У вашей программы получается "окно" для приёма всего несколько микросекунд, во время проверки в switch. После этого секунду нечего не принимает, пока работает delay.
Копайте в сторону "Мигаем светодиодом без delay()".
Nosferatu, я не понимаю, можете объяснить мою ошибку попроще?
Приема (подтверждения ?) в программе не должно быть, так как отключено подтверждение передачи:
А если не отключено, то прием подтверждения происходит во время выполнения
и время выполнения write при включенном приеме подтверждения немного больше, чем без подтверждения.
Мое сугубо дилетантсткое предположение, может быть дело в неправильной работе SPI и его сигналов CE и SS ?
По аналогиии с этим сообщением http://arduino.ru/forum/programmirovanie/s-kakim-obemom-rabotaet-bibliot...
Для Mega2560 стандартный SS=53, CE=не знаю какой. Для UNO см в таблице
Condensator, вы во внутрь либы RF24 загляните - при каких условия функция RF24.write() возвращает False? может станет понятнее
Заглянул, но ясности не прибавилось. https://github.com/maniacbug/RF24/issues . Проблема проявляется не только в том, что функция write возвращает false, но и приемник на второй ардуино перестает принимать пакеты.
RF24:write(const void *buf, uint8_t len) , на что влияет модификатор const для void *buf?
код функции RF24:write:
/* Copyright (C) 2011 J. Coliz <maniacbug@ymail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ #include "nRF24L01.h" #include "RF24_config.h" #include "RF24.h" /******************************************************************/ bool RF24::write( const void* buf, uint8_t len ) { bool result = false; // Begin the write startWrite(buf,len); // ------------ // At this point we could return from a non-blocking write, and then call // the rest after an interrupt // Instead, we are going to block here until we get TX_DS (transmission completed and ack'd) // or MAX_RT (maximum retries, transmission failed). Also, we'll timeout in case the radio // is flaky and we get neither. // IN the end, the send should be blocking. It comes back in 60ms worst case, or much faster // if I tighted up the retry logic. (Default settings will be 1500us. // Monitor the send uint8_t observe_tx; uint8_t status; uint32_t sent_at = millis(); const uint32_t timeout = 500; //ms to wait for timeout do { status = read_register(OBSERVE_TX,&observe_tx,1); IF_SERIAL_DEBUG(Serial.print(observe_tx,HEX)); } while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) && ( millis() - sent_at < timeout ) ); // The part above is what you could recreate with your own interrupt handler, // and then call this when you got an interrupt // ------------ // Call this when you get an interrupt // The status tells us three things // * The send was successful (TX_DS) // * The send failed, too many retries (MAX_RT) // * There is an ack packet waiting (RX_DR) bool tx_ok, tx_fail; whatHappened(tx_ok,tx_fail,ack_payload_available); //printf("%u%u%u\r\n",tx_ok,tx_fail,ack_payload_available); result = tx_ok; IF_SERIAL_DEBUG(Serial.print(result?"...OK.":"...Failed")); // Handle the ack packet if ( ack_payload_available ) { ack_payload_length = getDynamicPayloadSize(); IF_SERIAL_DEBUG(Serial.print("[AckPacket]/")); IF_SERIAL_DEBUG(Serial.println(ack_payload_length,DEC)); } // Yay, we are done. // Power down powerDown(); // Flush buffers (Is this a relic of past experimentation, and not needed anymore??) flush_tx(); return result; } /****************************************************************************/Заглянул, но ясности не прибавилось.
тоже заглянул. Во-первых, может
IF_SERIAL_DEBUGвключить, чтобы увидеть какую-то диагностику? И во-вторых, что-то мне кажется. что то что вы отключили ask-пакеты - либа не отслеживает и все равно ждет ответа. Хотя могу ошибаться, смотрел мельком.Ради эксперимента можете добавить ModuleToTest.stopListening(); перед switch() (пишу с телефона, так что лучше могу ошибиться в написании), а если не поможет, то и startListening(...); после
Но цитата из описания классов библиотеки http://maniacbug.github.io/RF24/classRF24.html противоречит этому совету тк в тексте программы внутри switch используется write():
Pipe 0 is also used by the writing pipe. So if you open pipe 0 for reading, and then
startListening(), it will overwrite the writing pipe. Ergo, do an openWritingPipe() again before
write().
Перевод: Pipe 0 также используется как pipe для записи. Таким образом, если открываете pipe 0 для чтения, и затем startListening(), это перепишет pipe трубу для write. Следовательно, сделайте openWritingPipe() опять до write().
void loop(void) { switch(ModuleToTest.write(B_32bytes,32)) { case false: digitalWrite(GR_LED,HIGH); digitalWrite(RED_LED,LOW); break; case true: digitalWrite(RED_LED,HIGH); digitalWrite(GR_LED,LOW); break; } delay(1000); //IF_SERIAL_DEBUGвключить, чтобы увидеть какую-то диагностику? И во-вторых, что-то мне кажется. что то что вы отключили ask-пакеты - либа не отслеживает и все равно ждет ответа. Хотя могу ошибаться, смотрел мельком.Я отключил подтверждение setAutoAck(false) (стр. 27,28 программы в сообщении 1) только в версии опубликованной на форуме, чтобы можно было тестировать программу одной картой NRF.
Если включить подтверждение при помощи setAutoAck(true), то понадобится вторая NRF в качестве приемника, но при этом возникает такая же ошибка и ее синхронно видно как со стороны TX, так и со стороны RX.
SERIAL_DEBUG попробую включить.
Не было возможности еще раз просмотреть даташит. И все равно, я бы посоветовал включить прослушку со всеми необходимыми настройками. У меня работает так и с delay и с millis.
Вы пробовали уменьшать/увеличивать значение delay?
При увеличении задержки в delay() от 15 и выше наблюдаются проблемы из-за которых и создана тема. Вместо delay() ставил длинные циклы операций с float для задержки и появляется эта же проблема.
Я не запаривался с чтением статусов вообще, только прием пакетов. Мой код отличается наличием listening и задержкой между пакетами в пару секунд. А еще ардуино спит 5 минут, в это время питание радио отключено. Соответсвенно после включения надо инициализировать заново. Может и Вам поможет.