1 of 33

open('/dev/real_world')

Raspberry Pi Sensor and Actuator Control

Jack Minardi

Enthought Inc.

jminardi.github.io

2 of 33

Typical Computing

Data

0000-0010: 2f 2a 20 42-43 43 2e 68-0a 20 2a 20-30 33 2f 30

0000-0020: 36 2f 30 37-20 43 72 65-61 74 65 64-20 74 68 69

0000-0030: 73 20 61 73-20 61 20 73-75 62 63 6c-61 73 73 20

0000-0040: 6f 66 20 4c-61 74 74 69-63 65 52 65-67 75 6c 61

0000-0050: 72 33 64 2e-0a 2a 2f 0a-0a 23 69 6e-63 6c 75 64

0000-0060: 65 20 22 42-43 43 2e 68-22 0a 23 69-6e 63 6c 75

0000-0070: 64 65 20 3c-76 65 63 74-6f 72 3e 0a-23 69 6e 63

0000-0080: 6c 75 64 65-20 3c 63 6d-61 74 68 3e-0a 0a 76 6f

0000-0090: 69 64 20 42-43 43 3a 3a-53 65 74 75-70 28 20 73

0000-00a0: 68 6f 72 74-20 70 62 63-20 29 0a 7b-0a 20 20 20

0000-00b0: 20 2f 2a 20-49 66 20 6e-75 6d 5f 73-69 74 65 73

0000-00c0: 20 77 61 73-20 63 68 61-6e 67 65 64-20 69 6e 20

0000-00d0: 74 68 65 20-63 6f 6e 73-74 72 75 63-74 6f 72 2c

0000-00e0: 20 74 68 69-73 20 6d 61-6b 65 73 20-73 75 72 65

0000-00f0: 20 74 68 61-74 0a 20 20-20 20 20 2a-20 6c 65 6e

0000-0100: 67 74 68 20-69 73 20 70-72 6f 70 65-72 6c 79 20

0000-0110: 64 65 66 69-6e 65 64 2e-0a 20 20 20-20 20 2a 2f

0000-0080: 6c 75 64 65-20 3c 63 6d-61 74 68 3e-0a 0a 76 6f

0000-0090: 69 64 20 42-43 43 3a 3a-53 65 74 75-70 28 20 73

0000-00a0: 68 6f 72 74-20 70 62 63-20 29 0a 7b-0a 20 20 20

0000-00b0: 20 2f 2a 20-49 66 20 6e-75 6d 5f 73-69 74 65 73

0000-00c0: 20 77 61 73-20 63 68 61-6e 67 65 64-20 69 6e 20

0000-00d0: 74 68 65 20-63 6f 6e 73-74 72 75 63-74 6f 72 2c

0000-00e0: 20 74 68 69-73 20 6d 61-6b 65 73 20-73 75 72 65

Pictures

3 of 33

Physical Computing

http://www.flickr.com/photos/alpi-costerni

4 of 33

Today's Goal

ZMQ

RPi.GPIO

ServoBlaster

spidev

5 of 33

Overview / Definitions

Raspberry Pi

  • Small $35 linux computer with...

GPIO Pins

  • General Purpose Input/Output
  • "Bridge" to the real world

Sensor

  • Any device that "reads in" data from the real world

Actuator

  • A computer controllable device that moves in the real world

6 of 33

Parts needed

  • Raspberry Pi
    • SD card with OS
    • Network connection

  • Laptop/Desktop

  • Potentiometer

  • Hobby servo motor

  • ADC

  • LED

  • Breadboard

  • Pi Cobbler or Male-Female jumper cables

  • Male-Male jumper cables or Wire

  • Resistors

7 of 33

Operating System

Occidentals - Wheezy based

Comes preloaded with most everything you will need

http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/occidentalis-v0-dot-2

8 of 33

1Blink an LED.

2Read a pot.

3Stream data.

4

Servo control.

9 of 33

1Blink an LED.

2Read a pot.

3Stream data.

4

Servo control.

10 of 33

1. Blink an LED.

Typical LEDs work with 10-30 mA and drop about 2-3 volts

Calculate resistor needed based on max current and LED voltage ( R = (VS - VL) / I )

If you don't feel like doing math choose a resistance between 500 and 1500 ohms.

wikimedia.org

11 of 33

1. Blink an LED.

RPi.GPIO python package

code.google.com/p/raspberry-gpio-python/

It comes with Occidentals, if using another distro:

apt-get install python-rpi.gpio

or

pip install rpi.gpio

12 of 33

1. Blink an LED.

Software

import time

from itertools import cycle

import RPi.GPIO as io

io.setmode(io.BCM)

io.setup(12, io.OUT)

o = cycle([1, 0])

while True:

io.output(12, o.next())

time.sleep(0.5)

Hardware

13 of 33

1. Blink an LED.

Software

import time

from itertools import cycle

import RPi.GPIO as io

io.setmode(io.BCM)

io.setup(12, io.OUT)

o = cycle([1, 0])

while True:

io.output(12, o.next())

time.sleep(0.5)

Hardware

14 of 33

1Blink an LED.

2Read a pot.

3Stream data.

4

Servo control.

15 of 33

2. Read a pot.

A potentiometer (pot) is a

variable resistor.

A voltage is applied across the

outer pins and the knob position is sensed on the inner pin

This is an analog sensor, and the raspi can not read it without help.

wikimedia.org

16 of 33

2. Read a pot.

MCP3008 http://adafru.it/856

This chip is an Analog-to-Digital Converter (ADC)

