Posts Tagged ‘ pyserial

Refresh your Pi

It seems like I use my Raspberry Pi just often enough to forget everything about how I set it up the previous time.  Unlike an Arduino, it’s possible all sorts of new configuration \ updating will need to take place if it’s sat for a few months.  This post will serve mainly a notepad to myself on what I need to do to get it up and running again, and info on how to do fresh installs.

I’m sure this all can vary widely from user to user and Pi to Pi.

Great Linux/Unix command-line cheat-sheet: Web Site, PDF.

First Time Setup Guides

Just in case you do need to do everything from scratch:

The overall gist is:

  • Format SD
  • Download Linux distro and install on card
    • Most recently, I used Pi Filler (looks like Mac only)  : It does both the format and install.
    • Look here for other solutions.
  • Once the pi is up and running, via the settings menu:  (run > raspi-config to get there from the commandline)
    • Expand the root partition:  This is only needed for older distro installs.  If you’re using NOOBS, it should be auto-expanded.
    • Set screen overscan (if wanted)
    • Configure keyboard
    • Change password (if wanted)
    • Set locale, timezone
    • Enable ssh & boot behavior
  • Optionally you can then try to make a new user, but I’ve not found a need yet.  And when I do it, I tend to screw it all up permission-wise.
  • Install VNC (so you access the Pi’s gui remotely)

Linux Distros

I’m the last person you want to ask about which distro to use, but the two main one’s I have used are Raseberian, and Occidentalis.  Rasberian is now installed as part of NOOBS, and it’s a much easier install than in the past.

  • NOOBS : From the page:  “We recommend that first-time Pi users start by downloading and installing our New Out of Box Software (NOOBS) onto a 4GB (or larger) SD card. On first boot, this presents you with a choice of operating systems to install, including Raspbian, Pidora and two flavours of XBMC. Once you have installed an operating system, you can return to the NOOBS interface by holding down shift during boot; this allows you to switch to a different operating system, or overwrite a corrupted card with a fresh install of the current one.”
  • Occidentalis : From the page : “Our distro is based on “Wheezy” but comes with hardware SPI, I2C, one wire, and WiFi support for our wifi adapters. It also has some things to make overall hacking easier such sshd on startup (with key generation on first boot) and  Bonjour (so you can simply ssh raspberrypi.local from any computer on the local network)”

Get into the Pi

It’s been a while, how do I do that?  I forgot where my  surplus usb keyboard is & the wifey is using the spare hdmi cable…

(To do a first-time setup of SSH & VNC, see the post, “Connecting the Mac to the Pi“)

First, SSH:

This will let external machines talk to the Pi.  The primary way I interact with the Pi.
Connect the pi to the network (I use cat5).
There’s a good chance the dynamic ip has changed.  From another computer, access the router and click on the ‘DHCP Client List’ to find the new ip of the Pi.
Or, if you have the Pi plugged into a monitor \ keyboard, you can enter the below command, and look for the “inet addr”

$ sudo ifconfig

Open a shell.  ssh into the Pi:

$ ssh <pi ip address> -l <userName>

Enter password.  Hopefully it lets you in…

This can fail though on a new install.  I get this on my mac:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
etc...

If this happens, lower down in the error it will have this line:

The fingerprint for the RSA key sent by the remote host is

And right below that, is an address.  Copy that address, browse (on the mac) here:

/Users/<userName>/.ssh/known_hosts

Edit that file (known_hosts), and find the section starting with the local ip of your pi.  At the end of that section, add a ‘+’, then paste in the address copied above.

When you try to re-ssh back in, it will ask you if you want to add this new host, and say “yes”.  Enter the password, and you should be good!

Copying files over SSH:

Once you have a ssh connection, you can copy data from one machine to another.

From a terminal on your PC (in my case, a Mac):

Copy data from the Pi to the PC:

$ scp pi@you_pis_ip:/path/to/source/file/on/pi /path/to/destination/file/on/pc

