2024-05-29 08:15 AM
I'm trying to write a driver for the nRF24L01+PA+LNA. I am using STM32F103, and on the receiver side I have an ESP32 with Arduino IDE and the RF24 library. To rule out a hardware issue I have programmed the STM32 using the Arduino IDE and library and the transmission works perfectly.
My library currently transmits only 10-20 times per second and the data it sends seems to multiplied by two or shifted once to the left. Also the last byte in the payload seems to be always changed to a seemingly random number between ~140-255. The payload I'm trying to send is:
uint8_t payload[32] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
The data I receive is something like this:
16:17:14.877 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 247
16:17:14.924 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 183
16:17:15.007 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 182
16:17:15.050 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 235
16:17:15.089 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 255
16:17:15.089 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 183
16:17:15.221 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 255
16:17:15.311 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 219
16:17:15.311 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 223
16:17:15.515 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 247
16:17:15.594 -> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 242
I checked that the device is configured properly before transmitting and to me it it seems to be correct:
One thing I don't quite understand is why the TX_DS bit in the STATUS register is always 1. I have turned off Auto ACK, CRC, Auto Retransmit, and Dynamic Payload Length to keep it simple.
This is the code I use to transmit:
// nRF24L01.c
HAL_StatusTypeDef nrf24_transmit(uint8_t* data, uint8_t size)
{
uint8_t cmd = NRF24_W_TX_PAYLOAD;
nrf24_set_CSN_low();
HAL_StatusTypeDef spi_status = HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
if (spi_status == HAL_OK) {
spi_status = HAL_SPI_Transmit(&hspi1, data, size, 200);
}
nrf24_set_CSN_high();
if (spi_status != HAL_OK) {
nrf24_flush_tx_fifo();
return spi_status;
}
nrf24_set_CE_high();
delay_us(30);
nrf24_set_CE_low();
delay_us(300); // delay because otherwise the data becomes garbage for some reason
uint8_t fifo_status = nrf24_read_reg(NRF24_FIFO_STATUS_REG);
// flush tx fifo if it's not empty
if ( !((fifo_status >> 4) & 0b1) ) {
nrf24_flush_tx_fifo();
}
return spi_status;
}
// main.c
.
.
HAL_Delay(100);
nrf24_reset(&hspi1);
nrf24_init(&hspi1);
nrf24_set_tx_mode(CHANNEL, TX_ADDRESS);
HAL_Delay(100);
NRF24_StateTypeDef state;
nrf24_read_state(&state);
uint8_t payload[32] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
HAL_StatusTypeDef tx_spi_status;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
tx_spi_status = nrf24_transmit(payload, 32);
// catch failed spi transmit
if (tx_spi_status != HAL_OK) {
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_Delay(3000);
}
}
I have tried to debug the code by looking at the STATUS and FIFO_STATUS registers before and after loading the TX FIFO and transmitting. The STATUS register is always 0b00101110 and FIFO_STATUS is sometimes not empty after transmitting and never full after writing the payload. I'm thinking that the issue is with my STM32 code or maybe it is somehow incompatible with the Arduino implementation. Receiver code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(10, 9); // CE, CSN
const byte address[5] = {0xEE,0xDD,0xCC,0xBB,0xAA};
void setup() {
Serial.begin(9600);
while (!radio.begin()) {
Serial.println(F("radio hardware not responding!"));
delay(100);
}
radio.setAddressWidth(5);
radio.openReadingPipe(0, address);
radio.setChannel(1);
radio.setPALevel(RF24_PA_MAX);
radio.setDataRate(RF24_2MBPS);
radio.disableAckPayload();
radio.disableDynamicPayloads();
radio.setCRCLength(RF24_CRC_DISABLED);
radio.startListening();
radio.flush_rx();
}
void loop() {
if (radio.available()) {
uint8_t d[32];
radio.read(&d, sizeof(d));
for (int i = 0; i < 32; ++i) {
Serial.print(d[i]);
Serial.print(" ");
}
Serial.println();
}
}
I have also tried different delays at many points, some of which slow down the transmission even more obviously and some make the data garbage. Different SPI clockspeeds have also been tried, this is my SPI config:
2024-05-29 09:01 AM
Have you looked on the SPI wires with an oscilloscope or logic analyser to see what is actually being sent to the nRF24L01 ?
2024-05-29 12:45 PM
Unfortynately I do not have such devices at hand right now, I was hoping that there would be something obvious wrong with my code or the configuration :beaming_face_with_smiling_eyes: