Chapter Goal: Build Your First IoT Device
Building an inexpensive IoT sensor device based on the ESP8266 and Arduino IDE
Setting up a simple self-organizing IoT sensor net
Reading I2C sensor (light and color) on the Arduino devices
Reading data from remote IoT sensors on the Raspberry Pi
Using the Raspberry Pi for monitoring and debugging
Displaying your data on the screen and on an iPad
Distributed control
Self-organization
Passing information to the Internet
Swarm behavior
The LightSwarm architecture is a simple and flexible scheme for understanding the idea of an IoT project using many simple small computers and sensors with shared responsibility for control and reporting. Note that, in this swarm, communication with the Internet is handled by a Raspberry Pi. The swarm devices talk to each other, but not with the Internet. The Raspberry Pi is located on the same WiFi access point as the swarm, but could be located far away with some clever forwarding of packets through your WiFi router. In this case, since we have no computer security at all in this design (see Chapter 7 for information on making your IoT swarm and device more secure), we are sticking with the local network.
IoT Sensor Nets
One of the major uses of the IoT will be building nets and groups of sensors. Inexpensive sensing is just as big of a driver for the IoT as the development of inexpensive computers. The ability for a computer to sense its environment is the key to gathering information for analysis, action, or transmittal to the Internet. Sensor nets have been around in academia for many years, but now the dropping prices and availability of development tools are quickly moving sensor nets out to the mainstream. Whole industrial and academic conferences are now held on sensor nets [www.sensornets.org]. The market is exploding for these devices, and opportunities are huge for the creative person or group that can figure out how to make the sensor net that will truly drive consumer sales.
IoT Characterization of This Project
LightSwarm Characterization (CPLPFC)
Aspect | Rating | Comments |
---|---|---|
Communications | 9 | WiFi connection to the Internet – can do ad hoc mesh-type communication |
Processor power | 7 | 80MHz XTensa Harvard Architecture CPU, ~80KB data RAM/~35KB of instruction RAM/200K ROM |
Local storage | 6 | 4MB Flash (or 3MB file system!) |
Power consumption | 7 | ~200mA transmitting, ~60mA receiving, no WiFi ~15mA, standby ~1mA |
Functionality | 7 | Partial Arduino support (limited GPIO/analog inputs) |
Cost | 9 | < $10 and getting cheaper |
Ratings are from 1 to 10, 1 being the least suitable for IoT and 10 being the most suitable for IoT applications.
This gives us a CPLPFC rating of 7.2. This is calculated by averaging all six values together with equal weighting. This way is great for learning and experimenting and could be deployed for some applications.
The ESP8266 is an impressive device having a built-in WiFi connection, a powerful CPU, and quite a bit of RAM and access to the Arduino libraries. It is inexpensive and will get cheaper as time goes on. It is a powerful device for prototyping IoT applications requiring medium levels of functionality.
How Does This Device Hook Up to the IoT?
The ESP8266 provides a WiFi transmitter/receiver, a TCP/IP stack, and firmware to support direction connections to a local WiFi access point that then can connect to the Internet. In this project, the ESP8266 will only be talking to devices on the local wireless network. This is an amazing amount of functionality for less than $10 retail. These chips can be found for as little as $1 on the open market, if you want to roll your own printed circuit board.
What Is an ESP8266?
The ESP8266 is made by a company in China called Espressif [espressif.com]. They are a fabless semiconductor company that just came out of nowhere with the first generation of this chip and shook up the whole industry. Now all the major players are working on inexpensive versions of an IoT chip with WiFi connectivity. Why did we not use the more powerful ESP32? Two reasons, the ESP32 has way more CPU power than we need, and it is twice as expensive.
The ESP8266 chip was originally designed for connected light bulbs but soon got used in a variety of applications, and ESP8266 modules are currently now the most popular solutions to add WiFi to IoT projects. While the ESP8266 has huge functionality and a good price, the amount of current consumed by the chip makes battery-powered solutions problematic.
The LightSwarm Design
Each of the LightSwarm devices in the swarm is identical. There are no software differences and no hardware differences. As you will see when we discuss the software, they vote with each other and compare notes and then elect the device that has the brightest light as the “Master,” and then the “Master” turns the red LED on the device to show us who has been elected “Master.” The swarm is designed so devices can drop out of the swarm, be added to the swarm dynamically, and the swarm adjusts to the new configuration. The swarm behavior (who is the master, how long it takes information about changing lights to propagate through the swarm, etc.) is rather complex. More complex than expected from the simple swarm device code. There is a lesson here: simple machines in groups can lead to large complex systems with higher-level behaviors based on the simple machines and the way they interact.
The Raspberry Pi in this diagram is not controlling the swarm. The Raspberry Pi gathers data from the swarm (the current “Master” device sends information to the Raspberry Pi), and then the Raspberry Pi can store the data and communicate it through the Internet, in this case to a local web page.
The LightSwarm project has an amazing amount of functionality and quirky self-organizing behavior for such a simple design.
Building Your First IoT Swarm
Swarm Parts List
Part Number | Count | Description | Approximate Cost per Board | Source |
---|---|---|---|---|
ESP8266 Huzzah board | 5 | CPU/WiFi board | $18 | |
TCS34725 breakout board | 5 | I2C light sensor | $10 | |
FTDI cable | 1 | Cable for programming the ESP8266 from PC/Mac | $20 |
Installing Arduino Support on the PC or Mac
The key to making this project work is the software. While there are many ways of programming the ESP8266 (MicroPython [micropython.org], NodeMCU Lua interpreter [nodemcu.com/index_en.html], and the Arduino IDE (Integrated Development Environment) [www.arduino.cc/en/Main/Software]), I chose the Arduino IDE for its flexibility and the large number of sensor and device libraries available.
- a.
Download the Arduino IDE package for your computer and install the software [www.arduino.cc/en/Guide/HomePage].
- b.
Download the ESP libraries so you can use the Arduino IDE with the ESP breakout board. Adafruit has an excellent tutorial for installing the ESP8266 support for the Arduino IDE [learn.adafruit.com/adafruit-huzzah-esp8266-breakout/using-arduino-ide].
Your First Sketch for the ESP8266
A great way of testing your setup is to run a small sketch that will blink the red LED on the ESP8266 breakout board. The red LED is hooked up to GPIO 0 (General-Purpose Input/Output pin 0) on the Adafruit board.
If your LED is happily blinking away now, you have correctly followed all the tutorials and have the ESP8266 and the Arduino IDE running on your computer.
Next, I will describe the major hardware systems and then dive into the software.
The Hardware
ESP8266 – CPU/WiFi interface Huzzah
TCS34725 – Light sensor
9V battery power
FTDI cable – Programming and power
The ESP8266 communicates with other swarm devices by using the WiFi interface. The ESP8266 uses the I2C interface to communicate with the light sensor. The WiFi is a standard that is very common (although we use protocols to communicate that are not common). See the description of UDP (User Datagram Protocol) later in this chapter. The I2C bus interface is much less familiar and needs some explanation.
Reviewing the I2C Bus
An I2C bus is often used to communicate with chips or sensors that are on the same board or located physically close to the CPU. It stands for standard Inter-IC device bus . The I2C was first developed by Philips (now NXP Semiconductors). To get around licensing issues, often the bus will be called TWI (Two-Wire Interface). SMBus, developed by Intel, is a subset of I2C that defines the protocols more strictly. Modern I2C systems take policies and rules from SMBus sometimes supporting both with minimal reconfiguration needed. The Raspberry Pi and the Arduino are both these kinds of devices. Even the ESP8266 used in this project can support both.
An I2C provides good support for slow, close peripheral devices that only need be addressed occasionally. For example, a temperature measuring device will generally only change very slowly and so is a good candidate for the use of I2C, where a camera will generate lots of data quickly and potentially changes often.
Vcc and Vdd mean the same. Gnd and Vss generally also both mean ground. There are historical differences, but today Vcc usually is one power supply, and if there is a second, they will call it Vdd.
When used on the Raspberry Pi, the Raspberry Pi acts as the Master and all other devices are connected as Slaves.
If you connect an Arduino to a Raspberry Pi, you need to be careful about voltage levels because the Raspberry Pi is a 3.3V device and the Arduino is a 5.0V device. The ESP8266 is a 3.3V device so you also need to be careful connecting an Arduino to an ESP8266. Before you do this, read this excellent tutorial [blog.retep.org/2014/02/15/connecting-an-arduino-to-a-raspberry-pi-using-i2c/].
Single message where a master writes data to a slave
Single message where a master reads data from a slave
Combined messages, where a master issues at least two reads and/or writes to one or more slaves
Lucky for us, most of the complexity of dealing with the I2C bus is hidden by drivers and libraries.
Pullups on the I2C Bus
One important thing to consider on your I2C bus is a pullup resistor. The Raspberry Pi has 1.8K (1k8) ohm resistors already attached to the SDA and SCL lines, so you really shouldn't need any additional pullup resistors. However, you do need to look at your I2C boards to find out if they have pullup resistors. If you have too many devices on the I2C bus with their own pullups, your bus will stop working. The rule of thumb from Philips is not to let the total pullup resistors in parallel be less than 1K (1k0) ohms. You can get a pretty good idea of what the total pullup resistance is by turning the power off on all devices and using an ohm meter to measure the resistance on the SCL line from the SCL line to Vdd.
Sensor Being Used
This is an excellent inexpensive sensor ($8 retail from Adafruit on a breakout board) and forms the basis of our IoT sensor array. Of course, you could add many more sensors, but having one sensor that is easy to manipulate is perfect for our first IoT project. In Chapter 3, we add many more sensors to the Raspberry Pi computer for a complete IoT Weather Station design.
3D Printed Case
Mounting Base for the IoT LightSwarm
You can download the STL file for the LightSwarm base from github/switchdoclabs.
The Full Wiring List
LightSwarm Wiring List
From | To | Description |
---|---|---|
ESP8266/GND | TCS34725/GND | Ground for I2C light sensor |
ESP8266/3V | TCS34725/3V3 | 3.3V power for I2C light sensor |
ESP8266/#4 | TCS34725/SDA | SDA for I2C light sensor |
ESP8266/#5 | TCS34725/SCL | SCL for I2C light sensor |
ESP8266/GND | 9VBat/“-” terminal (minus terminal) | Ground for battery |
ESP8266/VBat | 9VBat/“+” terminal (plus 9V) | 9V from battery |
The Software
There are two major modules written for the LightSwarm. The first is ESP8266 code for the LightSwarm device itself (written in the Arduino IDE – in simplified C and C++ language), and the second is the Raspberry Pi data-gathering software (written in Python3 on the Raspberry Pi). There is an excellent tutorial on how to set up the Arduino IDE and the ESP8266 libraries at https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout.
Device self-discovery.
Device becomes master when it has the brightest light; all others become slaves.
Distributed voting method for determining master status.
Self-organizing swarm. No server.
Swarm must survive and recover from devices coming in and out of the network.
Master device sends data to Raspberry Pi for analysis and distribution to the Internet.
LightSwarm Code
LIGHT_UPDATE_PACKET – Packet containing current light from a LightSwarm device. Used to determine who is master and who is slave.
RESET_SWARM_PACKET – All LightSwarm devices are told to reset their software.
CHANGE_TEST_PACKET – Designed to change the master/slave criteria (not implemented).
RESET_ME_PACKET – Just reset a particular LightSwarm device ID.
DEFINE_SERVER_LOGGER_PACKET – This is the new IP address of the Raspberry Pi so the LightSwarm device can send data packets.
LOG_TO_SERVER_PACKET – Packets sent from LightSwarm devices to Raspberry Pi.
MASTER_CHANGE_PACKET – Packet sent from LightSwarm device when it becomes a master (not implemented).
BLINK_BRIGHT_LED – Command to a LightSwarm device to blink the bright LED on the TCS34725.
LightSwarm Constants
The setup() Function for LightSwarm
Here, we use the floating value of the analog input on the ESP8266 to set the pseudo-random number generation seed. This will vary a bit from device to device, and so it’s not a bad way of initializing the pseudo-random number generator. If you put a fixed number as the argument, it will always generate the same set of pseudo-random numbers. This can be very useful in testing. Listing 2-5 shows the setup of the random seed and the detection of the TCS34725.
Remainder of the setup() Function for LightSwarm
Now we have initialized all the data structures for describing our LightSwarm device and the states of the light sensor. Listing 2-6 sets the SwarmID based on the current device IP address. When you turn on a LightSwarm device and it connects to a WiFi access point, the access point assigns a unique IP address to the LightSwarm device. This is done through a process called DHCP (Dynamic Host Configuration Protocol) [en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol]. While the number will be different for each LightSwarm device, it is not random. Typically, if you power a specific device down and power it up again, the access point will assign the same IP address. However, you can’t count on this. The access point knows your specific device because each and every WiFi interface has a specific and unique MAC (Media Access Control) number, which is usually never changed.
Faking MAC addresses allows you to impersonate other devices with your device in some cases, and you can use MAC addresses to track specific machines by looking at the network. This is why Apple Inc. has started using random MAC addresses in their devices while scanning for networks. If random MAC addresses aren’t used, then researchers have confirmed that it is possible to link a specific real identity to a particular wireless MAC address [Cunche, Mathieu. “I know your MAC Address: Targeted tracking of individual using Wi-Fi”. 2013].
Setting the SwarmID from IP Address
In Listing 2-7, we read all the data from the TCS34725 sensor to find out how bright the ambient light currently is. This forms the substance of the data to determine who the master in the swarm is.
Reading the Light Color
Interpreting the Packet Type
LightSwarm Packet Interpretation Code
Broadcasting to the Swarm
Master Check and Update
That is the entire LightSwarm device code. When compiling this code on the Arduino IDE targeting the Adafruit ESP8266, we get the following:
Sketch uses 308,736 bytes (29%) of program storage space. Maximum is 1,044,464 bytes.
Global variables use 50,572 bytes (61%) of dynamic memory, leaving 31,348 bytes for local variables. Maximum is 81,920 bytes.
Still a lot of space left for more code. Most of the compiled code space earlier is used by the system libraries for WiFi and running the ESP8266.
Self-Organizing Behavior
Why do we say that the LightSwarm code is self-organizing? It is because there is no central control of who is the master and who is the slave. This makes the system more reliable and able to function even in a bad environment. Self-organization is defined as a process where some sort of order arises out of the local interactions between smaller items in an initially disordered system.
Typically, these kinds of systems are robust and able to survive in a chaotic environment. Self-organizing systems occur in a variety of physical, biological, and social systems.
One reason to build these kinds of systems is that the individual devices can be small and not very smart, and yet the overall task or picture of the data being collected and processed can be amazingly interesting and informative.
Monitoring and Debugging the System with the Raspberry Pi (the Smart Guy on the Block)
Read and log information on the swarm behavior.
Reproduce archival swarm behavior.
Provide methods for testing swarm behavior (such as resetting the swarm).
Provide real-time information to the Internet on swarm behavior and status.
Remember that the Raspberry Pi is a full, complex, and powerful computer system that goes way beyond what you can do with an ESP8266. First, we will look at the LightSwarm logging software and then the software that supports the display web page. Note that we are not storing the information coming from the swarm devices in this software, but we could easily add logging software that would populate a MySQL database that would allow us to store and analyze the information coming in from the swarm.
LightSwarm Logging Software Written in Python
The entire code base of the LightSwarm logging software is available off the Apress site [Apress code site] and on the SwitchDoc Labs github site [github.com/switchdoclabs/SDL_Pi_LightSwarm]. I am picking out the most interesting code in the logging software to comment on and explain.
First of all, this program is written in Python3. Python3 is a widely used programming language, especially with Raspberry Pi coders. There are a number of device libraries available for building your own IoT devices, and there is even a small version that runs on the ESP8266. Python’s design philosophy emphasizes code readability. Indenting is important in Python, so keep that in mind as you look at the following code.
Python is “weakly typed,” meaning you define a variable and the type by the first time you use it. Some programmers like this, but I don’t. Misspelling a variable name makes a whole new variable and can cause great confusion. My prejudice is toward “strongly typed” languages as it tends to reduce the number of coding errors, at the cost of having to think about and declare variables explicitly.
Import and Constant Value Declaration
processCommand(s) – When a command is received from the software running on the same computer (writing to this file), this function defines all the actions to be completed when a specific command is received.
completeCommandWithValue(value) – Call function and return a value to a file when you have completed a command.
completeCommand() – Call function when you have completed a command to tell the external program you are done with the command.
Command Interface
Basically, the idea is that external software sends a command to the LightSwarm logging software that is running on a different thread in the same system. Remember that the Raspberry Pi Linux-based system is multitasking and you can run many different programs at once.
LightSwarm Command List
Command | Syntax | Description |
---|---|---|
Reset Swarm | RESETSWARM | Resets all connected Swarm units to initial state. They then start negotiating for Master Status Again |
Reset One | RESETSELECTED, <swarm id> | Resets a particular Swarm element. Uses Swarm ID 0-4, for example, RESETSELECTED, 1 |
Blink Bright LED | BLINKLIGHT, <swarm id> | Blinks the Bright LED on the selected Swarm unit. Uses Swarm ID 0-4, for example, BLINKLIGHT, 1 |
Get Status | STATUS | Returns the status of all the Swarm IDs in the file LSResponse.txt |
To use these commands is simple. Under the SDL_Pi_LightSwarm/state subdirectory, edit the LSCommand.txt and enter one of the preceding commands. Shortly the main loop in LightSwarm.py will pick up the command and execute the command.
LightSwarm Command Packet Definitions
Web Page Building Code
Incoming Swarm Analysis Code
LightSwarm Logger Startup Code
Raspberry Pi Logger Main Loop
Note the last line of code, processCommands. This function is where the LSCommand.txt file is read and the commands inside the file are executed.
Results
Results from LightSwarm IoT Device Run on ESP8266
Output from Raspberry Pi LightSwarm Logger
What Else Can You Do with This Architecture?
The LightSwarm architecture is flexible. You can change the sensor, add more sensors, and put in more sophisticated algorithms for swarm behavior. In Chapter 5, we extend this architecture to more complex swarm behavior, actually changing some of the physical environment of the swarm devices.
Conclusion
A good part of the IoT will be the gathering of simple, small amounts of data, some analysis on the data, and the communication of that data to servers for action and further analysis on the Internet. The projects in Chapters 3 and 4 are of more complex IoT devices gathering lots of data, processing it, acting on the data, and communicating summaries to the Internet. The LightSwarm is different in that each Swarm element is simple and cooperates without a central controller to determine which element has the brightest light and then will act on that information (turning the red LED on).
Swarms of IoT devices can be made inexpensively, can exhibit unexpected complex behavior, and can be devilishly difficult to debug. If you are trying to debug such a system, log everything during development!!!