For example:

$ scp pi@192.168.2.27:~/piVid.mp4 ~/macVid.mp4

Copy data from your PC to the Pi:

$ scp /path/to/source/file/on/pc pi@you_pis_ip:/path/to/destination/file/on/pi

For example:

$ scp ~/macVid.mp4 pi@192.168.2.27:~/piVid.mp4

I should note that I’ve not got this to work over SSH from a terminal on the Pi.  But once a ssh connection is open, I can execute these from a terminal on my Mac just fine.

Copying files via SFTP

If you want a more robust solution to copying files to\from the Pi, SSH File Transfer Protocol (SFTP) is a good solution. The post HERE by Trevor Appleton covers how to set it up using FileZilla.  Provides a super easy way via the FileZilla gui to drag & drop files.

Second, VNC:

Once you’ve ssh’d in to the Pi, optionally you can access the desktop via VNC.

If not yet installed, install it:

$ sudo apt-get install tightvncserver

Then start the server:

$ vncserver :1

To start the server.
On your other PC, access the VNC Viewer app.
Set the VNC server address to <pi ip address>:1
Connect:  You should see your Pi’s desktop on your PC.

Update Pi Configuration

Not always needed, but if you need to access the global configuration on the pi, from the shell enter:

$ raspi-config

When done, if a reboot is needed:

$ sudo reboot

Optionally, to safely shutdown the Pi (rather than just unplugging it, which I’m told can be hard on the sd card) :

$ sudo shutdown -h now

Auto Login

Check out the post here:  Raspberry Salad Part 3: Auto-run program on startup

General linux commands

  • ifconfig : network info
  • pgrep <process name> : Return the process id
  • kill <process id> : delete the process
  • lsusb : Get attached usb device info

Setup WiFi

Adafruit has a good overview here.  Note that their section on “Setting up WiFi with the graphic interface” works, but the Pi will only start using WiFi when the gui is up.  If you want wifi to be there at the commandline as soon as the Pi boots, you need to follow their  “Setting up WiFi with the Command Line” tutorial.

Note, I’ve needed to have the pi connected to a monitor\keyboard\mouse to get this setup properly.   Having the Pi hooked up over lan and ssh’d in seems to override the WiFi with the lan, and I can’t get the IP.  Maybe I’m not smart enough.

Check to see if it’s working:

$ ping google.com

BUUUUT, I’d had problems with loosing connection over wifi.  After getting a tip from this thread, I added this line:

wireless-power off

to

/etc/network/interfaces

But that didn’t help anything.  So then I tried the recommendations from this thread (since it’s based on the chipset of the wifi dongle I got from Adafruit) to:

$ sudo nano /etc/modprobe.d/8192cu.conf

and add this code to it:

# Disable power management
options 8192cu rtw_power_mgnt=0

But after a reboot, it still didn’t work well.  In fact it got even harder to ssh in, it would constantly “Operation timed out”.  So I decided to connect the wifi dongle to my powered usb hub.  When I removed it from the Pi, it was really hot:  Power issues?

After plugging the wifi dongle into the  powered hub, and the hub into the Pi, nothing seemed to be working.  I had to power it on\off twice (over lan).  Bu by the 3rd time the wifi dongle started blinking, apparently recognized.  From there I set the Pi to pinging google. com, and my mac to ping the Pi.  So far, so good, internet radio is streaming.

So it looks like the Pi can’t provide enough, or stable enough power to the wifi dongle over it’s own usb port?   That seems… really annoying.

FINALLY, I bought a new wifi dongle:  It worked immediately.  So lesson to you all.  If you have these problems, spend $10 and get a new dongle…

Setup Camera

This post from raspberrypi.org covers it all.

A really good tutorial covering how you can capture raw  h264 videos, convert them to mp4, the play them on the Pi can be found here: Capturing HD Video With The Pi Camera Module.

And, my own setup guide here: “Playing with the Raspberry Pi’s Camera

