Example: Python program sequence.py¶
A Python program was written to demonstrate how to communicate with the Arduino as an I/O controller using the cmd_response interface.
Use the circuit described previously (see Electronic Circuit: photocell and LED):
PWM:
- pin 11: LED, pointing at the photocell, sets \(V_{LED}\)
AI:
- pin 0: photocell, monitors \(V_P\)
- pin 1: LED supply voltage, monitors \(V_{LED}\)
The basics of this program are:
attach to the USB port
On linux, confirm the USB connection using:
>>> lsusb | grep FT232 Bus 005 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
wait (arbitrary time) for the port to connect
configure the PWM and averaging for a simple circuit, 0.1 s period, PWM on pin 11, AI on pins 0 and 1:
!t 100 !ai:watch 0 1 !ai:watch 1 1 !pin 11 1
wait a short time for the averaging period to set
step the PWM (\(V_P\)) through its range:
'!pwm 11 %d' % pwm
wait a short time for the ADC to settle and the averaging period to complete
measure the AI channels (\(V_P\) and \(V_{LED}\)) several times at each step:
?ai 0 ?ai:mean 0 ?ai:mean 1
Note the difference between readings of ?ai 0 and ?ai:mean 0.
This shows the effectiveness of signal averaging. [1]
| [1] | Also see the Arduino Smoothing example: http://arduino.cc/en/Tutorial/Smoothing |
Program Source Code¶
The full python program relies on the additional package pyserial:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #!/usr/bin/env python
'''Exercise the Arduino cmd_response interface'''
import time
import serial # easy_install -U pyserial
ARDUINO_SERIAL_PORT = '/dev/ttyUSB0'
SERIAL_PORT_BAUD = 115200
PERIOD_ms = 100
SLEEP_TIME_S = 0.003*PERIOD_ms
REPETITIONS = 10
PORT_TIMEOUT = 2 # seconds
class Cmd_Response(object):
'''interface class with cmd_response Arduino sketch'''
def __init__(self, serial_port, baud=115200,
delimiter='\n', timeout=PORT_TIMEOUT):
self.serial_port = serial_port
self.baud = baud
self.delimiter = delimiter
self.timeout = timeout
self.port = serial.Serial(serial_port, baud, timeout=self.timeout)
self.port.flushInput()
def send(self, cmd):
'''write the command to the USB port'''
self.port.write(cmd + self.delimiter)
def receive(self):
'''read the device response from the USB port'''
return self.port.readline().strip()
def request(self, cmd):
'''return the result from the command'''
self.send(cmd)
return self.receive()
def report(self, cmd):
'''print the response to the command'''
print "%s " % cmd,
print self.request(cmd)
def measure(port, pwm, reps=1):
'''report reading(s): LED photocell <photocell>'''
port.request('!pwm 11 %d' % pwm)
time.sleep(SLEEP_TIME_S)
port.receive()
for _ in range(reps):
time.sleep(PERIOD_ms*0.0011)
V_led_raw = int(port.request('?ai 0'))
V_led = float(port.request('?ai:mean 0'))/1000.
V_P = float(port.request('?ai:mean 1'))/1000.
print "%d %d %.3f %.3f" % (pwm, V_led_raw, V_led, V_P)
def main():
'''test the Arduino cmd_response interface'''
global PERIOD_ms
cr = Cmd_Response(ARDUINO_SERIAL_PORT, SERIAL_PORT_BAUD)
time.sleep(2.0)
cr.request('!t %d' % PERIOD_ms)
cr.request('!ai:watch 0 1')
cr.request('!ai:watch 1 1')
cr.request('!pin 11 1')
if False: # development use
for _ in ('?id', '?v', '?t', '?k', '?rate'):
cr.report(_)
time.sleep(SLEEP_TIME_S)
rate = cr.request('?rate')
print rate
print cr.request('?t')
print cr.request('?ai 0')
print cr.request('?ai:mean 0')
print cr.request('?ai:mean 1')
for pwm in range(0, 256, 5):
measure(cr, pwm)
for pwm in range(255, 0, -5):
measure(cr, pwm)
# change to a longer averaging period
PERIOD_ms = 1000
cr.request('!t ' + str(PERIOD_ms))
for pwm in range(0, 256, 5):
measure(cr, pwm, REPETITIONS)
cr.request('!pwm 11 0') # turn the pwm off
if __name__ == '__main__':
main()
|
Program Output¶
The full output (results.txt),
more than 600 lines, is too long for this documentation.
Here are the first few lines, to give you an idea:
1 2 3 4 5 6 7 8 9 10 | 0 0 0.000 0.000
5 55 50.812 18.393
10 74 77.818 34.528
15 92 97.936 57.812
20 121 114.451 73.577
25 118 128.521 98.010
30 141 140.944 118.253
35 160 152.141 132.800
40 188 162.221 157.675
45 201 171.575 178.688
|