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.
Serial¶
Serial communication is an standard asynchronous protocol for communication. All our 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:
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 | #!/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() |