It has 8 10-bit channels

Raspberry Pi uses SPI to communicate with it.

17 of 33

2. Read a pot.

spidev python package

github.com/doceme/py-spidev

To install:

git clone git://github.com/doceme/py-spidev

cd py-spidev/

sudo python setup.py install

For more information:

http://jeremyblythe.blogspot.co.uk/2012/09/raspberry-pi-hardware-spi-analog-inputs.html

18 of 33

2. Read a pot.

Software

import spidev

import time

spi = spidev.SpiDev()

spi.open(0,0)

def readadc(adcnum):

if not 0 <= adcnum <= 7:

return -1

r = spi.xfer2([1, (8+adcnum)<<4, 0])

adcout = ((r[1] & 3) << 8) + r[2]

return adcout

while True:

val = readadc(0)

print val

time.sleep(0.5)

Hardware

19 of 33

2. Read a pot.

Software

import spidev

import time

spi = spidev.SpiDev()

spi.open(0,0)

def readadc(adcnum):

if not 0 <= adcnum <= 7:

return -1

r = spi.xfer2([1, (8+adcnum)<<4, 0])

adcout = ((r[1] & 3) << 8) + r[2]

return adcout

while True:

val = readadc(0)

print val

time.sleep(0.5)

Hardware

20 of 33

1Blink an LED.

2Read a pot.

3Stream data.

4

Servo control.

21 of 33

3. Stream data.

ØMQ networking library

http://www.zeromq.org/

To install:

apt-get install python-zmq

pip install pyzmq

Described as "TCP on steroids"

REQUEST/REPLY pattern

22 of 33

3. Stream data.

Server

import zmq

context = zmq.Context()

socket = context.socket(

zmq.REP)

socket.bind('tcp://*:1980')

while True:

message = socket.recv()

print message

socket.send("I'm here")

Client

import zmq

context = zmq.Context()

socket = context.socket(

zmq.REQ)

a = 'tcp://192.168.1.6:1980'

socket.connect(a)

for request in range(10):

socket.send('You home?')

message = socket.recv()

print message

23 of 33

3. Stream data.

Server

import zmq

context = zmq.Context()

socket = context.socket(

zmq.REP)

socket.bind('tcp://*:1980')

while True:

message = socket.recv()

print message

socket.send("I'm here")

Client

import zmq

context = zmq.Context()

socket = context.socket(

zmq.REQ)

a = 'tcp://192.168.1.6:1980'

socket.connect(a)

for request in range(10):

socket.send('You home?')

message = socket.recv()

print message

24 of 33

3. Stream data.

Chaco - Interactive plotting library

Enaml - GUI development library

To install:

Download and install Enthought Canopy from enthought.com

or

Install the "Enthought Tool Suite" from PyPI

pip install ets

25 of 33

3. Stream data.

Model

class PlotModel(HasTraits):

plot = Instance(Plot)

def _plot_default(self):

data = ArrayPlotData()

x = np.arange(-3, 3, 0.1)

data['x'] = x

data['y'] = np.sin(x)

plot = Plot(data)

plot.plot(('x', 'y'))

plot.padding = (0, 0, 0, 0)

return plot

View

from enaml.widgets.api import (

MainWindow, EnableCanvas,

Container)

from plotmodel import PlotModel

enamldef Main(MainWindow):

id: main

attr model = PlotModel()

Container:

EnableCanvas:

component = model.plot

26 of 33

3. Stream data.

Model

class PlotModel(HasTraits):

plot = Instance(Plot)

def _plot_default(self):

data = ArrayPlotData()

x = np.arange(-3, 3, 0.1)

data['x'] = x

data['y'] = np.sin(x)

plot = Plot(data)

plot.plot(('x', 'y'))

plot.padding = (0, 0, 0, 0)

return plot

View

from enaml.widgets.api import (

MainWindow, EnableCanvas,

Container)

from plotmodel import PlotModel

enamldef Main(MainWindow):

id: main

attr model = PlotModel()

Container:

EnableCanvas:

component = model.plot

27 of 33

3. Stream data.

28 of 33

1Blink an LED.

2Read a pot.

3Stream data.

4

Servo control.

29 of 33

4. Servo control.

A servo can be set to a

given position.

Controlled with Pulse Width Modulation (PWM)

Min Position: 0.5 ms pulse

Max Position: 2.5 ms pulse

Period: ~20 ms

wikimedia.org

2.5 ms

.5 ms

~20 ms

30 of 33

4. Servo control.

ServoBlaster - Servo kernel module

https://github.com/richardghirst/PiBits

$ echo 3=120 > /dev/servoblaster

Servo Number

Pulse Width in 10 μs

Servo Number

0

1

2

3

4

5

6

7

Pin Number

4

17

18

21

22

23

24

25

31 of 33

4. Servo control.

Software

import time

import numpy as np

from robot_brain.servo import Servo

servo = Servo(0, min=60, max=200)

for val in np.arange(0, 1, 0.05):

servo.set(val)

time.sleep(0.1)

Hardware

https://github.com/jminardi/RobotBrain

32 of 33

4. Servo control.

Software

import time

import numpy as np

from robot_brain.servo import Servo

servo = Servo(0, min=60, max=200)

for val in np.arange(0, 1, 0.05):

servo.set(val)

time.sleep(0.1)

Hardware

https://github.com/jminardi/RobotBrain

33 of 33

Thanks! Questions?

All code can be found here:

jminardi.github.io

Contact:

jminardi@enthought.com

@jackminardi