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