Software Update

I use the apt-get package manager.

Update your cache:

$ sudo apt-get update

Search the cache for software:

$ sudo apt-cache search <someString>

Upgrade all the software on the Pi (can take a while… hours…)

$ sudo apt-get upgrade

Install new software:

sudo apt-get install <package>

Remove old software.  remove can leave some dependencies behind, purge deletes it all.

$ sudo apt-get remove <package>
$ sudo apt-get purge <package>

Adafruit WebIDE

The Adafruit WebIDE is a great way to program on the Pi from some other computer over ssh.  All the code is managed in the cloud via Bitbucket.   Setup guide HERE.

The general process is:

Note if you’re ‘refreshing’ an old Pi, the WebIDE may no longer recognize it.  In that case, log into your Bitbucket account, and in the “Manage Account -> Integrated Applications” menu, remove any “Consumers” and “OAut Consumers”, and then follow the setup guide to create a new one.

Packages

Scratch-pad area of different packages used based on projects I’ve done, or learned about, and probably forgotten about.

To get a list of all the packages installed:

$ dpkg -l

This post has a great overview of many packages to install: Linux & Python Packages for my Raspberry Pi

Presuming you have pip installed, you can use this to get a list of all Python packages installed:

$ pip freeze --local

Audio

Thanks to this post, I learned about these first three apps:

Alsamixer

$ alsamixer

Alsamixer is part of the distro, and has a simple command-line interface & gui.  Gives you a simple way to adjust volume, etc.

MPD & MPC

MPD is the “Music Player Daemon”.  From the page it is “an audio player that has a server-client architecture. It plays audio files, organizes playlists and maintains a music database all while using very few resources. In order to interface with it, a separate client is needed.”

One of those clients is MPC.  It is “a minimalist command line interface to MPD, not to be confused with musepack.”

To install the two at once:

$ sudo apt-get install mpc mpd

To add internet stream(s) to play (Let’s play some Groove Salad):

$ mpc add http://ice.somafm.com/groovesalad

To play a specific stream:

$ mpc play 1

MPlayer

I used MPlayer as part of my Raspberry FM internet music streamer.

Install:

$ sudo apt-get install mplayer

Play a stream:

$ mplayer http://streamer-dtc-aa01.somafm.com:80/stream/1018

Lot more MPlayer configuration from this post : “Raspberry Salad Part 2: Raspberry FM

Games

Minecraft Pi

Why wouldn’t you want to play Minecraft on you Pi?

Note, Minecraft Pi doesn’t work for me over VNC:  The application launches, but all I see is a black window.  You need to have the Pi directly connected to a monitor/keyboard/mouse.

FYI, it needs to be ran via the XWindows gui mode, so be sure to launch it first via

$ startx

Open a LXTerminal window:  Download (to your home dir), install (then remove the tar), & run:

$ cd ~
$ wget https://s3.amazonaws.com/assets.minecraft.net/pi/minecraft-pi-0.1.1.tar.gz
$ tar -zxvf minecraft-pi-0.1.1.tar.gz
$ rm minecraft-pi-0.1.1.tar.gz
$ cd mcpi
$ ./minecraft-pi

Python

First off, be sure to get pip installed:

$ sudo apt-get install python-pip

Once that’s installed, you can use pip to pull down all other Python packages needed.  This is preferred to using apt-get, this  post does a pretty good job of explaining why.  That being said, I’ve been unable to use pip to install certain packages (like matplotlib), and apt-get works fine.  However, once installed by apt-get, pip recognizes them.

See what Python packages you have installed:

$ pip freeze

RPi.GPIO

You’ll need this to access the Pi’s GPIO pins in Python:

$ sudo pip install RPi.GPIO

pyserial

$ sudo pip install pySerial

PIL

I’ve been unable to get PIL installed via pip.  But apt-get seems to work:

$ sudo apt-get install python-imaging

scipy

Again, pip fails for some reason.

