Сколько максимум бит/сек можно выжать из этого радиомодуля? Конечно, даташит гордо заявляет нам о 2 МБит/сек, однако если вчитаться, то оказывается, что каждую посылку заново стартует PLL, что приводит к большим потерям. Пользуясь формулами из даташита получил максимальную скорость около 800 КБит/сек.
Интересно, как к ней приблизится.
Сейчас работает тупой алгоритм:
static void NRF24L01_sendNextPacket(NRF24L01_Driver *radio) {
NRF24L01_Packet *packet;
while ((NRF24L01_readStatus(radio) & NRF24L01_STATUS_TX_FULL) == 0) {
if (chMBFetch(&radio->txMailbox, (msg_t*)&packet, TIME_IMMEDIATE) != MSG_OK) break;
if (radio->rxMode) {
NRF24L01_chipDisable(radio);
NRF24L01_andByteReg(radio, NRF24L01_REG_CONFIG, ~NRF24L01_CONFIG_PRIM_RX);
radio->rxMode = FALSE;
//chThdSleepMilliseconds(10);
}
NRF24L01_txPayload(radio, packet->data, packet->size, FALSE);
chHeapFree(packet);
NRF24L01_chipEnable(radio);
//chThdSleepMilliseconds(10);
return;
}
if (NRF24L01_readByteReg(radio, NRF24L01_REG_FIFO_STATUS) & NRF24L01_FIFO_STATUS_TX_EMPTY) {
NRF24L01_startRx(radio);
} else {
NRF24L01_chipEnable(radio);
}
}
Эта функция вызывается, когда в программной очереди отправки появляется очередной пакет, либо приходит прерывания TX_DS (на момент вызова функции флаг прерывания уже сброшен).
Приём осуществляется таким нехитрым способом:
static void NRF24L01_rxData(NRF24L01_Driver *radio) {
while ((NRF24L01_readByteReg(radio, NRF24L01_REG_FIFO_STATUS) & NRF24L01_FIFO_STATUS_RX_EMPTY) == 0) {
NRF24L01_Packet *packet = chHeapAlloc(NULL, sizeof(NRF24L01_Packet));
packet->size = NRF24L01_readRxPayloadLen(radio);
NRF24L01_rxPayload(radio, packet->data, packet->size);
if (chMBPost(&radio->rxMailbox, (msg_t)packet, TIME_IMMEDIATE) != MSG_OK) {
chHeapFree(packet);
}
}
}
Эта функция вызывается при приходе прерывания RX_DR. По идее должна высосать все данные из RX PIPE, сколько бы их там не скопилось.
Тестирую время отправки серии из 10 пакетов (размер очереди отправки позволяет запихнуть их туда все, всё упирается именно в скорость извлечения их оттуда), получаю скорость около 372 КБит/сек.
Маловато будет. Убираем return в конце цикла в функции передачи. В таком случае он по идее должен заполнять RX PIPE сразу 3-мя пакетами (как это позволяет радиомодуль), а затем по мере необходимости добавлять новые. И... теряем больше половины пакетов. Что характерно, пакеты с номерами кратными трём доходят всегда. То есть первый пакет, который мы запихнули в TX PIPE уходит нормально, а остальные отправляются как-то криво. Ну и зачем хвастаться в даташите трёхуровневой очередью отправки, если при запихивании в неё сразу трёх пакетов без пауз, она глючит?
Модули NRF24L01 точно с оригинальными чипами. В качестве микроконтроллера используется STM32F103 с ChibiOS.
Какие уловки следует применить, чтобы увеличить скорость? Да, ACK-ответы, разумеется, отключены.