cancel
Showing results for 
Search instead for 
Did you mean: 

NRF24 communication between Stm32g431RB and raspberry pi 4

fadrique
Associate

Hello, i used to have an arduino + NRF24L01 communicating with a raspberry pi, wich worked without any issues.

I dont have much knowledge in this area, and due to the lack of documentation in communicating these devices using nrf24, i find myself at a loss when trying to communicate the stm32 and the raspberry pi 4. Id apreciate whatever help can be given to solve this problem.

I have the stm32 as the transmitter and the raspberry pi as the receiver.

 

nrf24 library used for the stm32: https://github.com/elmot/nrf24l01-lib/tree/master

nrf24 python library: bjarne-hansen/py-nrf24: Library for NRF24L01 communication using pigpiod on Raspberry Pi. (github.com)

 

The issue seems to be that the receiver does not enter the while nrf.data_ready. 

 

I dont have much experience posting help on forums, so i hope i havent missed anything. The simplest form of working code for the stm32 and the raspberry pi would help a lot. 

 

Code in the Stm32g431RB:

 

int runRadio(void) { UART_SendStr("\r\nSTM32L432KC is online.\r\n"); // RX/TX disabled nRF24_CE_L(); // Configure the nRF24L01+ UART_SendStr("nRF24L01+ check: "); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-noreturn" if (!nRF24_Check()) { UART_SendStr("FAIL\r\n"); while (1) { Toggle_LED(); Delay_ms(50); } } #pragma clang diagnostic pop UART_SendStr("OK\r\n"); // Initialize the nRF24L01 to its default state nRF24_Init(); #if (DEMO_TX_SINGLE_ESB) // This is simple transmitter with Enhanced ShockBurst (to one logic address): // - TX address: '1SNSR' // - payload: 5 bytes // - RF channel: 100 // - data rate: 512Kbps // - CRC scheme: 2 byte // Set RF channel nRF24_SetRFChannel(100); // Set data rate nRF24_SetDataRate(nRF24_DR_250kbps); // Set CRC scheme nRF24_SetCRCScheme(nRF24_CRC_2byte); // Set address width, its common for all pipes (RX and TX) nRF24_SetAddrWidth(5); // Configure TX PIPE static const uint8_t nRF24_ADDR[] = { '1', 'S', 'N','S','R' }; nRF24_SetAddr(nRF24_PIPETX, nRF24_ADDR); // program TX address nRF24_SetAddr(nRF24_PIPE0, nRF24_ADDR); // program address for pipe#0, must be same as TX (for Auto-ACK) // Set TX power (maximum) nRF24_SetTXPower(nRF24_TXPWR_0dBm); // Configure auto retransmit: 10 retransmissions with pause of 2500s in between nRF24_SetAutoRetr(nRF24_ARD_250us, 15); // Enable Auto-ACK for pipe#0 (for ACK packets) // nRF24_EnableAA(nRF24_PIPE0); nRF24_DisableAA(nRF24_PIPE0); // Set operational mode (PTX == transmitter) nRF24_SetOperationalMode(nRF24_MODE_TX); // Clear any pending IRQ flags nRF24_ClearIRQFlags(); // Enable DPL nRF24_SetDynamicPayloadLength(nRF24_DPL_ON); // Wake the transceiver nRF24_SetPowerMode(nRF24_PWR_UP); // Some variables uint32_t packets_lost = 0; // global counter of lost packets uint8_t otx; uint8_t otx_plos_cnt; // lost packet count uint8_t otx_arc_cnt; // retransmit count // The main loop payload_length = 5; j = 0; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-noreturn" while (1) { // Prepare data packet for (i = 0; i < payload_length; i++) { nRF24_payload[i] = (uint8_t) 1;// j++ if (j > 0x000000FF) j = 0; } // Print a payload UART_SendStr("PAYLOADKK:>"); UART_SendBufHex((char *)nRF24_payload, payload_length); UART_SendStr("< ... TX: "); // Transmit a packet tx_res = nRF24_TransmitPacket(nRF24_payload, payload_length); otx = nRF24_GetRetransmitCounters(); otx_plos_cnt = (otx & nRF24_MASK_PLOS_CNT) >> 4; // packets lost counter otx_arc_cnt = (otx & nRF24_MASK_ARC_CNT); // auto retransmissions counter switch (tx_res) { case nRF24_TX_SUCCESS: UART_SendStr("OK"); break; case nRF24_TX_TIMEOUT: UART_SendStr("TIMEOUT"); break; case nRF24_TX_MAXRT: UART_SendStr("MAX RETRANSMIT"); packets_lost += otx_plos_cnt; nRF24_ResetPLOS(); break; default: UART_SendStr("ERROR"); break; } UART_SendStr(" ARC="); UART_SendInt(otx_arc_cnt); UART_SendStr(" LOST="); UART_SendInt(packets_lost); UART_SendStr("\r\n"); // Wait ~0.5s Delay_ms(500); Toggle_LED(); } #pragma clang diagnostic pop
View more
// Function to transmit data packet // input: // pBuf - pointer to the buffer with data to transmit // length - length of the data buffer in bytes // return: one of nRF24_TX_xx values nRF24_TXResult nRF24_TransmitPacket(uint8_t *pBuf, uint8_t length) { volatile uint32_t wait = nRF24_WAIT_TIMEOUT; uint8_t status; // Deassert the CE pin (in case if it still high) nRF24_CE_L(); // Transfer a data from the specified buffer to the TX FIFO nRF24_WritePayload(pBuf, length); // Start a transmission by asserting CE pin (must be held at least 10us) nRF24_CE_H(); // Poll the transceiver status register until one of the following flags will be set: // TX_DS - means the packet has been transmitted // MAX_RT - means the maximum number of TX retransmits happened // note: this solution is far from perfect, better to use IRQ instead of polling the status do { status = nRF24_GetStatus(); if (status & (nRF24_FLAG_TX_DS | nRF24_FLAG_MAX_RT)) { break; } } while (wait--); // Deassert the CE pin (Standby-II --> Standby-I) nRF24_CE_L(); if (!wait) { // Timeout return nRF24_TX_TIMEOUT; } // Check the flags in STATUS register UART_SendStr("["); UART_SendHex8(status); UART_SendStr("] "); // Clear pending IRQ flags nRF24_ClearIRQFlags(); if (status & nRF24_FLAG_MAX_RT) { // Auto retransmit counter exceeds the programmed maximum limit (FIFO is not removed) return nRF24_TX_MAXRT; } if (status & nRF24_FLAG_TX_DS) { // Successful transmission return nRF24_TX_SUCCESS; } // Some banana happens, a payload remains in the TX FIFO, flush it nRF24_FlushTX(); return nRF24_TX_ERROR; }
View more

 

 

 

Raspberry pi Python code:

 

 

import argparse from datetime import datetime import struct import sys import time import traceback import pigpio from nrf24 import * # A simple NRF24L receiver that connects to a PIGPIO instance on a hostname and port, default "localhost" and 8888, and # starts receiving data on the address specified. Use the companion program "simple-sender.py" to send data to it from # a different Raspberry Pi. # if _name_ == "_main_": print("Python NRF24 Simple Receiver Example.") # Parse command line argument. parser = argparse.ArgumentParser(prog="simple-receiver.py", description="Simple NRF24 Receiver Example.") parser.add_argument('-n', '--hostname', type=str, default='localhost', help="Hostname for the Raspberry running the pigpio daemon.") parser.add_argument('-p', '--port', type=int, default=8888, help="Port number of the pigpio daemon.") parser.add_argument('address', type=str, nargs='?', default='1SNSR', help="Address to listen to (3 to 5 ASCII characters)") args = parser.parse_args() hostname = args.hostname port = args.port address = args.address # Verify that address is between 3 and 5 characters. if not (2 < len(address) < 6): print(f'Invalid address {address}. Addresses must be between 3 and 5 ASCII characters.') sys.exit(1) # Connect to pigpiod print(f'Connecting to GPIO daemon on {hostname}:{port} ...') pi = pigpio.pi(hostname, port) if not pi.connected: print("Not connected to Raspberry Pi ... goodbye.") sys.exit() # Create NRF24 object. # PLEASE NOTE: PA level is set to MIN, because test sender/receivers are often close to each other, and then MIN works better. nrf = NRF24(pi, ce=25, payload_size=RF24_PAYLOAD.DYNAMIC, channel=100, data_rate=RF24_DATA_RATE.RATE_250KBPS, pa_level=RF24_PA.MIN) nrf.set_address_bytes(len(address)) # Listen on the address specified as parameter nrf.open_reading_pipe(RF24_RX_ADDR.P1, address) # Display the content of NRF24L01 device registers. nrf.show_registers() # Enter a loop receiving data on the address specified. try: print(f'Receive from {address}') count = 0 while True: # As long as data is ready for processing, process it. while nrf.data_ready(): # Count message and record time of reception. count += 1 now = datetime.now() print("data ready") # Read pipe and payload for message. pipe = nrf.data_pipe() payload = nrf.get_payload() # Resolve protocol number. protocol = payload[0] if len(payload) > 0 else -1 hex = ':'.join(f'{i:02x}' for i in payload) # Show message received as hex. print(f"{now:%Y-%m-%d %H:%M:%S.%f}: pipe: {pipe}, len: {len(payload)}, bytes: {hex}, count: {count}") # If the length of the message is 9 bytes and the first byte is 0x01, then we try to interpret the bytes # sent as an example message holding a temperature and humidity sent from the "simple-sender.py" program. if len(payload) == 9: #and payload[0] == 0x01: values = struct.unpack("<Bff", payload) print(f'Protocol: {values[0]}, temperature: {values[1]}, humidity: {values[2]}') # Sleep 100 ms. time.sleep(0.1) except: traceback.print_exc() nrf.power_down() pi.stop()
View more

 

 

 

 

1 REPLY 1
Pavel A.
Evangelist III

The issue seems to be that the receiver does not enter the while nrf.data_ready. 

This is line 60 in your python snippet. Is there any error message printed on the python side? If the program just hangs, type ctrl/C and see in the stack trace where it was interrupted.