$ sudo apt-get install python-scipy

OpenCV

This wil install OpenCV, and the Python bindings:

$ sudo apt-get install libopencv-dev python-opencv

Some links:

Other Hardware

Arduino

This Instructable has a really good overview of how to instal all the necessary packages to get your Pi to talk to an Arduino: “Arduino / Raspberry Pi Internet Radio“.

$ apt-get install arduino

And other Python dependencies:

$ sudo pip install nanpy
$ sudo pip install pyserial

Arduino to Maya Communication via Python

Arduino + light sensor talking to a sphere in Maya

I’ve wanted for some time to get my Arduino to talk with my 3d application of choice, Maya.  There were a few hurdles to overcome first:

  1. The Arduino communicates to the computer over the serial port (easily, by default).
  2. Maya (to my knowledge), has no built-in serial communication.  If you can find a built in mel command or API call, let me know 😉
  3. Maya comes with its own version of the Python scripting language (2.6ish)
  4. Python (external to Maya) has it’s own (separately installed)  pySerial module.  BUT:
    1. pySerial is a 32-bit app  (no 64-bit build I can find, and I’m not smart enough to recompile it to 64-bit).
    2. I’m running a 64-bit version of Maya, with a 64-bit version of Python = I can’t use pySerial in Maya :-(

Maya can however receive incoming communication over a commandPort, which you can ‘pretend’ is a serial port.  Below I’ll describe how to do that.  A bunch of these steps I’d already discussed in previous blog posts here or on my mel wiki, which I’ll list individually first:

Overview of the process:

  1. Author Arduino code to read sensor data and send it over the serial port.
  2. Author Python code in Maya (Maya’s version of 64-bit Python 2.6) to setup a commandPort, and to do ‘something’ with the incoming data.
  3. Author Python code external to Maya (in 32-bit Python 2.6) to receive the Arduino serial data (using pySerial), and broadcast it to the open Maya commandPort.

Notes about the commandPort code below:

  • I’ve hard-coded the commandPort data below to the address of  “127.0.0.1:7777”.
  • 127.0.0.1 is the localHost address of your machine, you shouldn’t change that.  But the “7777” is an arbitrary port number I made up, feel free to change it.
  • The important thing is that it must be consistent in all the places referenced in the code below.

Step 1:  Author Arduino Code:

This is a very simple sketch showing you the bare-bones requirements. In my case, I’ve hooked up an analog sensor to pin 5 (in my case, it’s a light sensor).
Upload this to the Arduino and start broadcasting!  You can open the Arduino Serial Monitor to see what it’s up to, but be sure to close the monitor before you do any other work.

/**
SerialSend01
Eric Pavey 2011-01-26

Sketch will print the value from the sensor to the serial port.
Sensor is plugged into analog pin 5
*/

#define SENSOR 5
int val = 0;

void setup(){
  Serial.begin(9600);
}

void loop(){
  val = analogRead(SENSOR);
  // Print to the serial port:
  Serial.println(val);
  delay(100);
}

Step 2: Author Python code in Maya:

The below code could eventually be made into a well-packaged Maya-Python module, but for the time being you can just paste it into the Script Editor for execution.  Thing to note:

  • The Maya commandPort command has a ‘prefix’ parameter that takes the name of a mel procedure (not Python function) that can intercept the incoming data.  Because of this, we use Python to create a simple wrapper mel procedure that in turn calls to the Python function that does the work.
  • In the below example, I have the Python function query for the existence of a ‘pSphere1’ object in Maya, and if it finds it, will scale it based on the passed in Arduino sensor values.  This should obviously be changed to something way more cool for what you’re doing :-)
# Eric Pavey - 2011-01-26
# In Maya, via Python:
import maya.cmds as mc
import maya.mel as mm

# Our mel global proc.
melproc = """
global proc portData(string $arg){
    python(("portData(\\"" + $arg + "\\")"));
}
"""
mm.eval(melproc)

