Internet of Things With Python - Sample Chapter
Internet of Things With Python - Sample Chapter
$ 49.99 US
31.99 UK
P U B L I S H I N G
Gastn C. Hillar
Internet of Things
with Python
ee
Sa
m
pl
C o m m u n i t y
E x p e r i e n c e
D i s t i l l e d
Internet of Things
with Python
Interact with the world and rapidly prototype IoT applications
using Python
Gastn C. Hillar
eight. He began programming with the legendary Texas TI-99/4A and Commodore
64 home computers in the early 80s. He has a bachelor's degree in computer science,
in which he graduated with honors, and an MBA, in which he graduated with an
outstanding thesis. At present, Gastn is an independent IT consultant and freelance
author who is always looking for new adventures around the world.
He has been a senior contributing editor at Dr. Dobb's and has written more than a
hundred articles on software development topics. Gaston was also a Microsoft MVP
in technical computing. He has received the prestigious Intel Black Belt Software
Developer award seven times.
He is a guest blogger at Intel Software Network (http://software.intel.com).
You can reach him at gastonhillar@hotmail.com and follow him on Twitter at
http://twitter.com/gastonhillar.
His blog is http://csharpmulticore.blogspot.com.
He lives with his wife, Vanesa, and his two sons, Kevin and Brandon.
Preface
Internet of Things, also known as IoT, is changing the way we live and represents
one of the biggest challenges in the IT industry. Developers are creating lowcost devices that collect huge amounts of data, interact with each other, and take
advantage of cloud services and cloud-based storage. Makers all over the world are
working on fascinating projects that transform everyday objects into smart devices
with sensors and actuators.
A coffee cup is not a simple object anymoreit can send a message to your
smartwatch indicating that the liquid inside has the right temperature so that you
can drink it without worrying about checking whether it is too hot. In case you move
the coffee cup before you receive the message, your wearable vibrates to indicate that
you don't have to drink it yet.
You can check the coffee level of the coffee dispenser in your smartphone, and
you won't have to worry about ordering more coffee: the coffee dispenser will
automatically place an online order to request coffee when the coffee level is not
enough to cover the rest of the day. You just need to approve the online order that
the coffee dispenser suggests from your smartwatch. Based on certain statistical
algorithms, the coffee dispenser will know the appropriate time to make the order.
What happens when more usual visitors arrive at the office? Their smartwatches
or smartphones will communicate with the coffee dispensers and they will place
orders in case the probable consumption of decaffeinated coffee increases too much.
We have smart coffee cups, smart coffee dispensers, smartwatches, smartphones,
and wearables. All of them take advantage of the cloud to create a smart ecosystem
capable of providing us with all the different types of coffees we need for our day.
Preface
The Intel Galileo Gen 2 board is an extremely powerful and versatile minicomputer
board for IoT projects. We can boot a Linux version and easily execute Python scripts
that can interact with the different components included on the board. This book will
teach you to develop IoT prototypes, from selecting the hardware to all the necessary
stacks with Python 2.7.3, its libraries, and tools. In case you need a smaller board or
an alternative, all the examples included in the book are compatible with Intel Edison
boards, and therefore, you can switch to this board in case you need to.
Python is one of the most popular programming languages. It is open source,
multiplatform, and you can use it to develop any kind of application, from websites
to extremely complex scientific computing applications. There is always a Python
package that makes things easier for us in order to avoid reinventing the wheel and
solve problems faster. Python is an ideal choice for developing a complete IoT stack.
This book covers all the things you need to know to transform everyday objects into
IoT projects.
This book will allow you to prototype and develop IoT solutions from scratch with
Python as the programming language. You will leverage your existing Python
knowledge to capture data from the real world, interact with physical objects,
develop APIs, and use different IoT protocols. You will use specific libraries to easily
work with low-level hardware, sensors, actuators, buses, and displays. You will learn
how to take advantage of all the Python packages with the Intel Galileo Gen 2 board.
You will be ready to become a maker and to be a part of the exciting IoT world.
Preface
Chapter 3, Interacting with Digital Outputs with Python, teaches us how to work with
two different libraries to control digital outputs in Python: mraa and wiring-x86. We
will connect LEDs and resistors to a breadboard and write code to turn on between
0 to 9 LEDs. Then, we will improve our Python code to take advantage of Python's
object-oriented features, and we will prepare the code to make it easy to build an API
that will allow us to print numbers with LEDs with a REST API.
Chapter 4, Working with a RESTful API and Pulse Width Modulation, has us working
with Tornado Web Server, Python, the HTTPie command-line HTTP client, and the
mraa and wiring-x86 libraries. We will generate many versions of RESTful APIs that
will allow us to interact with the board in computers and devices connected to the
LAN. We will be able to compose and send HTTP requests that print numbers in
LEDs, change the brightness levels for three LEDs, and generate millions of colors
with an RGB LED.
Chapter 5, Working with Digital Inputs, Polling and Interrupts, explains the difference
between reading pushbutton statuses with polling and working with interrupts and
interrupt handlers. We will write code that will allow the user to perform the same
actions with either pushbuttons in the breadboard or HTTP requests. We will combine
code that reacts to changes in the statuses of the pushbuttons with a RESTful API built
with Tornado Web Server. We will create classes to encapsulate pushbuttons and the
necessary configurations with the mraa and wiring-x86 libraries.
Chapter 6, Working with Analog Inputs and Local Storage, explains how to work with
analog inputs to measure voltage values. We will measure voltages with an analog
pin and both the mraa and the wiring-x86 libraries. We will be able to transform a
variable resistor into a voltage source and make it possible to measure the darkness
level with an analog input, a photoresistor, and a voltage divider. We will fire actions
when the environment light changes, and we will work with both analog inputs and
outputs. We will register events by taking advantage of the logging features included
in the Python standard library and the USB 2.0 connector included in the Intel
Galileo Gen 2 board.
Chapter 7, Retrieving Data From the Real World with Sensors, has us working with a
variety of sensors to retrieve data from the real world. We will take advantage of
the modules and classes included in the upm library that will make it easy for us
to start working with analog and digital sensors. We will learn the importance of
considering units of measurement because sensors always provide values measured
in a specific unit, which we must consider. We will measure the magnitude and
direction of proper acceleration or g-force, ambient temperature, and humidity.
Preface
Take advantage of the upm library with LCD displays and actuators
Use an LCD display with an RGB backlight that works with the I2C bus
[ 235 ]
For example, we can use simple LEDs to provide information that we can represent
with colors. For example, a red LED that turns on can indicate that our temperature
sensor connected to the board has detected that the ambient temperature is higher
than 80 degrees Fahrenheit (F) or 26.66 degrees Celsius (C). A blue LED that
turns on can indicate that our temperature sensor had detected that the ambient
temperature is lower than 40 degrees Fahrenheit (F) or 4.44 degrees Celsius (C).
A red LED turned on can indicate that the temperature is between these two values.
These three LEDs allow us to provide valuable information to the user.
We can also achieve the same goal using a single RGB LED and work with pulse
width modulation (PWM) to change its color based on the measured ambient
temperature value, as we learned in Chapter 4, Working with a RESTful API and
Pulse Width Modulation.
However, sometimes colors aren't enough to provide a detailed and accurate
information to the user. For example, sometimes we want to display the humidity
level with a percentage value and a few LEDs aren't enough to represent numbers
from 0 to 100%. If we want to be able to display a 1% step, we would require 100
LEDs. We don't have 100 GPIO pins, and therefore, we would require a shield or
breakout board with 100 LEDs and a digital interface such as an I2C bus to allow us
to send commands indicating the number of LEDs that we want to be turned on.
In these cases, an LCD screen that allows us to print a specific number of characters
might be an appropriate solution. For example, on an LCD screen that allows us to
display 16 characters per line, with 2 lines of 16 characters, known as a 16x2 LCD
module, we can display the temperature in the first line and the humidity level in the
second line. The following table shows an example of each line with the text and the
values considering that we have 16 columns and 2 rows for the characters.
T
H
e
u
m
m
p
i
.
d
4
i
.
8
2
0
F
%
The 16x2 LCD module provides a clear description for each value, a floating point
value and a unit of measure. Thus, we will use a 16x2 LCD module for our example.
The following picture shows an example of the location of each character in a 16x2
LCD screen:
[ 236 ]
Chapter 8
There are LCD modules with different features and we must consider a lot of the
things we learned when we analyzed sensors in Chapter 7, Retrieving Data from the
Real World with Sensors. The following list enumerates the most important things
that we must consider when we select an LCD module and their description. As we
analyzed many of these things when we learned about sensors, we won't repeat the
descriptions for the common items.
Compatibility with Intel Galileo Gen 2 board and the voltage supply that
we are using (5V or 3.3V).
Power consumption.
Connection type: Some LCD displays consume too many pins, and therefore,
it is very important to check all the pins that they require. The most common
connection types for LCD displays are the I2C bus, the SPI bus, and the UART
port. However, some LCD displays require a bus or port combined with
additional GPIO pins.
Number of columns and rows: Based on the text we have to display, we will
select the LCD display with the appropriate number of columns and rows
that can display the characters.
[ 237 ]
Response time: It is very important to determine how much we can wait for
the LCD display to show the new content that replaces the text that is being
displayed or to clear the display.
Supported character set and built-in fonts: Some LCD displays support
user-defined characters, and therefore, they allow us to configure and display
custom characters. It is also important to check whether the LCD display
supports characters for the languages in which we have to display the text.
Backlight color, text color and contrast level: Some LCD displays allow us
to change the backlight color while others have a fixed backlight color. An
RGB backlight makes it possible to combine red, green, and blue components
to determine the desired backlight color. In addition, it is always important
to take into account whether the contrast level is appropriate for the light
conditions in which you will need to display information.
Cost.
[ 238 ]
Chapter 8
The following diagram shows the digital temperature and humidity breakout, the
LCD RGB backlight breakout, the necessary wirings, and the wirings from the Intel
Galileo Gen 2 board to the breadboard. The Fritzing file for the sample is iot_
fritzing_chapter_08_01.fzz and the following image is the breadboard view:
[ 239 ]
The following image shows the schematic with the electronic components
represented as symbols:
[ 240 ]
Chapter 8
The SDA pin is connected to both the breakout board pins labeled SDA.
This way, we connect both the digital temperature and humidity sensor
and the LCD backlight to the serial data line for the I2C bus.
The SCL pin is connected to both the breakout board pins labeled SCL. This
way, we can connect both the digital temperature and humidity sensor and
the LCD backlight to the serial clock line for the I2C bus.
The power pin labeled 3V3 is connected to the digital temperature and
humidity sensor breakout board power pin labeled VCC.
The power pin labeled 5V is connected to the LCD backlight breakout board
power pin labeled VCC.
The ground pin labeled GND is connected to both the breakout board pins
labeled GND.
Now, it is time make all the necessary wirings. Don't forget to shut down the
Yocto Linux, wait for all the onboard LEDs to turn off and unplug the power supply
from the Intel Galileo Gen 2 board before adding or removing any wire from the
board's pins.
[ 241 ]
We will create an Lcd class to represent the 16x2 LCD RGB backlight and make
it easier for us to set the background color and write the text in two lines without
worrying about the specific methods when working with an instance of the
Jhd1313m1 class. We will use the Jhd1313m1 class to interact with the LCD and its
RGB backlight. The following lines show the code for the new Lcd class that works
with the upm library, specifically with the pyupm_i2clcd module. The code file for
the sample is iot_python_chapter_08_01.py.
import pyupm_th02 as upmTh02
import pyupm_i2clcd as upmLcd
import time
class Lcd:
# The I2C address
lcd_i2c_address =
# The I2C address
rgb_i2c_address =
[ 242 ]
Chapter 8
The Lcd class declares two class attributes: lcd_i2c_address and rgb_i2c_
address. The first class attribute defines the I2C address for the LCD display, that is,
the address that will process the commands that locate the cursor and write text once
the cursor is located in a specific row and column. The address is 3E in hexadecimal
(0x3E). If we just see a 0x3E within the code, we don't understand that it is an I2C
bus address for the LCD display. The second class attribute defines the I2C address
for the RGB backlight, that is, the address that will process the commands that set
the red, green, and blue components for the backlight color. The address is 62 in
hexadecimal (0x62). If we just see a 0x62 within the code, we don't understand that
it is an I2C bus address for the RGB backlight. These class attributes make it easier to
read the code.
We have to specify the I2C bus number to which the both the 16x2 LCD and the RGB
backlight are wired when we create an instance of the Lcd class in the bus required
argument. In addition, it is necessary to specify the values for the red, green and
blue color components to configure the background color for the RGB backlight.
The constructor, that is, the __init__ method, creates a new upmLcd.Jhd1313m1
instance with the received bus argument followed by the lcd_i2c_address and
rgb_i2c_address class attributes and saves the reference for the new instance in the
lcd attribute. Then, the code calls the clear method for the new instance to clear the
LCD screen. Finally, the code calls the set_background_color method with the red,
green, and blue values received as arguments to configure the background color for
the RGB backlight.
The class declares the set_background_color method that calls the lcd.setColor
method with the red, green and blue values received as arguments. Under the
hoods, the upmLcd.Jhd1313m1 instance will write data to the slave device whose
address is equal to the rgb_i2c_address class attribute through the I2C bus to
specify the desired value for each color component. We just create a specific method
to follow Python naming conventions and make our final code that uses our class
easier to read.
The class defines the following two additional methods to make it easy to print text
on the first and the second row of the LCD display:
print_line_1
print_line_2
[ 243 ]
The print_line_1 method calls the setCursor method for the upmLcd.Jhd1313m1
instance (self.lcd), with 0 as the value for both the row and the column argument,
to locate the cursor in the first row and the first column. Then, a call to the write
method for the the upmLcd.Jhd1313m1 instance (self.lcd) with the message
reviewed as a parameter as an argument prints the received string in the LCD
display. Under the hoods, the upmLcd.Jhd1313m1 instance will write the data to
the slave device whose address is equal to the lcd_i2c_address class attribute
through the I2C bus to specify the desired location for the cursor and then to write
the specified text starting in the position in which we have located the cursor. The
first row is identified with 0, but we named the method print_line_1 because it
makes it easier for us to understand that we are writing a message in the first line of
the LCD screen.
The print_line_2 method has the same two lines of code than the print_line_1
method with just one difference: the call to the setCursor method specifies 1 as the
value for the row argument. This way, the method prints a message in the second
line of the LCD screen.
Now, we will create a subclass of the previously coded Lcd class named
TemperatureAndHumidityLcd. The subclass will specialize the Lcd class to allow
us to easily print a temperature value expressed in degrees Fahrenheit in the first
line of the LCD screen and print a humidity value expressed in percentage in the
second line of the LCD screen. The following lines show the code for the new
TemperatureAndHumidityLcd class. The code file for the sample is iot_python_
chapter_08_01.py.
class TemperatureAndHumidityLcd(Lcd):
def print_temperature(self, temperature_fahrenheit):
self.print_line_1("Temp.
{:5.2f}F".format(temperature_
fahrenheit))
def print_humidity(self, humidity):
self.print_line_2("Humidity
{0}%".format(humidity))
The new class (TemperatureAndHumidityLcd) adds the following two methods to its
superclass (Lcd):
text that displays the temperature value expressed in degrees Fahrenheit (F)
received in the temperature_fahrenheit argument.
[ 244 ]
Chapter 8
Now, we will write a loop that will display the ambient temperature expressed in
degrees Fahrenheit (F) and the humidity value in the LCD screen, every 10 seconds.
The code file for the sample is iot_python_chapter_08_01.py.
if __name__ == "__main__":
temperature_and_humidity_sensor = \
TemperatureAndHumiditySensor(0)
lcd = TemperatureAndHumidityLcd(0, 0, 0, 128)
while True:
temperature_and_humidity_sensor.\
measure_temperature_and_humidity()
lcd.print_temperature(
temperature_and_humidity_sensor.temperature_fahrenheit)
lcd.print_humidity(
temperature_and_humidity_sensor.humidity)
print("Ambient temperature in degrees Celsius: {0}".
format(temperature_and_humidity_sensor.temperature_
celsius))
print("Ambient temperature in degrees Fahrenheit: {0}".
format(temperature_and_humidity_sensor.temperature_
fahrenheit))
print("Ambient humidity: {0}".
format(temperature_and_humidity_sensor.humidity))
# Sleep 10 seconds (10000 milliseconds)
time.sleep(10)
The highlighted lines show the changes made to the __main__ method compared
with the previous version. The first highlighted line creates an instance of the
previously coded TemperatureAndHumidityLcd class with 0 as the value of the
bus argument, 0 for red and green, and 128 for blue to set the background color
to light blue. The code saves the reference to this instance in the lcd local variable.
This way, the instance will establish a communication with the LCD screen and
the RGB backlight through the I2C bus. The RGB backlight will display a light blue
background.
Then, the code runs a loop forever and the highlighted line calls the lcd.print_
temperature method with temperature_and_humidity_sensor.temperature_
fahrenheit, that is, the measured temperature expressed in degrees Fahrenheit (F),
as an argument. This way, the code displays this temperature value in the first line of
the LCD screen.
[ 245 ]
After you run the example, turn on an air conditioner or heating system, to generate
a change in the ambient temperature and humidity. The LCD screen will display the
temperature and humidity and refresh it every 10 seconds.
[ 246 ]
Chapter 8
Now, we will replace the breakout board with a 16x2 LCD RGB backlight with a
16 grayscale 96-by-96 dot matrix OLED display module that also works with the
I2C bus, and we will use this new screen to display similar values with a different
configuration. The wirings are compatible with the previous breakout board.
As it happened in our previous example, the dot matrix OLED will also be
connected to the same I2C bus to which the temperature and humidity digital sensor
is connected. As the dot matrix OLED has an I2C address that is different than the
one used by the temperature and humidity digital sensor, we don't have problems
to wire the two devices to the same I2C bus.
We need the following additional part to work with this example: A SeeedStudio
Grove OLED Display 0.96", 16 grayscale 96-by-96 dot matrix OLED display module.
The 96-by-96 dot matrix OLED display provides us the chance to control 9,216 dots,
known as pixels. However, in this case, we just want to use the OLED display to
display a similar text than the one we displayed in our previous example, but with a
different layout.
If we use the default 8-by-8 character box, we have 12 columns (96/8) and 12 rows
(96/8) for characters. The following table shows an example of each line with the text
and the values.
T
F
4
a
0
h
.
r
2
C
4
e
.
l
5
s
5
H
L
8
u
e
0
m
v
%
i
e
d
l
[ 247 ]
After we replace the LCD screen breakout board with the OLED module, we will
have the following connections:
The SDA pin is connected to both breakout board pins labeled SDA. This
way, we connect both the digital temperature and humidity sensor and the
OLED module to the serial data line for the I2C bus.
The SCL pin is connected to both the breakout board pins labeled SCL. This
way, we connect both the digital temperature and humidity sensor and the
OLED module to the serial clock line for the I2C bus.
The power pin labeled 3V3 is connected to the digital temperature and
humidity sensor breakout board power pin labeled VCC.
The power pin labeled 5V is connected to the OLED module power pin
labeled VCC.
The ground pin labeled GND is connected to both the breakout board pins
labeled GND.
Now, it is time make all the necessary wirings. Don't forget to shutdown the Yocto
Linux, wait for all the onboard LEDs to turn off, and unplug the power supply
from the Intel Galileo Gen 2 board before adding or removing any wire from
the board's pins.
[ 248 ]
Chapter 8
The Oled class declares the oled_i2c_address class attribute that defines the I2C
address for the OLED display, that is, the address that will process the commands
that locate the cursor and write text once the cursor is located in a specific row and
column. The address is 3C in hexadecimal (0x3C).
We have to specify the I2C bus number to which the OLED display is wired when we
create an instance of the Oled class in the bus required argument. The constructor,
that is, the __init__ method, creates a new upmLcd. SSD1327 instance with the
received bus argument followed by the oled_i2c_address class attribute, and saves
the reference for the new instance in the oled attribute. Finally, the code calls the
clear method for the new instance to clear the OLED screen.
[ 249 ]
The class declared the print_line method to make it easy to print text on a specific
row. The code calls the setCursor method for the upmLcd.SSD1327 instance (self.
oled), with the received row value as the value for the row argument and 0 for the
column argument, to locate the cursor in the specified row and the first column.
Then, a call to the setGrayLevel and the write method for the the upmLcd.SSD1327
instance (self.oled) with the message reveiced as a parameter as an argument
prints the received string in the OLED display with the default 8-by-8 character box
with the gray level set to 12. Under the hoods, the upmLcd.SSD1327 instance will
write data to the slave device whose address is equal to the oled_i2c_address class
attribute through the I2C bus to specify the desired location for the cursor and then to
write the specified text starting in the position in which we have located the cursor.
Now, we will create a subclass of the previously coded Oled class named
TemperatureAndHumidityOled. The subclass will specialize the Oled class to
allow us to easily print a temperature value expressed in degrees Fahrenheit, the
temperature value expressed in degrees Celsius and a humidity value expressed in
percentage. We will use the previously explained layout for the text. The following
lines show the code for the new TemperatureAndHumidityOled class. The code file
for the sample is iot_python_chapter_08_02.py.
class TemperatureAndHumidityOled(Oled):
def print_temperature(self, temperature_fahrenheit, temperature_
celsius):
self.oled.clear()
self.print_line(0, "Temperature")
self.print_line(2, "Fahrenheit")
self.print_line(3, "{:5.2f}".format(temperature_fahrenheit))
self.print_line(5, "Celsius")
self.print_line(6, "{:5.2f}".format(temperature_celsius))
def print_humidity(self, humidity):
self.print_line(8, "Humidity")
self.print_line(9, "Level")
self.print_line(10, "{0}%".format(humidity))
[ 250 ]
Chapter 8
In this case, we refresh many lines to change just a few values. As we will
run a loop every 10 seconds, it won't be a problem. However, in other
cases in which we want to update values in a shorter amount of time, we
can write optimized code that just clears a single line and updates the
specific value in this line.
Now, we will write a loop that will display the ambient temperature expressed in
Fahrenheit (F) and Celsius (C) and the humidity value in the OLED screen, every
10 seconds. The code file for the sample is iot_python_chapter_08_02.py.
if __name__ == "__main__":
temperature_and_humidity_sensor = \
TemperatureAndHumiditySensor(0)
oled = TemperatureAndHumidityOled(0)
while True:
temperature_and_humidity_sensor.\
measure_temperature_and_humidity()
oled.print_temperature(
temperature_and_humidity_sensor.temperature_fahrenheit,
temperature_and_humidity_sensor.temperature_celsius)
oled.print_humidity(
temperature_and_humidity_sensor.humidity)
print("Ambient temperature in degrees Celsius: {0}".
format(temperature_and_humidity_sensor.temperature_
celsius))
print("Ambient temperature in degrees Fahrenheit: {0}".
format(temperature_and_humidity_sensor.temperature_
fahrenheit))
print("Ambient humidity: {0}".
format(temperature_and_humidity_sensor.humidity))
# Sleep 10 seconds (10000 milliseconds)
time.sleep(10)
The highlighted lines show the changes made in the __main__ method compared
with the previous version. The first highlighted line creates an instance of the
previously coded TemperatureAndHumidityOled class with 0 as the value of the bus
argument. The code saves the reference to this instance in the oled local variable.
This way, the instance will establish a communication with the OLED screen through
the I2C bus.
[ 251 ]
Then, the code runs a loop forever and the highlighted line calls the oled.print_
temperature method with temperature_and_humidity_sensor.temperature_
fahrenheit and temperature_and_humidity_sensor.temperature_celsius as
arguments. This way, the code displays both temperature values in the first lines of
the OLED screen.
The next hightlighted line calls the oled.print_humidity method with
temperature_and_humidity_sensor.humidity. This way, the code uses many
lines to display this humidity value at the bottom of the OLED screen.
The following line will start the example:
python iot_python_chapter_08_02.py
After you run the example, turn on an air conditioner or a heating system to generate
a change in the ambient temperature and humidity. The OLED screen will display
the temperature and humidity and refresh it every 10 seconds.
[ 252 ]
Chapter 8
Obviously, not all servor motors have the same features and we must take into
account many of them when we select a specific servo motor for our project. It
depends on what we need to position, the accuracy, the required torque, the optimal
servo rotational velocity, among other factors. In this case, we will focus on the usage
of PWM to position a standard servo motor. However, you cannot use the same
servo to rotate a lighter plastic piece than the one you will need to rotate a heavy
robotic arm. It is necessary to research about the appropriate servo for each task.
Now, we will wire a standard high sensitive mini servo motor to our existing project
and we will rotate the shaft to display the measured temperature expressed in
degrees Fahrenheit with the shaft. The shaft will allow us to display the measured
temperature in a half circle protractor that measures angles in degrees and will
display the number for the angle from 0 to 180 degrees. The combination of the
servo with the shaft and the protactor will allow us to display the temperature
with moving parts. Then, we can create our own protactor with a scale that can
add colors, specific thresholds and many other visual artifacts to make temperature
measurement funnier. Specifically, we can create a gauge chart, speedometer or
semicircle donut, that is, a combination of a doughnut chart and a pie chart in a
single chart with the different temperature values. The following picture shows and
example of a half circle protractor that we can use in combination with the servo
with the shaft.
We need the following additional part to work with this example: A SeeedStudio
Grove Servo or a EMAX 9g ES08A High Sensitive Mini Servo. The following URLs
provide detailed information about these servos: http://www.seeedstudio.com/
depot/Grove-Servo-p-1241.html and http://www.seeedstudio.com/depot/
EMAX-9g-ES08A-High-Sensitive-Mini-Servo-p-760.html.
[ 253 ]
The following diagram shows the digital temperature and humidity breakout,
the LCD RGB backlight breakout, the mini servo, the necessary wirings and the
wirings from the Intel Galileo Gen 2 board to the breadboard. The Fritzing file for
the sample is iot_fritzing_chapter_08_03.fzz and the following picture is the
breadboard view:
[ 254 ]
Chapter 8
The following picture shows the schematic with the electronic components
represented as symbols:
The power pin labeled 5V in the board's symbol is connected to the servo's
pin labeled +. Servos usually use a red wire for this connection.
The PWM capable GPIO pin labeled D3 PWM in the board's symbol is
connected to the servo's pin labeled PULSE. Servos usually use a yellow
wire for this connection.
The ground pin labeled GND in the board's symbol is connected to the
servo's pin labeled -. Servos usually use a black wire for this connection.
[ 255 ]
Now, it is time make all the necessary wirings. Don't forget to shut down the Yocto
Linux, wait for all the onboard LEDs to turn off, and unplug the power supply
from the Intel Galileo Gen 2 board before adding or removing any wire from the
board's pins.
pyupm_th02 as upmTh02
pyupm_i2clcd as upmLcd
pyupm_servo as upmServo
time
class TemperatureServo:
def __init__(self, pin):
self.servo = upmServo.ES08A(pin)
self.servo.setAngle(0)
[ 256 ]
Chapter 8
def print_temperature(self, temperature_fahrenheit):
angle = temperature_fahrenheit
if angle < 0:
angle = 0
elif angle > 180:
angle = 180
self.servo.setAngle(angle)
We have to specify the pin number to which the servo is connected when we create
an instance of the TemperatureServo class in the pin required argument. The
constructor, that is, the __init__ method, creates a new upmServo.ES08A instance
with the received pin as its pin argument, saves its reference in the servo attribute
and calls its setAngle with 0 as the value for the angle required argument. This
way, the underlying code will configure the output duty cycle for the PWM enabled
GPIO pin based on the received value in the angle argument to position the shaft at
the desired angle. In this case, we want the shaft to be positioned at 0 degrees.
The class defines a print_temperature method that receives a temperature value
expressed in degrees Fahrenheit (F) in the temperature_fahrenheit argument.
The code defines an angle local variable that makes sure that the desired angle
for the shaft is in a valid range: from 0 to 180 (inclusive). If the value received in
the temperature_fahrenheit argument is lower than 0, the angle value will be
0. If the value received in the temperature_fahrenheit argument is greater than
180, the angle value will be 180. Then, the code calls the setAngle method for
the upmServo.ES08A instance (self.servo) with angle as an argument. Under
the hoods, the upmServo.ES08A instance will configure the output duty cycle for
the PWM enabled GPIO pin based on the received value in the angle argument to
position the shaft at the desired angle. This way, the shaft will position at an angle
that will be the same than the received temperature in degrees Fahrenheit (F), as
long as the temperature value is between 0 and 180 degrees Fahrenheit (F).
In case it is too cold, (less than 0 degrees Fahrenheit) the shaft will stay at a 0 degrees
angle. In case the temperature is higher than 180 degrees Fahrenheit, the shaft will
stay at a 180 degrees angle.
Now, we will make changes to our main loop to display the ambient temperature
expressed in Fahrenheit (F) with the shaft, every 10 seconds. The code file for the
sample is iot_python_chapter_08_03.py.
if __name__ == "__main__":
temperature_and_humidity_sensor = \
TemperatureAndHumiditySensor(0)
oled = TemperatureAndHumidityOled(0)
temperature_servo = TemperatureServo(3)
while True:
[ 257 ]
The highlighted lines show the changes made to the __main__ method compared
with the previous version. The first highlighted line creates an instance of the
previously coded TemperatureServo class with 3 as the value of the pin argument.
The code saves the reference to this instance in the temperature_servo local
variable. This way, the instance will configure PWM for pin number 3 and position
the shaft at 0 degrees.
Then, the code runs a loop forever and the highlighted line calls the temperature_
servo.print_temperature method with temperature_and_humidity_sensor.
temperature_fahrenheit as an argument. This way, the code makes the shaft
point to the temperature value in the protractor.
The following line will start the example.
python iot_python_chapter_08_03.py
After you run the example, turn on an air conditioner or a heating system and
generate a change in the ambient temperature. You will notice how the shaft starts
moving to reflect the changes in the temperature every 10 seconds.
[ 258 ]
Chapter 8
[ 259 ]
Summary
In this chapter, we learned about different displays the we could connect to our
board through the I2C bus. We worked with an LCD display, an RGB backlight,
and then replaced it with an OLED dot matrix.
We wrote the code that took advantage of the modules and classes included in the
upm library that made it easier for us to work with LCD and OLED display and show
text on them. In addition, we wrote the code that interacted with an analog servo.
Instead of writing our own code to set the output duty cycle based on the desired
position for the shaft, we took advantage of a specific module and a class in the upm
library. We could control the shaft to allow us to create a gauge chart to display
the temperature value retrieved with a sensor. Our Python code could make
things move.
Now that we are able to show data next to the board and work with servos, we will
connect our IoT device to the entire world and work with cloud services, which is
the topic of the next chapter.
[ 260 ]
www.PacktPub.com
Stay Connected: