7

I'm writing a Raspberry Pi program, to run stuff, take inputs from sensors, save in database and synchronise to a server.

Is there a way to test it on the PC before deploying it to the Raspberry Pi? Because there are too many GPIO operations, I want to make sure it works before putting it on the Raspberry Pi. Some sort of a GPIO emulator or something. I'm on Manjaro Linux.

It doesn't have to be emulator, some sort of an IDE capable of understanding GPIO functions. For instance, a possible output would be:

gpio 1 is running,
sensor 1 is running
sensor 2 isn't running

Something like that, perhaps a Bpython plugin or something. All I want to do is make sure that all my GPIO functions are working the way I want them to work before testing on the Raspberry Pi, because many times, errors on the Raspberry Pi has to do with me not connecting parts correctly. And I don't like to code and fix bugs on the Raspberry Pi.

So if I can verify my script is working correctly on my PC, I can go to the Raspberry Pi, knowing that my script is fine and fix stuff on the board. I just don't want to test my script on the Raspberry Pi anymore.

  • A different approach could be to use "sshfs" to mount your raspberry pi home directory on your PC. You can then use whatever you want to write your code with your files on the pi, and then have a ssh-shell on the pi in which you actually run the code. As this happens over an ssh connection the speed is limited, but it may work well for you. – Thorbjørn Ravn Andersen Aug 15 '15 at 20:49
6

I'm not aware of any ready built solution for your needs.

However you could write your own with not very much effort. How many different calls do you make to the gpio functions? You might find you use less than 10. Just create your own local Python module named the same as your target module and produce stubs for the functions you use.

E.g. if you use function gpio_write() which takes a gpio and a level your stub could just be

def gpio_write(gpio, level):
   print("gpio_write called with gpio={} level={}".format(gpio, level))

Your gpio_read stub could be

def gpio_read(gpio):
   global val
   print("gpio_read called with gpio={}, returning {}".format(gpio, val))
   return val # where val may be read from a file or set externally

This is a fairly standard practice, long used in software development to test software before hardware is available.

By the way my pigpio Python module runs on Windows/Mac/Linux PCs.

  • your module runs on on linux but doesn't give error if it doesn't find gpios like the standard gpio library? I'm using your module btw – Lynob Aug 15 '15 at 11:47
  • My module will give errors if it has not been connected to the Pi. It does need a networked Pi running the pigpio daemon to be available when the script is run. So you would still have to use stubs if you did not have a Pi available on the network. However it will allow you to develop and run scripts on your PC rather than on the Raspberry Pi. I made that suggestion in response to "And I don't like to code and fix bugs on pi". – joan Aug 15 '15 at 11:56
  • 1
    ah thats nice!!! – Lynob Aug 15 '15 at 12:10
  • could I install your module using pip? – Lynob Aug 16 '15 at 23:44
  • @Lynob Not as far as I am aware. – joan Aug 17 '15 at 6:40
3

GPIO Zero provides a mock pin interface, meaning you can run the same code on your PC and emulate the pins. See examples of how it's used in the test suite.

3

I made this little library, fedeb95/pin that proved useful for me. Lacks some features, but if it suits you... it worked for me.

Edit: pin is a RPi.GPIO wrapper. Instead of calling method x of RPi.GPIO you call method x of pin. You can specify in a configuration file if your program is running in test mode (wyere you read random values from pins, or values you set with set_value) or on an actual raspberry, where this library simply calls the corresponding RPi.GPIO method. It lacks something, but it's a very simple library, and anyone is free to contribute or tell me what feature he needs and I'll try to add it

  • 2
    Could you list here a short overview of the features? – RalfFriedl Apr 12 at 5:24
  • Basically it's a RPi.GPIO wrapper. Instead of calling method x pf RPi.GPIO you call method x of pin. You can specify in a configuration file if your program is running in test mode (wyere you read random values from pins, or values you set with set_value) or on an actual raspberry, where this library simply calls the corresponding RPi.GPIO method. It lacks something, but it's a very simple library, and anyone is free to contribute or tell me what feature he needs and I'll try to add it – fedeb Apr 13 at 8:30
  • You should edit that into the answer. – RalfFriedl Apr 13 at 11:49
2

There's a library you can download here: https://roderickvella.wordpress.com/2016/06/28/raspberry-pi-gpio-emulator/

Or there's a simulator which lets you write and test the python code here: http://blog.withcode.uk/2016/10/rpi-gpio-python-simulator/

2

I suppose you could use mocking libraries like Mock.

They are mostly used for Unit Testing, but I'm pretty it would work very well in your case. And you would probably be better of trying it by writting some unit tests.

It replaces on-the-go an existing class, and you just have to write yourself the behaviour you're looking for. It allows you not to change anything in your logic (even the imports), but still get the return values you suppose you would receive from an actual call of the API.

2

Being a newbie to Python and the Pi I didn't understand Joan's answer and needed a simple (bot not elegant!) way of testing my program on the PC without error messages caused by missing GPIO calls. I simply choose what sections of code to run by checking what machine I'm running on. I can then emeluate a GPIO call - like a switch closing - from the PC keyboard.

#!/usr/bin/python3
import socket
my_PC_host_name = 'Dev'
host_name = socket.gethostname()
if (host_name != my_PC_host_name):  # Only run these lines if we're not on the PC
    import RPi.GPIO as GPIO
    # Set GPIO numbering mode and define the input pin
    GPIO.setmode(GPIO.BOARD)  # Uses the same board numbering as on the board
    GPIO.setup(16, GPIO.IN)  # Set up the pin 16 as input

if (host_name != my_PC_host_name):  # Only run these lines if we're not on the PC
    try:
        while True:
            if GPIO.input(16) == 0:
                print ("Switch is open")
            else:
                print ("Switch is closed")             
    finally:
        GPIO.cleanup()  # Cleanup the GPIO ports before ending          
else:  # We're running on the PC
    try:
        while True:
            c = input('Press "o" then "Enter":')
            if c.upper() == 'O':
                print ("Switch is open")
            else:
                print ("Switch is closed")
    finally:           
        print ("Process completed")

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.