Arduino-Python bridge

Here is a Python library that I cooked up to replace Firmata/Pyduino, which I could not get working with my Diecimila. The library is based on the Simple Message System protocol, an Arduino library intended to facilitate simple i/o control between computer and microcontroller (it can be found here: Arduino Playground - SimpleMessageSystem). My Python library is pretty self-explanatory (just make sure you have the SMS example sketch loaded on your Arduino), feel free to use it with whatever you want :slight_smile:

# Pyduino SMS
# by Dylan V, free to copy/edit/distribute
# A simple[r] Python-Arduino bridge, based on the Simple Message System protocol.
# Requires SMS library and SMS example sketch to be loaded on board.
# For USB Arduinos, please change baudrate in sketch to 115200. 

import serial, atexit

__version__ = "0.2"
# This is alpha code, written by a novice. Syntax/structure changes are extremely welcome.
debug = True
global comm

class arduino:
   def __init__(self, port, baudrate=115200):
      try: self.comm = serial.Serial(port, baudrate, timeout=0.25)
      except: print "Could not connect to Arduino at specified port."
      if debug: print "Serial connection established at port %s." % port
      atexit.register(self.disconnect)

   def read_digital(self, pin):
      if pin in range(2, 14):
         self.comm.write("r d\r")
         result = self.comm.readline().split()[1:][pin - 2]
         if debug: print "Read digital pin %s, value was %s" % (str(pin), result)
         if result == "": return None
         else: return int(result)

   def read_analog(self, pin):
      if pin in range(6):
         self.comm.write("r a\r")
         result = self.comm.readline().split()[1:][pin]
         if debug: print "Read analog pin %s, value was %s" % (str(pin), result)
         if result == "": return None
         else: return int(result)

   def write_digital(self, pin, val):
      if pin in range(2, 14) and val in [0, 1]:
         self.comm.write("w d %s %s\r" % (pin, str(val)))
         if debug: print "Wrote value %s to digital pin %s" % (str(val), pin)

   def write_analog(self, pin, val):
      if pin in [3, 5, 6, 9, 10, 11] and val in range(256):
         self.comm.write("w a %s %s\r" % (pin, str(val)))
         if debug: print "Wrote value %s to pwm pin %s" % (str(val), pin)

   def disconnect(self):
      if self.comm: self.comm.close()
      if debug: print "Serial connection closed."

I'm having some trouble with this in Windows XP / Python 2.4 / Arduino NG Rev C. Can anyone see what I'm doing wrong?

I'm brand new to the Arduino so it's entirely possible I'm doing something very stupid.

I have this sketch successfully loaded onto the Arduino:
http://www.arduino.cc/playground/Code/SimpleMessageSystem

My Arduino is installed as Com4 under Windows, and I set it's buardrate in Device Manager to be 115200 (it installed as 9600, but the change doesn't seem to have affected it).

For simplicity I extracted the relevant parts of the above code:

import serial, time

baudrate = 115200

comm = serial.Serial(3, baudrate, timeout=0.25)

for i in range(10):
    comm.write("r d\r")
    o = comm.readline()

    if len(o) == 0: print "no response..."
    else: print o

    time.sleep(.5)

With pins GRD and 11 jumpered I get the following output when running the above:

d 0 0 0 1 1 1 1 1 1 0 0 0
d 0 0 0 1 1 1 1 1 1 0 0 0
d 0 0 0 1 1 1 0 1 0 0 0 0
d 0 0 0 1 1 1 0 1 0 0 0 0
d 0 0 0 1 1 1 0 1 0 0 0 0
no response...
no response...
d 0 0 0 1 1 1 1 1 0 0 0 0
d 0 0 0 1 1 1 1 1 0 0 0 0
no response...

With all pins open (no jumpers) I get the following:

no response...
d 0 1 0 1 1 1 0 1 1 1 0 0
d 0 1 0 1 1 1 0 1 1 1 0 0
d 0 1 0 1 1 1 0 1 1 1 0 0
d 0 1 0 1 1 1 0 1 1 1 0 0
no response...
no response...
no response...
d 0 0 0 1 1 1 0 1 1 1 0 0
d 0 1 0 1 1 1 1 1 1 1 0 0

Ok, so far so good, the digit 3rd from the right is Pin 11 and it's indicating its status well. However, if I attach a button across the two pins and press and release I get this:

no response...
d 0 0 0 1 1 1 1 1 0 0 0 0
d 0 0 0 1 1 1 0 1 0 0 0 0
no response...
no response...
d 0 0 0 1 1 1 1 1 0 0 0 0
no response...
d 0 0 0 1 1 1 1 1 0 0 0 0
d 0 0 0 1 1 1 1 1 0 0 0 0
d 0 0 0 1 1 1 1 1 0 0 0 0

Three questions:

  1. How do I make it update faster? When I was pressing that button its status never changed. I have a feeling its reading from a buffer. Do I need to clear that buffer when I read from it? If so, how?

  2. Is it normal to get no response from the Arduino when querying it? Even when I increased the timeout to 1 I still get the no responses...

  3. And on a minor note, why were the other pins fluctuating even when nothing was attached to them?

Thanks for any help.

I'm really sorry, but I'm afraid I don't have the answers to your questions!!!

I'm really a novice Python programmer; I only made this solution as a workaround to Firmata and Pyduino, which wasn't working for me. But it's working now, see this link for details:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1198961581/all-0

This is a much more robust Python<->Arduino solution, which I recommend you use :slight_smile:

Erm, stupid question, but this should work just fine if I have a Duemilanove, right?