# Our Python function that can be changed to do whatever we want:
def portData(arg):
    """
    Read the 'serial' data passed in from the commandPort
    """
    print "Recieved!: ", arg

    # Some silly example code to scale a sphere:
    mappedVal = (float(arg)/1023.0) * 10
    if mc.objExists('pSphere1'):
        mc.setAttr('pSphere1.scale', mappedVal, mappedVal, mappedVal)

# Open the commandPort.  The 'prefix' argument string is calling to the defined
# mel script above (which then calls to our Python function of the same name):
mc.commandPort(name="127.0.0.1:7777", echoOutput=False, noreturn=False,
               prefix="portData", returnNumCommands=True)
mc.commandPort(name=":7777", echoOutput=False, noreturn=False,
               prefix="portData", returnNumCommands=True)

Step 3: Author Python module to receive Arduino serial data and broadcast to Maya:

You must make sure you’ve previously downloaded and installed pySerial to a place where your system-installed Python can see it.  And it goes without saying you also need to have Python 2.6 installed as well.

This code will intercept the Arduino serial data, and send it to Maya over the commandPort.  It will only send new data, meaning, it will only send data that has changed from the previous data received.

# arduinoRead.py
# Python module external to Maya
# Eric Pavey - 2011-01-26

import socket
import serial

ARDUINO =  "COM3"

def main():
    maya = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    maya.connect(("127.0.0.1", 7777))
    ser =  serial.Serial(ARDUINO, timeout=1)
    prevVal = None
    while 1:
        # Read the serial value
        ser.flushInput()
        serialValue = ser.readline().strip()
        # Catch any bad serial data:
        try:
            if serialValue != prevVal:
                # Print the value if it differs from the prevVal:
                maya.send(str(serialValue))
                prevVal = serialValue
        except ValueError:
            pass

if __name__ == '__main__':
    main()

Save the above code as a Python module, and then execute it from a shell:

c:\pythonStuff\python arduinoRead.py

This should form the link between the broadcasting Arduino, and the listening Maya session, converting from serial data to data sent over Maya’s commandPort.

Result:

In Maya, make a sphere, and rename it to ‘pSphere1’ if it’s not already.  If all the code is working, you should see the script editor print the received Arduino data whenever it changes, and you should see the scale of your sphere be effected by that data.  Magic!

Python lolshield graphics

Or pylolgraph for short.  See latest info for this subject over on it’s official page.

My son and I soldered together a lolshield for the Arduino Duemilanove we picked up at the 2010 Maker Faire:

(Video Note: The flickering you see is based on the camera capture, it doesn’t actually do that…)

After making it… what to do with it?  I thought it would be fun to make a Python \ Arduino library that would allow you to send Pygame graphics to the lolshield, and that’s what I implemented.

There are two main parts to the library:

And, I’ve made an example Pygame application illustrating usage:

You can also download all three in a zip here pylolgraph.zip

How to use:

  • My system is WinXP.  Not tested on anything else.
  • Download pylolgraph.pde, and upload it to your Arduino.  Make sure the BAUD variable matches that in your Python module (below).
  • Download pylolgraph.py, put it in your Python path.
  • Download example01.py:  Set it’s BAUD variable to match that in pylolgraph.pde, and set its PORT variable to be the port your Arduino is on (will vary depending on your OS).
  • Start pylolgraph.pde on the Arduino.  Run example01.py from the command-line or double-click the icon: You should see a small Pygame window pop up:  When you click the LMB, a white donut will appear in the Pygame window.  The same donut should then appear on the lolshield.

Inspect the documentation in pylolgraph.py for more details on implementation.  Here is example pseudo-code for writing your own Pygame application with the code:

import pygame
import pylolgraph

# Setup some constants:
# Create a resolution that corresponds to the lolshield.
# See docs on the pylolgraph.LOLShield.setSurface() method
# for acceptable resolutions.
WIDTH, HEIGHT = (448, 288)
# Baud rate must be the same as setup in pylolgraph.pde
BAUD = 28800
# Port the Arduino is on, on my WinXP box.
PORT = 'COM4'

