1

I'm using a Raspberry Pi 2 and a nRF24L01+ with the pyRF24 library. I've had it working fine on a Raspberry Pi (1) model B rev 2 but on the Pi 2 I'm getting this error:

can't send spi message: Invalid argument

I have enabled SPI in raspi-config and I have this in /etc/modules

snd-bcm2835
i2c-bcm2708
i2c-dev

I am running the following code with sudo python3 test.py:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import time, sys, datetime, yaml, urllib.request, urllib.parse, urllib.error
from pyRF24 import pyRF24

class FleetHubError(Exception):
    """ Some weird error """
    pass

class CorruptDataError(Exception):
    """ Data was currupt """
    pass    

class ServerConnectionError(Exception):
    """ Couldn't connect to server """
    pass

class FleetHub:
    def __init__(self,port=0,pipes=[0xF0F0F0F0E1, 0xF0F0F0F0E2]):
        try:
            self.radio = pyRF24("/dev/spidev0.0", 8000000, 25, retries = (15, 15), channel = 76, dynamicPayloads = True, autoAck = True)
            self.radio.openWritingPipe(pipes[0])
            self.radio.openReadingPipe(1, pipes[1])
            self.radio.setDataRate(2)
            self.mode("rcv")
        except Exception as e:
            raise e

    def mode(self,mode):
        if mode == "receive" or mode == "rcv":
            radio.startListening()
            time.sleep(0.25)
        else:
            radio.stopListening()
            time.sleep(0.25)

    def available(self,updateServer=True): # returns the data (as dictionary) if there is any, otherwise False
        try:
            self.recv()
            timeout = False
            started_waiting_at = time.time()
            while not self.radio.available() and not timeout:
                if ((time.time() - started_waiting_at) > 5): timeout = True
            if timeout: return False
            else:
                ok = True
                data = binascii.hexlify(self.radio.read(radio.getDynamicPayloadSize())).decode('utf-8').rstrip() # read data
                try: data = yaml.safe_load(data) # attempt to convert to dict
                except: ok = False
                if ok: # all good
                    data['status'] = data['status'].replace(" ","") # clean up status
                    try: # to get speed
                        data['kph'] = data['speed']['kph']
                        data['mph'] = data['speed']['mph']
                        data['knots'] = data['speed']['knots']
                    except: # no speed
                        data['kph'] = ""
                        data['mph'] = ""
                        data['knots'] = ""
                    try: # to get location 
                        data['lat'] = data['location'][0]
                        data['lng'] = data['location'][1]
                    except: # no location
                        data['lng'] = ""
                        data['lat'] = ""
                    if updateServer: self.updateServer(data) # we need server updated
                return(data)

        except KeyError: raise CorruptDataError
        except OSError: raise DeviceConnectionError
        except TypeError: raise CorruptDataError
        except SystemExit: pass
        except Exception as e: raise(e)


    def updateServer(self,params):
        params.pop("location")
        params.pop("speed")
        try:
            server_response = urllib.request.urlopen("http://myserver.com/update?%s" % urllib.parse.urlencode(params)).read().decode("utf-8")
            return(server_response)
        except urllib.error.URLError:
            raise ServerConnectionError
        except SystemExit: pass
        except Exception as e: raise(e)

if __name__ == "__main__":
    radio = FleetHub()

Could someone tell me why I'm getting this error?

EDIT: I just came accross this https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314 - does it have anything to do with it?

EDIT: I have it working fine in C++, as per the instructions from @user1628, which to me suggests that Python doesn't have the correct SPI BCM2835_PERI_BASE details. So now the question is: How can I make it work in Python3?

2
  • As per the article you linked to yourself, did you try sudo raspi-config --> "Advanced Options" --> "Enable SPI" and a reboot? Alternatively you can add dtparam=spi=on into /boot/config.txt and do a reboot. – Phil B. May 18 '15 at 18:58
  • @PhilB. Yep I did – developius May 18 '15 at 18:59
0
+50

As per @user1628's answer, please try this: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=99227 . Basically, what they did is:

  1. The RF24 library needs to be updated to have a different BCM2835_PERI_BASE argument (from 0x20000000 to 0x3F000000). (In the bcm2835.h file)
  2. Then change the Makefile to have the correct armv7 architecture flag (-march=armv7-a)
  3. Recompile the library and test it out

UPDATE: As discussed in chat - the RF24 library included in the github link for pyRF24 (https://github.com/jonathongrigg/RF24/tree/master/raspberrypi/librf24) does not have the BCM2835_PERI_BASE setting which is what helped you get the C++ version working. You'd need to see if you can compile the pyRF24 module by replacing the RF24 version included with the version stored here: https://github.com/edoardoo/RF24/tree/master/RPi.

Actually, that github library (edoardoo) ALSO contains a pyRF24 wrapper with a setup.py script. Can you try making your BCM2835_PERI_BASE change there, change the architecture flag for the rPi2 and then build the librf24 and the pyRF24 wrapper from that source?

Here are the steps you need to do (Actually, you confirmed in Chat that these steps worked for you - so kudos to yourself) - this gets the wrapper to work in Python2.7, not Python3:

# raspi-config: Advanced -> enable SPI 

sudo apt-get install python-dev python-rpi.gpio python-smbus i2c-tools libboost1.50-all -y 

sudo reboot 

git clone github.com/edoardoo/RF24 
cd RF24/RPi 
rm -rf RF24 
git clone github.com/tmrh20/RF24.git RF24 
cd RF24 

in Makefile change: 
-march=armv6zk 
to 
-march=armv7-a 

sudo make clean && sudo make && sudo make install 

cd examples_RPi 

in Makefile change: 
-march=armv6zk 
to 
-march=armv7-a 

in gettingstarted.cpp 
1. uncomment    `RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);` 
2. comment out  `RF24 radio(22,0);` 

make 
sudo ./gettingstarted # test with C++ 

cd ../ 
./setup.py build 
sudo ./setup.py install

Hope that helps!

11
  • I did that and it works fine in C++. However, I want to work in Python so how do I update the PERI_BASE for Python3? Or does something need to be changed in github.com/jonathongrigg/rf24 (pyRF24 library)? – developius May 18 '15 at 19:14
  • From what I read (I don't have the RF24) the Python3 library is just a wrapper around the C++ classes. I would assume that now that you've got the C++ classes working, you are able to use the pyRF24 library as well. Have you tried? – Phil B. May 18 '15 at 19:16
  • It is indeed just a wrapper but the instructions here raspberrypi.org/forums/viewtopic.php?f=28&t=99227 use a different C++ library, which doesn't have the wrapper included. – developius May 18 '15 at 19:19
  • From the github link you gave: "1. Ensure you have Cython installed under python3 (not python/python2) 2. Also ensure that librf24 has been built and is now in /usr/local/lib 3. From raspberrypi/pyRF24 run sudo python3 setup.py build_ext --inplace " – Phil B. May 18 '15 at 19:20
  • Yes I have done that but the pyRF24 library (which I think is just a rename of the Python RF24 library) doesn't seem to be using the correct SPI details. The GitHub repo for pyRF24 doesn't have a bcm2835.h file, so where is it located? If I can change that, would it then work? – developius May 18 '15 at 19:24
1

You should be able to follow this: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=99227

1
  • 1
    I looked at that thread but couldn't figure out quite what they are doing. Could you provide the steps needed? – developius May 10 '15 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.