Coder Social home page Coder Social logo

bjarne-hansen / py-nrf24 Goto Github PK

View Code? Open in Web Editor NEW
51.0 3.0 21.0 1.36 MB

Library for NRF24L01 communication using pigpiod on Raspberry Pi.

License: MIT License

Python 82.25% Shell 0.04% C++ 17.71%
raspberry python nrf24l01 arduino wiring communication pypi electronics iot

py-nrf24's Introduction

NRF24L01 for Python

This package implement 2.4Ghz communication using NRF24L01+ modules on a Raspberry Pi using Python.

Changes

  • Version 2.0.0 - Released to PyPi.org on April 8th, 2021.

    This version contains breaking changes compared to version 1.1.1. Make sure to review CHANGES.md and make changes to you client code accordingly.

  • Version 1.1.1 - Released to PyPi.org on September 20th, 2020.

  • Version 1.1.0 - Released to PyPi.org on September 20th, 2020.

  • Version 1.0.2 - Released to PyPi.org on May 8th, 2020.

  • Version 1.0.1 - Released to PyPi.org on May 8th, 2020.

  • Version 1.0.0 - Released to PyPi.org on May 8th, 2020.

  • Version 0.8.0 - Released to PyPi.org on May 1st, 2020.

  • Version 0.5.2 - Released to PyPi.org on April 20th, 2020.

Background

The code is based on a modified version of some example code found on StackExchange. The author of the original code is also the author of the pigpio library found here http://abyz.me.uk/rpi/pigpio/.

I have obtained the original authors approval to modify and distribute the code anyway I want. So, I have created a very basic Python package and published it on PyPI under a MIT license.

The nrf24 packages depends on the pigpio package that is available via PyPI as well. Before installing and running any of the code and examples below, please make sure you the pigpid daemon running on your Raspberry. This is a library/server that provides access to the GPIO ports of the Raspberry.

Details avalable at http://abyz.me.uk/rpi/pigpio/download.html

Quick installation of pigpio on Raspbian:

sudo apt-get update    
sudo apt-get install pigpio python-pigpio python3-pigpio

Installing

You may want to create a virtual environment before installing the nrf24 package which depends on the pigpio package.

$ pip install nrf24

Examples

All examples in the test folder can be run as command line programs. They all take optional command line arguments to specify the hostname (default: localhost) and the port (default: 8888) of the pigpio deamon. Most of them also takes one or more addresses to use. All should have sensible defaults, so running them without arguments should be an OK first approach to testing your setup.

All test have been run on a Raspberry Pi 4 and a Raspberry Pi Zero Wireless equipped with 2 x NRF24L01+ modules each.

The int-sender.py and int-receiver.py examples requires extra wiring connenting the IRQ PIN of the NRF24L01+ module to a GPIO on the Raspberry. This wiring is shown in "Raspberry Pi with Single NRF24L01+ Module (IRQ)".

The multi-sender.py and multi-receiver.py examples requires two NRF24L01+ modules. The wiring for that setup can be seen in "Raspberry Pi with Dual NRF24L01+ Modules" below.

The rest of the Raspberry Pi examples runs with the IRQ wiring as described above, or a simpler wiring like the one shown in "Raspberry Pi with Single NRF24L01+ Module" below.

