Interfacing with Python

There are many applications where you want to interface with mbed from a computer. Python is one language which you may wish to use. This page provides a library of code that can be used to communicate with mbed using RPC and a guide to set up Python.

Setup Python

On windows, install python, win32 extensions and pyserial (if you want to communicate using serial):

On Mac OS X (10.5 or later):

  • Python is already installed.
  • Run Terminal.app and type sudo easy_install pyserial at the prompt to install PySerial.
  • Also type ls /dev/tty.usbmodem* to find the device name of the mbed USB serial connection.

On Linux, or other unix-like:

  • Python is most-likely already installed; if not see your OS's install system or visit http://www.python.org/download/
  • In a terminal type sudo easy_install pyserial to install PySerial.
  • Also type ls /dev/ttyACM* to find the device name of the mbed USB serial connection.

Python RPC Library

The mbed libraries support RPC, which means you can create objects and control them remotely; Interfacing-Using-RPC.

Here is a Python RPC library which uses the mbed RPC mechanism to map Python classes on to the mbed Library C++ Interface classes. The library is designed to be very similar to the mbed interface. This is an example using HTTP.

Python_mbed_HelloWorld

#!python
python
>>> from mbedrpc import *
>>> mbed = HTTPRPC("192.168.0.4")
>>> x = DigitalOut(mbed,LED1)
>>> z = DigitalOut(mbed,LED2) 
>>> ain = AnalogIn(mbed, LED3)
>>> x.write(1)
>>> z.write(0.5)
>>> ain.read()
0.786757474
>>>

The API

  • First of all you must import the mbedrpc library. To do this the mbedrpc.py file must be in the Python library.
  • You then create an mbed object on the transport mechanism that you require, (more information on this below). If you are using more than one mbed then create an object for each one passing the appropriate parameters to the transport mechanism for each.

>>> mbed = HTTPRPC("192.168.2.2")
>>> mbed2 = HTTPRPC("192.168.2.3")
  • You can then create mbed interface objects in the same way as you would on mbed only you also have to pass them the mbed object which represents the mbed they are to be created on. This means you can control multiple mbeds.

>>> x = DigitalIn(mbed, p20)

  • Alternatively you may wish to tie a Python object to an existing object on mbed in which case you pass in the name of that object.

>>> y = DigitalOut(mbed, "myled")
  • Finally you can execute the methods on interface objects as defined in the Handbook.

>>>x.read()
>>>y.write(1)

Information

If you want to execute an RPC command that isn't wrapped by the classes we've provided then use: RPCresponse = mbed.RPC(<Object name>,<Method name>,<Arguments as an array>)

Python RPC via HTTP

First you need code running on mbed to set up a HTTP server. Guidelines for this are in the Interfacing-Using-RPC page.

Once this is on the mbed, plug it in to your home router and power it up. With the serial port enabled, it should show the i/f comeing up, and print out the ip address that it has been assigned via DHCP.

#!python
python
>>> from mbedRPC import *
>>> mbed = HTTPRPC("192.168.0.4")
>>> x = DigitalOut(mbed, LED3) # LED3
>>> x.write(1)
>>> x.read()
1
>>>

Python RPC via Serial

Test the Serial Connection

On Windows, connect to COM15 with default 9600 8N1 setting:

#!python
python
>>> import serial
>>> serdev = 15
>>> s = serial.Serial(serdev)
>>> s.write("hello")
>>> s.close()

or when on a Macintosh (in this case /dev/tty.usbmodem1912):

#!python
>>> import serial
>>> serdev = '/dev/tty.usbmodem1912'
>>> s = serial.Serial(serdev)
>>> s.write("hello")
>>> s.close()

or when on a Linux/unix system (in this case /dev/ttyACM0):

#!python
>>> import serial
>>> serdev = '/dev/ttyACM0'
>>> s = serial.Serial(serdev)
>>> s.write("hello")
>>> s.close()

Status light flickered. Cool!

For more basic info, see http://pyserial.wiki.sourceforge.net/pySerial