# Start Pygame application:
# Make surface that will have its data sent to lolshield:
screenSurf = pygame.display.set_mode((WIDTH, HEIGHT))

# Setup lolshield object:
lolshield = pylolgraph.LolShield(port=PORT, baudrate=BAUD)
# Set the surface that will have its pixel data sent to the Arduino\lolshield:
lolshield.setSurface(screenSurf)

# inside main loop:
    # Draw stuff to screenSurf.  Then:
    lolshield.sendData()

Python talks to the Arduino…

Sort of a followup to my previous post ‘Arduino talks to Processing, Python…‘, I thought I’d try going the other way:  Send commands to the Arduino from Python over the serial port.

My son and I recently soldered together a lolshield (‘lots of LEDs’) for the Arduino.  The ultimate goal for this is to have Python, via Pygame (most likely) run graphics on the lolshield as if it was a mini-flatscreen.  But first I need to get something sent from Python to Arduino, and this was surprisingly hard.

First, the internets came to my aid and I got some sample code allowing the Arduino to read a single character from the serial port, and blink an LED that number of times.  The source was by Tod E. Kurt, and I got it off his  page here.  My modified version is below (modified mainly with docs so I could understand what’s going on…)

// Arduino Code:
// Below, 'character' types are defined:  They hold 1 byte of data, 256 values.
// A char can be interpreted as a small number (0-255) or as a member of the
// ASCII set (which is what we deal with below).  Characters expressed as
// ASCII are surrounded in single-quotes, like '5'.
// Thus each char has a corresponding numeric value can thus be tested against.

int ledPin = 13;   // select the pin for the LED
int val = 0;       // variable to store the data from the serial port

void setup() {
 pinMode(ledPin,OUTPUT);    // declare the LED's pin as output
 Serial.begin(9600);        // connect to the serial port
}

void loop () {
  if (Serial.available()) {
    // For the below examples, let's pretend that the passed-in serial 
    // value is character '5'.
    // Since the declared variable val is an int, it converts the char 
    // value passed in into an int.
    // If char val = '5', the numeric representation is 53.
    val = Serial.read();      // read the serial port

    // If the stored value is a single-digit number, blink the LED 
    // that number of times.
    // Here we compare the int value of val against the int values 
    // of the string.
    // Characters '0' and '9' are equivalent to integer 48 and 57.
    if (val > '0' && val <= '9' ) {
      Serial.println(val);
      // Convert from char to int:
      // From above, int conversion of val, which is char '5', is 53.
      // int conversion of char '0' is 48.
      // 53-48 = 5  : blink that # of times
      val = val - '0';  
      for(int i=0; i<val; i++) {
        Serial.println("blink!");
        digitalWrite(ledPin,HIGH);
        delay(150);
        digitalWrite(ledPin, LOW);
        delay(150);
      }
    }
  }
}

Now for the Python stuff.  On the ‘Arduino: Playground‘ site, I found this example Python code using the pySerial libary:

>>> import serial # if you have not already done so
>>> ser = serial.Serial('/dev/tty.usbserial', 9600)
>>> ser.write('5')

And it works, presuming you’re in the interactive Python shell.  If however you try to make a module out of the same code and execute it, it will fail:  No multi-blinking LED.  After researching several posts of other people that had similar issue (here, here, here, and here) I tracked down the main culprit:  When you make a connection to the serial port via Python, it sends a reset command to the Arduino. If you immediately send your data to the port immediately after, the Arduino won’t be initialized and ready to receive it.  To solve this, we simply pause the module for a bit while the Arduino does its thing:

# simpleSerialSend.py
import sys
import serial
import time
PORT = 'COM4' # The port my Arduino is on, on my WinXP box.

