Joining Raspberry Pi and Arduino applications with SIMPL

eightLeds.py Checklist

  • 1. The tclSurrogate daemon must be up and running in the background on a known port number. The default port number=8000.
  • 2. The environment variable PYTHONPATH must be set to the directory that contains the SIMPL python modules, such as csimpl.py.

To run this script on the Rasp Pi remotely from your other Linux box, you may use SSH; for example (note the uppercase X),

ssh -X pi@10.0.1.32

where (in this case) pi is the user and 10.0.1.32 is the local IP address of the Rasp  Pi.

This Python SIMPL sender script may be run from the command line on the SSH console terminal as:

python eightLeds.py

Note that eightLeds.py is compatible with Python versions 2 and 3.

If you are successful, you should see something like the picture in Figure 3.

Figure 3: Python sender.

When buttons are pushed on the GUI along with Send, the corresponding LEDs on the Arduino should illuminate.

Testing Using arduinoSim.py

Next, we'll discuss an important feature of a modular SIMPL application. Because each SIMPL module communicates via a well-defined messaging protocol, it is very easy to swap out modules for test stubs during the testing stage. We'll look at how this might work for testing our eightLeds.py module without actually connecting an Arduino to the Rasp Pi.

This approach is also useful if you don't have an Arduino handy, but you still want to try out the demo.

In the test configuration, the Arduino sketch has been replaced by a Python application running on the Rasp Pi (Figure 4). This Python application uses the Python-SIMPL library tclSimpl.py to connect into the SIMPL application via the tclSurrogate protocol in exactly the same way that the real Arduino sketch does.

Figure 4: Test configuration with arduinoSim.py.

The full listing of arduinoSim.py is shown in Listing 3.

Listing 3

arduinoSim.py

01 #import required modules
02 import tclsimpl
03 import sys
04 if sys.version < '3':
05       from Tkinter import *
06       import tkMessageBox
07 else:
08       from tkinter import *
09       from tkinter import messagebox
10
11 # defines
12 BRINKY_RITE = 0
13
14 global leds
15
16 def deconstructMsg(nee):
17         # extract the incoming message
18         intoken,status = nee.unpackMsg(nee.BIN, "hb")
19
20         if intoken == BRINKY_RITE:
21                for num in range(8):
22                        bit = 1 << num
23                        if status & bit:
24                                leds[num]["text"] = "ON"
25                        else:
26                                leds[num]["text"] = "OFF"
27
28
29 # define functionality to be performed whan a message is received
30 def hndlMessage(a, b):
31        # receive a message
32        messageSize, senderId = nee.receive()
33
34        if messageSize == -1:
35                # error
36                print("receive error")
37                sys.exit(-1)
38
39       # examine the message
40       deconstructMsg(nee)
41
42       # reply to sending program
43       retVal = nee.reply(senderId)
44       if retVal == -1:
45                print("reply error")
46                sys.exit(-1)
47
48 # define callback function when exit button is selected
49 def finish(event):
50       sys.exit(0)
51
52
53 #***** main part of program ******************************
54
55 # constructor for simpl class object
56 nee = tclsimpl.Simpl("8000:localhost:ARDUINO")
57
58 # initialize Tk for graphics
59 root = Tk()
60
61 # get the receive fifo file descriptor
62 fd = nee.whatsMyFd()
63
64 # attach a callback for incoming simpl messages
65 root.tk.createfilehandler(fd, READABLE, hndlMessage)
66
67 rowframe = Frame(root)
68 rowframe.pack(fill=BOTH)
69
70 leds = [None] * 8
71 for num in range(8):
72
73      leds[num] = Button(rowframe,  borderwidth=2, relief=SOLID, justify=CENTER, \
                 bg="Yellow", fg="Black", text="OFF", font=("Times", 12, "bold"), width=3)
74      leds[num].pack(side=LEFT)
75
76 # the bottom frame of buttons
77 rowframe = Frame(root)
78 rowframe.pack(fill=BOTH)
79
80 # build an exit button widget
81 button = Button(root)
82 button["text"] = "Exit"
83 button.bind("<Button>", finish)
84 button.pack()
85
86 # handle user input and simpl messaging
87 root.mainloop()

The first thing you might notice is the similarity to the eightLeds.py code itself. Why reinvent the wheel? The key line in this test stub is line 56. Here we are telling the arduinoSim code to connect to the tclSurrogate port via the TCP/IP local host loopback socket. This allows arduinoSim.py to run on the same node (Rasp Pi) as the eightLeds.py code but still connect via the tclSurrogate daemon.

To run this test, simply start the arduinoSim as

python arduinoSim.py

on a console terminal (or an ssh -X window). It is then simply a matter of running the eightLeds.py code exactly as before. This code has no way to "know" that a stub is running in place of the Arduino. All the messaging interactions are identical, so a thorough test can be performed without changing a single line of the eightLeds.py module.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content