We know how to make Python talk to Serial. So if we set up mbed to receive RPC over serial then we can use this to control it. Again guidelines for setting up mbed to use serial RPC can be found here: Interfacing-Using-RPC

We can use the same mbedRPC.py file as before. We just need to set up the mbed object using SerialRPC rather than HTTPRPC

#!python
python
>>> from mbedRPC import *
>>> serdev = 15 # or '/dev/tty.usbmodem1912' for Mac or '/dev/ttyACM0' for Linux/unix
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3) # LED3
>>> x.write(1)
>>> x.read()
1
>>>



2 related questions:


30 comments:

10 Nov 2010

Hi, there's a bug in mbedrpc.py on line 266, you have to remove the . before (self.name... to get it working. The line should look like this: self.mbed.rpc(self.name, "write", [str(value)])

And not this: self.mbed.rpc.(self.name, "write", [str(value)])

10 Nov 2010

Another thing:

The code

>>> x = DigitalOut(mbed, 3) # LED3

is wrong. When used, the DigitalOut instance won't get a proper name. You have to use one of the defined pin-instanced from mbedrpc.py. These are LED1-4 and p5 - p30. The correct code would be:

>>> x = DigitalOut(mbed, LED3) # LED3
16 Nov 2010

Another small detail: To get the example above working completely, the DigitalOut.read() method in mbedrpc.py needs to return a value.

After line 118, add:

return int(r)

for this method:

class DigitalOut():
...
  def read(self):
      r = self.mbed.rpc(self.name, "read", [])
      return int(r)
17 Nov 2010

Hi

Thanks for finding and pointing these errors out. I've made the corrections to the Python file.

Michael

23 Nov 2010

Hi all, I am having a problem in using mbedrpc.py file. I have copied this file into Lib folder of python31 installation. when I type following line in python shell,

from mbedrpc import *

I get following error inconsistent use of tabs and spaces in indentation

I don't know whats going wrong. I shall be grateful if any one can help on this. Kind Regards, Hassan

23 Nov 2010

Hi

That would appear to be also my fault, I'm not winning with this one. I've updated the file again but note it will have a changed name while the site updates. The file loaded fine for me in Python 2.6 but I ran an indent checker and it found one incorrect indent which I've corrected Hope this works now.

Michael

24 Nov 2010

Hi Michael,

Thanks for your reply. So does it mean that this file is not compatible with Python31? Because I only have Python31 installed on my PC. How did you corrected that incorrect indent?

24 Nov 2010

Hi,

I have successfully compiled the mbedrpc.py file and disable to load urllib2 file in the beginning of script. Perhaps its not available in Python3 folder under same name. But when I tried to use the commands above for using RPC serially I found following error.

Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information.

from mbedrpc import * serdev = 2 mbed = SerialRPC(serdev, 9600) x = DigitalOut(mbed, LED1)

Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> x = DigitalOut(mbed, LED1) File "C:\Python31\lib\mbedrpc.py", line 108, in init self.name = self.mbed.rpc("DigitalOut", "new", [mpin.name]) File "C:\Python31\lib\mbedrpc.py", line 86, in rpc self.ser.write("/" + name + "/" + method + " " + " ".join(args) + "\n") File "C:\Python31\lib\site-packages\serial\serialwin32.py", line 249, in write data = bytes(data) TypeError: string argument without an encoding

I shall be grateful if any one can help. Kind Regards, Hassan

24 Nov 2010

Hi

Firstly python 3.0 is "Intentionaly Backwards Imcompatible" with 2.0 so something written in python 2 need no necessarily work in python 3. That said, I think it should be possible to make this work in py3k. Have you downloaded pyserial from the link above, I don't think that version supports py3k. If you goto http://pyserial.sourceforge.net/pyserial.html and then goto the downloads page then you can select a version of v2.5 for py3k.

If you use that then you might make some progress, it would also be good to know if you can communicate with the serial port directly as this will narrow the problem down to either the serial port or the mbedRPC library.

(The incorrect indent was just one extra space on a line - so to correct it I deleted it)