def main(val=5):
    # Open a connection to the serial port.  This will reset the Arduino, and
    # make the LED flash once:
    ser = serial.Serial(PORT)

    # Must given Arduino time to rest.
    # Any time less than this does not seem to work...
    time.sleep(1.5)

    # Now we can start sending data to it:
    written = ser.write(val)
    ser.close()
    print "Bytes Written to port:", written
    print "Value written to port: '%s'"%val

if __name__ == '__main__':
    args = sys.argv
    try:
        main(args[1])
    except IndexError:
        main()

This module can now be ran from the command prompt, and you can optionally pass in (from 0->9) the number of times you want the LED to blink:

c:\pyModules\simpleSerialSend.py 5

When this runs, you’ll see the LED blink once when the reset happens, a 1.5 second pause, and then the LED will blink 5 times.

What’s interesting is I tried this same thing with Processing, and failed, and I presume for the same reason:  The Processing sketch was executing too fast to allow the Arduino time to warm up.  And, there doesn’t seem to be a ‘pauses \ sleep \ wait’ function in Processing.  I tried using java.lang.Thread, but it didn’t seem to pause the sketch until it was done running.  So I need to do some more research there.  Had I got that working, then the title of this blog post would probably be different 😉

Arduino talks to Processing, Python…

Note:  This post has been updated, see notes below.

Been enjoying tinkering around with the Arduino and the Electronic Brick Kit I recently got. It’s easy to send data from the computer to the Arduino and run sketches there, but what about the other way? The Arduino can talk back with the computer over its serial port, so at that point any language that can read the serial port can read the Arduino’s data.  Since I’m most comfortable with Python and Processing, that’s what the below code covers.

Few things to note:

  • Python has no built-in serial modules\packages (to my knowledge), but I found several references to pySerial, that appears to be the go-to source for cross-platform serial info in Python.  So you will need that.
  • Update:  After a bit of thinking, I have got Python working independently from Pygame, see notes below.
    • (Old subject):  I couldn’t get Python working directly:  When I’d run a loop to capture the serial data, it would hang the shell.  I figured this was because it wasn’t ‘advancing in time’ (just looping endlessly on the first item), so I popped the code into Pygame, and it started working flawlessly.  There probably is a way to do this in Python, but this is my first stab at reading any kind of serial data.  So the Python example is implemented via Pygame.
  • This is all authored on  Win2k OS.  Serial ports on different OS’s are handled differently.  For the Python and Processing code I define a variable that sets which com port the Arduino is on (in my case, it’s COM5), which is something that you should have already defined via the Arduino IDE.  Just make sure those values match.  And again, if you’re on Linux of Mac, the serial port values will be different.
  • On both the Processing and (the old)  Python examples, they will draw a window with a circle inside that will change in size based on the passed in serial data. Based on the sensor I was using (twist sensor) on an analog pin, this maps the voltage of the sensor into values 0-1023, which are easy to then map into the on-screen graphics. The code will also print out to the shell\IDE the captured serial values.
  • Finally, I should point out I pulled a lot of info from the book Getting Started with Arduino.

Dependencies:

Begin:

Arduino:

Here is the Arduino code.  I have a rotational sensor on analog pin 5.  But you can use any kind of sensor that you want.  I picked the rotational sensor since it’s easy to see the values change.

/**
serialSensor
Eric Pavey 2009-12-26

Sketch will print the value from the sensor to the serial port
*/

#define SENSOR 5

int val = 0;

void setup(){
  Serial.begin(9600);
}

void loop(){
  val = analogRead(SENSOR);
  // Print to the serial port:
  Serial.println(val);
  delay(100);
}

When that is uploaded to the Arduino you can hit the ‘Serial Monitor’ button in the IDE, which will pop up a new window that shows the values captured from the serial port:  When I twist my rotational sensor, I see the result print in the serial monitor.  Pretty straight-forward.  Be sure to close the serial monitor window before you run any of the below code, or they will be blocked from accessing the serial port.

Processing:

The IDE’s for Processing and Arduino are very similar; the Arduino docs say it was ‘built on’ Processing, and the resembelence is strong.  When executed, will create a window, with a white circle inside thats size is controlled by the sensor data passed through the serial port.

Here is the Processing code:

/**
 * readArduinoSerial
 * Eric Pavey 2009-12-26
 * Read data from the computers serial port, that is being fed
 * by an Arduino sketch.  It's expecting values from 0->1023.
 */

import processing.serial.*;

// Create object from Serial class
Serial myPort;  

// Converted data received from the serial port
float val = 1.0;
float prevVal = 1.0;
int minSerial = 0;
int maxSerial = 1023;
// Define which port the Arduino is on:
String arduino = "COM5";

void setup(){
  smooth();
  frameRate(30);
  size(200, 200);
  myPort = new Serial(this, arduino, 9600);
}

void draw(){
  if ( myPort.available() > 0){
    String portVal = myPort.readString();
    // Trim off any extra chars that have no meaning
    // to our sketch.  If we don't do this, we can get
    // NaN float vals when converted.
    String trimmed = portVal.trim();
    if(trimmed.length() > 0){
      // if we have a valid value, update it:
      val = float(portVal);
    }
  }
  if(val != prevVal){
    println("New val: " + val);
    prevVal = val;
  }

  background(0);
  float mapVal = map(val, minSerial, maxSerial, 1, width);
  fill(255);
  ellipse(width/2, height/2, mapVal, mapVal);
}

Python / Pygame:

Like Processing, when executed, will create a window, with a white circle inside thats size is controlled by the sensor data passed through the serial port.

Here is the Python / Pygame code:

"""
readArduinoSerial.py
Eric Pavey - 2009-12-27

Read data from the computers serial port, that is being fed
by an Arduino sketch.  It's expecting values from 0->1023.
"""

import serial
import pygame
from pygame.locals import *
pygame.init()

WIDTH = 256
HEIGHT = 256
FRAMERATE = 30
# Define which com port the Arduino is on:
ARDUINO = "COM5"

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Arduino Serial Com.")
clock = pygame.time.Clock()

ser = serial.Serial(ARDUINO, timeout=1)
floatVal = 1.0
prevVal = 1.0

def main():
    global floatVal
    global prevVal
    cirCol = Color("white")
    looping = True

    while looping:
        clock.tick(FRAMERATE)
        screen.fill(0)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                looping = False

        # Read the serial value
        ser.flushInput()
        serialValue = ser.readline().strip()

        # Catch any bad serial data:
        try:
            floatVal = float(serialValue)/8.0
            if floatVal != prevVal:
                # Print the value if it differs from the prevVal:
                print "New Val: ", floatVal
                prevVal = floatVal
        except ValueError:
            pass
        pygame.draw.circle(screen, cirCol, (WIDTH/2, HEIGHT/2), floatVal)

        # update our display:
        pygame.display.update()

if __name__ == "__main__":
    main()

Update: Here is the new Python code sans-Pygame. It will print results directly to the shell it was executed from:

import serial

ARDUINO =  "COM4"

def main():
    ser =  serial.Serial(ARDUINO, timeout=1)
    prevVal = None
    while 1:
        # Read the serial value
        ser.flushInput()
        serialValue = ser.readline().strip()
        # Catch any bad serial data:
        try:
            if serialValue != prevVal:
                # Print the value if it differs from the prevVal:
                print "New Val: ", serialValue
                prevVal = serialValue
        except ValueError:
            pass

if __name__ == '__main__':
    main()

In Conclusion…

So while the implementation in Processing \Python is pretty simple, it opens doors into what could be.  Another interesting observation is that the Processing sketch was really ‘jumpy’:  It seems to capture values that aren’t being reported by the Arduino sketch, causing the circle to ‘jump’ in size occasionally.  However, the Pygame (and updated pure Python) app seems pretty rock solid, and no ‘jumping’ is reported.