Command Line Comments
python test/simple-sender.py Emulates a process sending sensor readings every 10 seconds using a dynamic payload size (default sending address is 1SNSR).
python test/simple-receiver.py Emulates a receiving process receiving sensor readings from the corresponding sender using a dynamic payload size (default listening address 1SNSR).
python test/fixed-sender.py Emulates a process sending sensor readings every 10 seconds using a fixed payload size (default sending address is 1SNSR).
python test/fixed-receiver.py Emulates a receiving process receiving sensor readings from the corresponding sender using a fixed payload size (default listening address 1SNSR).
python test/mixed-sender.py Shows an example of sending both fixed and dynamic payload sized messages. Suggested address for fixed messages is FTEST, and the suggested address for dynamic messages is DTEST.
python test/mixed-receiver.py Shows how to configure reading pipes using both fixed and dynamic message sizes at the same time.
python test/int-sender.py Shows how to use interrupt to detect that a message has been sent (default sending address 1SNSR).
python test/int-receiver.py Shows how to use interrupt to detect that a message has been received (default listening address 1SNSR).
python test/rr-client.py Shows example of how to send a request to a server with a reply to address included in the message, and then switching to RX mode to receive the response from the server (default server (TX) address is 1SRVR and default reply to address (RX) is 1CLNT)
python test/rr-server.py Shows example of a server listening for requests and returning a response to the client (default server (RX) address is 1SRVR).
python test/ack-sender.py Sends message to the receiver every 10 seconds, expecting a payload sent back with the acknowledgement (default sender address 1ACKS).
python test/ack-receiver.py Receives message and sends acknowledgement message with payload (default listen address 1ACKS).
python test/multi-sender.py Sends messages using 2 x NRF24L01+ modules connected to the same Raspberry Pi (defult send addresses 1SRVR and 2SRVR).
python test/multi-sender.py receives messages using 2 x NRF24L01+ modules connected to the same Raspberry Pi (defult listen addresses 1SRVR and 2SRVR).

If you do not have multiple Raspberry Pi computers, you can run some of the test programs on Arduino. In the arduino/ directory are sender programs equivalent with some of those described above. The wiring for the Arduino Nano can be seen in "Arduino Nano with DHT22 and NRF24L01+" below. Unlike it's Raspberry Pi counterparts the Arduino examples have been done with an actual DHT22 sensor connected so that we do not need to emulate sensor readings.

Arduino Code Comments
arduino/simple-sender Sends temperature and humidity readings to the simple-receiver.py counterpart.
arduino/fixed-sender Sends temperature and humidity readings to the fixed-receiver.py counterpart.
arduino/mixed-sender Sends temperature and humidity readings to the mixed-receiver.py counterpart.
arduino/rr-client Executes request/response calls against its rr-server.py counterpart.
arduino/ack-sender Sends temperature and humidity readings to the ack-receiver.py counterpart and receives acknowledgements with payload.

Wiring

Raspberry Pi with Single NRF24L01+ Module (IRQ)

Raspberry Pi with Single NRF24L01+ Module (IRQ)

Raspberry Pi with Dual NRF24L01+ Modules

The multi-sender.py and multi-receiver.py examples requires two NRF24L01+ modules wired to each Raspberry Pi.

Raspberry Pi with Dual NRF24L01+ Modules

Raspberry Pi with Single NRF24L01+ Module

All the examples, except the multi-sender.py, multi-receiver.py, int-sender.py, and int-receiver.py ones will run with the following wiring of a single NRF24L01+ module.

Raspberry Pi with Single NRF24L01+ Module

Arduino Nano with DHT22 and NRF24L01+

The Arduino examples in arduino/ can all run with the following wiring.

Arduino Nano with DHT22 and NRF24L01+

py-nrf24's People

Contributors

4ybaka avatar bjarne-hansen avatar lennart99 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

py-nrf24's Issues

Raspbeery Pi4 as a reciever not working

Using a pi 4 as the receiver and an ESP8266 fot the transmitter , the pi code runs well same as the esp but nothing seems to be publishing,...

This are the response from both devices:

Pi 4:
2023-05-13 09:25:51.945012: pipe: 0, len: 9, bytes: 00:00:00:00:00:00:00:00:00, count: 12393

ESP8266:
Sensor values: temperature=35.00, humidity=25.00
Preparing payload.
Bytes packed: 9
Failed to send payload. Retries=15

The code used are those in the test repo, specifically simple-receiver.py and simple-sender.ino

Python version confusion

I was using a Pi Zero W with Python 3.9 :

$ python --version
Python 3.9.2

After following the "Quick installation of pigpio on Raspbian:" in README.md :

$ sudo apt-get update    
$ sudo apt-get install pigpio python-pigpio python3-pigpio

the default Python version changed to 2.7 :

$ python --version
Python 2.7.18

Calling simple-receiver.py with "python" gives an error:

$ python simple-receiver.py
  File "simple-receiver.py", line 34
    print(f'Invalid address {address}. Addresses must be between 3 and 5 ASCII characters.')

...but works with "python3"

$ python3 simple-receiver.py
Python NRF24 Simple Receiver Example.
Connecting to GPIO daemon on localhost:8888 ...

Which of the packages in "sudo apt-get install pigpio python-pigpio python3-pigpio" are necessary to have the example working without automatically installing Python v2.7 ?

update:

$ sudo apt-get install python-is-python3

The following packages were automatically installed and are no longer required:
  libpython2-stdlib libpython2.7-minimal libpython2.7-stdlib python2 python2-minimal python2.7 python2.7-minimal
Use 'sudo apt autoremove' to remove them.
The following packages will be REMOVED:
  python-is-python2 python-pigpio
...

$ python --version
 Python 3.9.2

$ python simple-receiver.py
... works

Implement IRQ mask

Implement methods to set/get the IRQ mask of the NRF24L01+ module.

set_irq_mask(mask)
get_irq_mask()

enable_rx_irq()
disable_rx_irq()

enable_tx_irq()
disable_tx_irq()

enable_rt_irq()
disable_rt_irq()

CONFIG
MASK_RX_DR     1 << 6 
MASK_TX_DS     1 << 5 
MASK_MAX_RT    1 << 4 
EN_CRC         1 << 3
CRCO           1 << 2
PWR_UP         1 << 1
PRIM_RX        1 << 0

Add retransmission parameters to constructor.

Add delay and retries as parameters to constructor.

Delay is a value between 0 and 15. The delay between retransmissions is (delay + 1) * 250 µs
Retries is a value between 0 and 15.

function ack_payload() not sending ack packages

According to nrf24 datasheet the ack_payload function was changed from:

def ack_payload(self, data):
    self._nrf_command([self.W_ACK_PAYLOAD ] + data)

to:

def ack_payload(self, pipe, data):
    self._nrf_command([self.W_ACK_PAYLOAD | (pipe & 0x07)] + data)

Question

Can code be modified to receive from more then 1 nrf24l01 chip? I just started looking at it might find my answer but figured I'd ask anyway. Tha is for sharing code I've been trying to figure this out for a while with what libraries to import and such.

A suggestion to use a callback instead of the while loop

Dear Bjarne,

In your example I noticed that little while loop that constantly checks for available data. Although it works, it pushes the CPU to an unnecessary load. Moreover it happens to have few messages circulating through the NRF24. The good thing is that you can change this behavior with a callback approach. The advantage is that the callback will only be called when data arrives, so it lets the CPU take care of some other tasks.

To implement it, the NRF24 class will need a new attribute, the callback itself. The callback can be set by passing it to the constructor:

self.cb = cb

Then, inside the constructor you set the callback to be called on the falling edge of the MOSI pin. This can be achieved with the pigpio library:

pi.callback(10, pigpio.FALLING_EDGE, self.callback)

Then the callback:

def callback(this, a=None, b=None, c=None):
	if self.data_ready():
		self.cb(self.get_payload())

That’s all. Please let me know if you find it usefull and if it deserves to be perpetuated.

Regards,
Alinux.

Only one Message gets sended

My program only receves one message from the sender.
I copyed the code from the simple_sender and simple_recever files and just added a diffrent payload.

payload = struct.pack("@B"+"?"*13+"f"*6+"h"*2, 0x01, *send[0].values(), *send[1].values(), send[2][0][0], send[2][0][1])

the first message gets correctly sended and receved. But after that its get stuck on this message and the nrf.data_ready() function gives always true back. Is there any way to reset the receved data?
And the transitter can't send anymore.

Recever side:
`
while True:
while nrf.data_ready():
# Count message and record time of reception.
count += 1
now = datetime.now()

            # Read pipe and payload for message.               
            payload = nrf.get_payload()                                             
            print(payload)
            # 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 payload[0] == 0x01:
                
                for i in payload:
                    print(i)
                print("Payload rx: " + str(struct.unpack("@B"+"?"*13+"f"*6+"h"*2, payload)))
                values = struct.unpack("<B"+"?"*13+"f"*6+"h"*2, payload)
                self.queue.put_nowait(values)
        time.sleep(0.1)

`