25 Nov 2010

Hi Michael, Thanks for your prompt reply. Yes, I have downloaded the py3k compatible version of pyserial from its web site. I can setup serial port setting in Py3K but when I use command: x = DigitalOut(mbed, LED1) I get error. But last night I installed py26 and related software as mentioned above. The mbedRPC is working perfectly with this version. So I believe that mbedrpc.py file need to be revised to be compatible with py3k. I will work on it and will let you know if successful. Kind Regards, Hassan

27 Dec 2010

When trying to follow the steps above to communicate over serial on linux, I can get the status light to blink when sending "hello" using just pyserial, but when I try using the mbedrpc.py module, I get the message Superclass method not overridden.

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mbedrpc import *
>>> serdev = '/dev/ttyACM0'
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3)
Superclass method not overridden
>>> x.write(1)
Superclass method not overridden
>>> x.read()
Superclass method not overridden
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/mbedrpc.py", line 119, in read
    return int(r)
TypeError: int() argument must be a string or a number, not 'NoneType'
>>> 

How would I fix this error? Did I save the mbedrpc.py in the wrong spot?

19 Jan 2011

I have a doubt related to RPC. 1) If I control same pin using both rpc and direct Digital out(in compiler) how does it work. pl. tell me if any one knows. which will get preference? for example

  1. include "mbed.h"

DigitalOut pin11out(p11);

int main() { while(1) {

pin11out= 1;

} }

Now if I am controlling this p11 bit using Python also simultaneosly from an external GUI also

from mbedrpc import * mbed = HTTPRPC("192.168.0.4") x = DigitalOut(mbed,p11)

>>> x.write(0)

What may happen? I am confused.

2) In another case suppose pin 11 is defined as digital input in mbed compiler program and pin11 digital output in python , which will get preference?

05 Feb 2011

I have a global variable say "int temperature" which I need to read its integer value of "temperature" through python using RPC. pl.susggest anyone. actually a is a return value of a fuction.

So Is it possible to read and write a global variable through HTTPRPC technique like one does for Digital object.

05 Feb 2011

If you look up the RPCVariable class

Import library

Public Member Functions

template<class A >
  RPCVariable (A *ptr, const char *name)
  Constructor.
read ()
  Read the variable over RPC.
void  write (T value)
  Write a value to the variable over RPC.

which is described on the RPC-Interface-Library page you'll find a way to read the value of a variable using RPC. They python library supports this, you need to create an object with the name that you give the RPCVariable object on mbed.

Python_code

x = RPCVariable(mbed, "NAME_OF_RPCVARIABLE")
y = x.read
x.write(5)

In answer to your previous post about multiple objects on one pin; rather than creating 2 Digital outs, one in the code on mbed and one via RPC, create the object in mbed code but then "tie" your python object to the existing digital in (see above). This object can be read or written to from either python or the code on mbed. Note that when you create the object on mbed you must give it a name as well as the pin out ie:

mbed_code

DigitalOut pin11out(p11, "Dout");
07 Feb 2011

Anyone know why my Linux box cannot run the example script?

#!python
python
>>> from mbedrpc import *
>>> serdev = '/dev/ttyACM0'
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3) # LED3
>>> x.write(1)
>>> x.read()
1
>>>

I still get the error below:

Dan O'Brien wrote:

When trying to follow the steps above to communicate over serial on linux, I can get the status light to blink when sending "hello" using just pyserial, but when I try using the mbedrpc.py module, I get the message Superclass method not overridden.

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mbedrpc import *
>>> serdev = '/dev/ttyACM0'
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3)
Superclass method not overridden
>>> x.write(1)
Superclass method not overridden
>>> x.read()
Superclass method not overridden
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/mbedrpc.py", line 119, in read
    return int(r)
TypeError: int() argument must be a string or a number, not 'NoneType'
>>> 

How would I fix this error? Did I save the mbedrpc.py in the wrong spot?

Thanks!

23 Feb 2011

Dan O'Brien wrote:

Anyone know why my Linux box cannot run the example script?

