Interacting with the Real World¶
As we already know, Python is able to interact with tons of things. In this section, we will interact with tangible objects, and learn how to connect with sensors and actuators branched, or not, with the computer.
Better with interaction
Check this week’s code in gitlab code club repo
Serial¶
Serial communication is an standard asynchronous protocol for communication.
RS232 are not that common anymore, but all your computers have at least one serial port, also known as… USB!.
Python comes with a library supporting serial communication. It’s called pyserial:
Installation¶
As usual, python packages are available through pip
:
pip search pyserial
pyserial (3.4) - Python Serial Port Extension
pip install pyserial
Usage¶
We can create a serial object by using:
import serial
ser = serial.Serial(PORT, BAUDRATE)
To check the PORT, in the terminal, we can use (sorry, only for MAC):
ls /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port
Or we can use this function in python:
def serial_ports():
"""Lists serial ports
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of available serial ports
"""
if sys.platform.startswith('win'):
ports = ['COM' + str(i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this is to exclude your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result
This will return a list of ports:
>>> ports = serial_ports()
>>> ports
['/dev/tty.Bluetooth-Incoming-Port', '/dev/tty.usbmodem1411']
If we take the first port, we can open it with a BAUDRATE of 115200:
ser = serial.Serial(ports[1], 115200)
Now, to read the serial, removing :
def ReadSerial(serial):
return serial.readline().replace("\r\n", "")
Write to the serial
serial.write('Hello')
If now we continuosly read and print the input, we have a data logger!:
while True:
timestamp = datetime.datetime.now()
reading = ReadSerial(ser)
#~ print reading
# Print it and flush standard output
print "{},{}".format(timestamp,reading)
sys.stdout.flush()
Terminal like a pro
Send the output of your program to a file with the output redirection >>
:
python read_serial.py >> log.dat
Altogether:
#!/usr/bin/python
# Import packages
import serial
import datetime
import glob
import sys
from sys import stdout
# Numpy
import numpy as np
# I2C device definition
PORT = '/dev/cu.usbmodem1411'
BAUDRATE = 115200
def serial_ports():
"""Lists serial ports
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of available serial ports
"""
if sys.platform.startswith('win'):
ports = ['COM' + str(i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this is to exclude your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result
def ReadSerial(serial):
return serial.readline().replace("\r\n", "")
# Retrieve constants (ports, time, header)
ports = serial_ports()
ser = serial.Serial(ports[1], 115200)
# print (ser)
# Create header
print ("TIME, LIGHT")
# Create the reading
while True:
timestamp = datetime.datetime.now()
reading = ReadSerial(ser)
#~ print reading
# Print it and flush standard output
print "{},{}".format(timestamp,reading)
sys.stdout.flush()