Sender side:
`
while True:
if not self.sending_data.empty():
for _ in range(self.sending_data.qsize()-1):
send=self.sending_data.get_nowait()

                if not send:
                    continue
                if send[0][9] and send[0][10]:
                    pass
                else:     
                    payload = struct.pack("@B"+"?"*13+"f"*6+"h"*2,
                                            0x01,
                                            *send[0].values(),
                                            *send[1].values(),
                                            send[2][0][0],
                                            send[2][0][1])
                    nrf.reset_packages_lost()
                    nrf.send(payload)
                print("<B"+"?"*13+"f"*6+"h"*2)
                print(not send)
                print(len(send[0].values()))
                print(len(send[1].values()))
            print(payload)        
            # Send the payload to the address specified above.
            
            try:
                if payload:
                    nrf.wait_until_sent()
                    print("sented")
            except TimeoutError:
                print("Timed out")
                time.sleep(0.2)
                continue
            time.sleep(1)

`

And in the examples simple_rx/tx is the code and the transmition working.

Pipes RF24_RX_ADDR.P2 and above not working

The Pipes RF24_RX_ADDR.P2 and above seem to not be working, If I doe anything wrong, please tell.

Raspberry Pi code:

import pigpio
import nrf24
import struct

slaves = [[nrf24.RF24_RX_ADDR.P0, 0x00], [nrf24.RF24_RX_ADDR.P1, 0x01], [nrf24.RF24_RX_ADDR.P2, 0x02], [nrf24.RF24_RX_ADDR.P3, 0x03]]

# Connect to Raspberry Pi
pi = pigpio.pi()

# Set up NRF24L01 module for reading.
radio = nrf24.NRF24(pi, ce=22, data_rate=nrf24.RF24_DATA_RATE.RATE_250KBPS, payload_size=nrf24.RF24_PAYLOAD.from_value(8))
radio.set_pa_level(nrf24.RF24_PA.LOW)
for slave in slaves:
    radio.open_reading_pipe(slave[0], [slave[1], 0, 0, 0, 0])

while True:
    while radio.data_ready(): 
        # Get pipe, payload.
        pipe = radio.data_pipe()
        payload = radio.get_payload()

        # Convert data to hex.
        hex = ':'.join(f'{i:02x}' for i in payload)
        
        print(f'Data received on pipe {pipe}: {hex}')
        
        # Unpack protocol, temperature, and humidity.
        (id, data) = struct.unpack('<ii', payload)

        # Report
        print(f'pipe: {pipe}, id: {id}, data: {data}')```

arduino code:

/*
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

struct Package {
  long id;
  long data;
};

RF24 radio(7, 8); // CE, CSN

const uint64_t address = 0x00LL; // every 'slave' will get a different address

void setup() {

  radio.begin();
  radio.enableDynamicPayloads();
  radio.setPayloadSize(sizeof(Package));
  radio.setAutoAck(true);
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(address);

  radio.stopListening();
}

int data = 0;
void loop() {
  Package pack;
  pack.id = 1;
  pack.data = data;
  
 radio.write(&pack, sizeof(Package));

  data ++;

  delay(1000);
}

When setting the address in the arduino code to 0 or 1, the data is received normally, but when the address is set to 2 or 3, the raspberry pi receives nothing.

Please let me know if this is a bug or if i am doing it wrong

Use of library on jetson nano

Hello, I successfully established communication between two RP-s as described in the readme. Can library also be used for jetson nano, because the command sudo apt-get install python-pigpio python3-pigpio throws me and error: E: Unable to locate package python3-pigpio? Download using pip installs pigpio library, but the deamon still won't start.

Implement a soft reset.

Implement reset() method performing a soft reset setting all registers to their default value.

Error while pip install

Hello!

I got the following error after [pip install nrf24] command:

"Could not find a version that satisfies the requirement nrf24 (from versions: )
No matching distribution found for nrf24"

Could you help me what is the problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.