#!python
python
>>> from mbedrpc import *
>>> serdev = '/dev/ttyACM0'
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3) # LED3
>>> x.write(1)
>>> x.read()
1
>>>

I still get the error below:

Dan O'Brien wrote:

When trying to follow the steps above to communicate over serial on linux, I can get the status light to blink when sending "hello" using just pyserial, but when I try using the mbedrpc.py module, I get the message Superclass method not overridden.

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mbedrpc import *
>>> serdev = '/dev/ttyACM0'
>>> mbed = SerialRPC(serdev, 9600)
>>> x = DigitalOut(mbed, LED3)
Superclass method not overridden
>>> x.write(1)
Superclass method not overridden
>>> x.read()
Superclass method not overridden
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/mbedrpc.py", line 119, in read
    return int(r)
TypeError: int() argument must be a string or a number, not 'NoneType'
>>> 

How would I fix this error? Did I save the mbedrpc.py in the wrong spot?

Thanks!

Apparently, you just need to do a indent check in the mbedrpc.py file. I use Geany IDE for edit most of my codes in python. Check out the mbed class (lines 71 to 75). That should do the trick...

JG

23 Feb 2011

J. Gerardo García wrote:

Apparently, you just need to do a indent check in the mbedrpc.py file. I use Geany IDE for edit most of my codes in python. Check out the mbed class (lines 71 to 75). That should do the trick...

JG

Thanks Señor García!

28 Feb 2011

oye gerardo sabes si puedes coexistir dos o mas programas a la vez en el mbed y/o que pasa? cual programa ejecuta?

27 Jul 2011

I was never able to get the mbedRPC.py library to work on Linux or on Windows XP. I checked indentations and it still gives me errors.

When I try to run this python script:

from mbedRPC import*
mbed = SerialRPC("COM8",9600);
myled = DigitalOut(mbed,LED1);
myled.write(1)

I get the following error:

C:\>python c:\downloads\lights.py
Superclass method not overridden
Superclass method not overridden
Superclass method not overridden

When I try to run this script:

from mbedRPC import *
serdev = 8
mbed = SerialRPC(serdev, 9600)
x = DigitalOut(mbed, LED1)
x.write(1)

It tries to connect to COM9, not COM8....

C:\>python c:\downloads\lights.py
Traceback (most recent call last):
  File "c:\downloads\lights.py", line 4, in <module>
    mbed = SerialRPC(serdev, 9600)
  File "C:\Python26\lib\mbedRPC.py", line 82, in __init__
    self.ser = serial.Serial(port)
  File "C:\Python26\lib\site-packages\serial\serialwin32.py", line 30, in __init__
    SerialBase.__init__(self, *args, **kwargs)
  File "C:\Python26\lib\site-packages\serial\serialutil.py", line 260, in __init__
    self.open()
  File "C:\Python26\lib\site-packages\serial\serialwin32.py", line 56, in open
    raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))
serial.serialutil.SerialException: could not open port COM9: [Error 2] The system cannot find the file specified.

When I change "serdev = 8" to "serdev = 7" It makes a connection on COM8 and then I get the following error:

C:\>python c:\downloads\lights.py
Superclass method not overridden
Superclass method not overridden
Superclass method not overridden

However, when I use plain old Serial, I can get things to blink:

import serial
import time

ser = serial.Serial(port='COM8', baudrate=9600)


ser.write('/PwmOut/new p21 red\n')
ser.write('/PwmOut/new p22 green\n')

for i in range(12):
	ser.write('/red/write 1\n'
	time.sleep(.5)
	ser.write('/red/write 0\n')
	time.sleep(.5)
	ser.write('/green/write 1\n')
	time.sleep(.5)
	ser.write('/green/write 0\n')
	time.sleep(.5)


ser.write('/red/delete\n')
ser.write('/green/delete\n')
ser.close() 

Why can't I get the python RPC library to work for me?

07 Aug 2011

Is it possible to use interrupts, timers, etc through the python interpreter? Could anyone suggest what should be done?