–by Floris Wouterlood — The Netherlands —
Summary —
Sometimes it is handy to have a device at hand that measures and logs several environmental parameters. You might want to know, for instance, what the humidity is a in a given spot in your home and how it fluctuates during some period: a day, a week. You might want to know how hot / cold it can get in some spot or how humid it has been. You want to receive this information on your smart phone. While this sensor information can be obtained in many ways, we describe here the design and construction of our solution: a Sniffer box: a small, easy to move, portable device equipped with sensors that sends the acquired data via wifi to an account at Thingspeak. The server at Thingspeak accumulates the data and displays them attractively via the browser on your smart phone or tablet. The entire device is based on Arduino-compatible components, and programming is done via the Arduino IDE on your computer.
Introduction
In a previous project I constructed a weather station with several Arduino components. Its engine is a NodeMCU ESP8266 microcontroller board. Several sensors collect useful data and send them to a Thingspeak server that can be accessed through a browser on my smart phone. I consider the weather station as a real success. It has been in 24/7 continuous operation for more than one year. This weather station consists of a board mounted in a box that is in a permanent, fixed position. However, every now and then I feel the need to measure environmental parameters for some time in some other part of my home away from my weather station. There are several solutions to do this, for instance I built a device consisting of a classical Arduino microcontroller board carrying a logging recorder shield that writes production data of my solar panels to file on a SD card. This device is also positioned in a fixed place notably the cupboard wherein the solar inverters are mounted. The current challenge was to build an instant portable device, as compact as possible, that collects data and sends them to the Internet: an IOT solution. I called the project the Sniffer box. Specification was that it should measure at least temperature and relative humidity and it should be possible to connect a display to the device.
Design of the Sniffer box
The Sniffer box is built around a Wemos D1 mini, which is an ESP8266 chip mounted on a board with an incredibly small footprint : 35x28mm (figure 1). The D1 mini is functionally fully compatible with the NodeMCU ESP8266 and so is its pin layout, however because of the small footprints the number of pins is limited. Most handy is that the D1 mini is programmable with the Arduino IDE because it is 100% compatible with the NodeMCU 1.0 (ESP-123E model) in the IDE’s list of supported boards.
In an electric hardware shop I bought a 80 x 120 mm electric junction box with breakaway ports which I considered a suitable container to provide place for the board and the sensors. The sensors, one DS18B20 temperature sensor and two DHT11 relative humidity sensors, can be positioned in front of a breakaway port and kept in a compartment separate from that with the microcontroller board, to avoid the danger of heat transfer from the latter to the former, however modest, that might influence measurements. This ‘inside-yet-close-to-breakaway-port’ placement avoids sticking out of vulnerable sensors and thus provides a robust protection in a handy portable format with unhindered access of the sensors to the outside air.
figure 1. Wiring diagram (final design) of the D1 Mini ESP8266 and the components inside the Sniffer box
The wiring diagram in its final version is shown in figure 1. While in operating mode a display is not necessary when prolonged logging is done, a display is very handy during software programming and next to that, also useful to have visual control over the operation of the device. In line with the ‘small footprint’ concept I opted for a small, ‘pluggable’ monochrome 128×32 OLED display that works with the i2c protocol. Displays of this kind are very energy-efficient and thus prolong operational time in cases where a battery or power bank powers the Sniffer box. The design includes plugging the D1 board’s pins into female pin headers that are soldered onto the base soldering board. This makes it easy to replace this microprocessor or to remove it, for instance if I need it for other device or to use it in some test setup.
Electronics and supplies
1x Wemos-type D1 mini ESP87266 microcontroller board, 2x DHT11 relative humidity sensor, 1x Dallas DS18B20 temperature sensor, 1x 128×32 i2c monochrome OLED display, 2x 30×70 mm soldering boards, 1x led, 2x 8-pin female pin header, 1x 4-pin female pin header, 1x 220 Ω resistor, 1x 4.7 kΩ resistor, 2x 10 kΩ resistor, wire,1x M3 nylon spacer length 6mm, 1x PVC container 80 x 120 mm (electric junction box with breakaway ports and a snap-on lid), 1x 5V USB power supply (or USB power bank), 1x USB cord to connect the power supply to the D1 mini.
figure 2. Container and the positioning of the soldering boards and main electronic components. The final soldering board platform consists of board A that supports the microcontroller board via pin headers, and that is firmly attached to board B which will accommodate the sensors (1-2-3) and the display.
Construction
The Sniffer Box housing consists of a PVC electric junction box (figure 2) available at an electric hardware store. Inside are two soldering boards: one to support the D1 microcontroller board and the other to accommodate the sensors. These boards are placed in a L-configuration, with slight overlap. Main consideration is that the sensors must face (open) breakout ports for unhindered functionality. The best place to position the sensors is at the long end of the container box and in front of a breakaway port. Because heat might build up inside the box, however modest, threatening to influence the sensors, it was made sure to place the microcontroller board as far away from the sensors as possible. The two boards are firmly attached to each other by overlapping three rows of holes and ‘stitching’ the boards together in this configuration with wire and soldering (best visible in figure 5). Once the soldering board platform configuration was established, two rows of pin headers were soldered onto this platform to accommodate the D1 mini board (figure 3).
figure 3. Container and soldering board platform with the pin headers on board A that will support the microcontroller board. Boards A and B have not yet been stitched together. The pin header on board B that supports the display was added later.
Next the sensors were positioned and soldered onto the platform. Sensors are two DHT11 relative humidity-temperature sensors and one DS18B20 temperature sensor. The DHT11s were selected simply because they are cheap and because I have a supply of these sensors. As they are relatively inaccurate in their detection of relative humidity I always mount two of these sensors and average their readouts in software. While a DHT11 has a temperature sensor on board I prefer the DS18B20 for temperature measurements because in my experience temperature measured with the DS18B20 is much more accurate in the decimals than temperature measurement with a DHT11. Both types of sensor are compact and they are easy to program in the Arduino C+ language environment. Figure 4 shows the sensors mounted in their definitive position.
figure 4. Completed soldering platform, with the pin headers for the microcontroller board and with the sensors. The platform is secured to the container’s bottom with a nylon spacer of which the bolt is visible. To accommodate the spacer the drilling of a hole in the soldering platform was necessary. Pieces of foam plastic glued to the bottom of the container support the platform.
figure 5. The soldering platform with all its mounted components on the bench during construction, programming and testing. A control led with its accompanying 220 Ω resistor was added later in the design to have a led signalling a major event (e.g. wifi transmission). The four pins of the OLED display stick into a pin header soldered onto board B of the platform. The display pin header makes it possible to temporarily remove the display when the Sniffer box is going to be used for a long period unattended.
Further construction
Once the positions of the main components of the Sniffer box had been determined and the components soldered onto the soldering platform, the design was slightly changed, that is, I decided to mount for convenience a led and to solder an extra pin header onto the platform to hold the display. Note that a display is only necessary when the Sniffer box is being programmed. In field operation all communication is via wifi. Thus a removable display is a handy feature. All physical wires connecting pins and parts were soldered on the back of the platform (figure 6). Seen from above the assembly looks neat (figure 5). Seen from below some resemblance with spaghetti may come to mind (figure 6).
figure 6. Upside down view of the platform showing all physical wiring on the back of the platform. Sensors on the left. The colors of the wire insulation correspond with that of the wiring diagram of figure 1. The brown wire leads from pin D5 to the control led.
After the last piece of wire had been inserted and soldered the soldering platform and its contents were mounted in the box. A ‘heat’ barrier was cut of foam plastic was attached to the platform with double-sided adhesive tape (figure 7). Testing could continue.
figure 7. Finished Sniffer box. The soldering platform with all components on board is now placed in the box. After attaching the platform to the box with a nylon bolt and fastening of the foam ‘heat barrier’ with double-sided adhesive tape the box is ready for testing and operation in the field. T = temperatures sensor (DS18B20); H1, H2 = humidity sensors.
Sketch
The purpose of the Sniffer box is to collect temperature and relative humidity data and to transfer these to a server on the Internet. The Internet site then presents the data in an attractive way and stores them for future download. The server is at Thingspeak, a free MATLAB service available at https://thingspeak.com. I opened a free account at Thingspeak and created a channel named ‘Sniffer’ with four fields, displaying respectively temperature measured by the DS18B20 sensor, humidity measured by DHT nr 1, humidity measured by DHT nr 2 and relative humidity averaged from HT1 and DHT2. Widgets can be added; for the purpose of this paper I added to my channel a gauge widget displaying temperature (figure 8, B).
The sketch Snifferbox-IOT.ino starts with a series of comment lines explaining the purpose of the sketch, pins used for specific sensors, etcetera. Next follow the #includes, declarations, variables and connection/login variables:
// Snifferbox-IOT.ino
// July 11, 2019
// public domain
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#define onewirepin 00
#define OLED_RESET LED_BUILTIN
#define myPeriodic 60 // in sec | Thingspeak standard pub is 15sec
Adafruit_SSD1306 display(OLED_RESET);
OneWire oneWire(onewirepin);
DallasTemperature sensors(&oneWire);
DeviceAddress Probe = {0x28, 0xFF, 0xA1, 0xBD, 0x50, 0x18, 0x02, 0xE7}; // unique address of the DS18B20
float probe_temp = 0;
float dht1_h = 0;
float dht1_t = 0;
float dht2_h = 0;
float dht2_t = 0;
float average_dht_h = 0;
DHT sens1 (12, DHT11); // datapin sensor to pin D6 of MiniD1 (equivalent of arduino pin 12)
DHT sens2 (2, DHT11); // datapin sensor to pin D4 of MiniD1 (equivalent of arduino pin 2)
const char* server = “api.thingspeak.com”;
String apiKey =”xxxxxxxxxxxxxxxx”; // this must contain your API obtained from Thingspeak
const char* MY_SSID = “xxxxxxxxxx””; // fill in the name of the wifi network to connect with
const char* MY_PWD = “xxxxxxxxxx””; // fill in the password of the wifi network to connect with
int sent = 0;
Of course all the libraries mentioned in #include should be installed in your Arduino IDE. Next comes the setup () part of the sketch:
{
Serial.begin(9600);
pinMode (14, OUTPUT); // D5 pin on NodeMCu corresponds with D14 Arduino
Serial.begin (9600);
Serial.println (“”);
Serial.println (“”);
Serial.println (“+—————————————————-+”);
Serial.println (” + Sniffer box + “);
Serial.print (“Initializing Temperature Control Library Version “);
Serial.println (DALLASTEMPLIBVERSION);
Serial.println (“+—————————————————-+”);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // OLED display stuff
display.clearDisplay();
display.setTextSize (1);
display.setTextColor (WHITE);
display.setCursor (0,0);
display.println (“Temperature-humidity”);
display.println (“”);
display.println (“”);
display.println (“FGW – July 2019”);
display.display ();
sensors.begin (); // Initialize the DS18B20 temp sensor and set resolution level
sensors.setResolution(Probe, 10);
delay (1000);
Serial.println ();
Serial.print (“Number of DS18B20 devices found on bus = “);
Serial.println (sensors.getDeviceCount());
Serial.println (“Getting temperature … “);
Serial.println (“”);
delay(200);
connectWifi(); // here we go!
}
So far for the Setup. Note that connectWifi() is a subroutine to create an ESP8266 wifi network station. I always place subroutines after the loop() section to have an orderly set of instructions.
Loop() contains the following:
sensors.requestTemperatures(); // Command all onewire devices on bus to read temperature
delay (100);
probe_temp = sensors.getTempC (Probe);
Serial.print (“DS18B20 temp: “);
Serial.print (probe_temp,1);
Serial.println (” *C”);
Serial.println (“”);
dht1_h = sens1.readHumidity(); // DHT11 number one
dht1_t = sens1.readTemperature();
Serial.print (“DHT11-nr-1 temp: “); // serial monitor stuff
Serial.print (dht1_t,1);
Serial.println (” *C”);
Serial.print (“DHT11-nr-1 humidity: “);
Serial.print (dht1_h,0);
Serial.println (” %”);
Serial.println (“”);
dht2_h = sens2.readHumidity(); // DHT11 number two
dht2_t = sens2.readTemperature();
Serial.print (“DHT11-nr-2 temp: “); // serial monitor stuff
Serial.print (dht2_t,1);
Serial.println (” *C”);
Serial.print (“DHT11-nr-2 humidity: “);
Serial.print (dht2_h,0);
Serial.println (” %”);
Serial.println (“”);
average_dht_h = ((dht1_h + dht2_h)/2);
Serial.println (“humidity sensors averaged”);
Serial.print (“average DHT1-DHT2: “); // serial monitor stuff
Serial.print (average_dht_h,0);
Serial.println (” %”);
Serial.println (“”);
display.clearDisplay (); // OLED display stuff
display.setTextSize (1);
display.setTextColor (WHITE);
display.setCursor (0,0);
display.println (“”);
display.print (“Temperature: “);
display.print (probe_temp,1);
display.print (” “);
display.print ((char)247); // degree symbol
display.println (“C”);
display.println (“”);
display.print (“RH:1= “);
display.print (dht1_h,0);
display.print (” % – 2= “);
display.print (dht2_h,0);
display.println (” %”);
display.display ();
digitalWrite (14,HIGH);
delay(100);
digitalWrite (14,LOW);
Serial.println (“data transmission to Thingspeak channel…”);
delay(1900);
send_the_stuff();
int count = myPeriodic;
while(count–)
delay(1000);
}
In the instructions in loop() the following actions are programmed:
1. Get the temperature from the DS18B20 and store the value in the variable probe_temp;
2. Send the value in probe_temp to Serial Monitor;
3. Get temperature, humidity from sensor DHT-1 and store these values in variables dht1_t and dht_2, respectively;
4. Send the values in variables dht1_t and dht_2 to Serial Monitor;
5. Do the same for sensor DHT2;
6. Average the values for humidity of DHT 1 and 2 and store in variable average_dht_h;
7. Display values in a neat way on the OLED display;
8. Initiate data transmission;
9. Close the loop.
The subroutine connectWifi() was downloaded from a source on the Internet. It creates a station in the wifi network.
void connectWifi()
{
Serial.print(“Connecting to “+*MY_SSID);
WiFi.begin(MY_SSID, MY_PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“Connected”);
Serial.println(“”);
digitalWrite (14,HIGH);
delay(25);
digitalWrite (14,LOW);
delay(20);
digitalWrite (14,HIGH);
delay(255);
digitalWrite (14,LOW);
delay(20);
digitalWrite (14,HIGH);
delay(25);
digitalWrite (14,LOW);
}
The repetition of the led on pin 14 being set HIGH and LOW (led blinks three times) can also be achieved with a for-next loop.
Note that connectWifi() is called at the end of the setup() section. If the subroutine fails to establish a connection the execution of the sketch halts at the end of setup(). The only thing that happens in that case is continuous display of the initialization message on the OLED display.
Finally the collected data are transmitted to the server at Thingspeak. I found the procedure funny at first hand but very useful later because it is extremely easy to add fields (up to a total of eight). The concept is simple: concatenate all values and send that as one long string to the Thingspeak server who will chop the string up in their respective pieces and then run the fancy display routines. The transmission is executed in the subroutine send_the_stuff():
void send_the_stuff()
{
WiFiClient client;
if (client.connect(server, 80)) { // use ip 184.106.153.149 or api.thingspeak.com
Serial.println(“WiFi Client connected “);
Serial.println(“”);
String postStr = apiKey;
postStr += “&field1=”;
postStr += String(probe_temp);
postStr += “&field2=”;
postStr += String(dht1_h);
postStr += “&field3=”;
postStr += String(dht2_h);
postStr += “&field4=”;
postStr += String(average_dht_h);
client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: ” + apiKey + “\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(postStr.length());
client.print(“\n\n”);
client.print(postStr);
delay(1000);
digitalWrite (14,HIGH);
delay(50);
digitalWrite (14,LOW);
delay(50);
digitalWrite (14,HIGH);
delay(50);
digitalWrite (14,LOW);
}
Results
With the above sketch and with the proper channel settings in the Thingspeak account I got nice temperature and humidity logging with the Sniffer box. Figure 8 shows how data can be displayed in my Sniffer box channel.
figure 8. Presentation of data at https://thingspeak.com. Thingspeak offers a range of presentation widgets to the user. A, Temperature change plotted against time. B, ‘Gauge’ widget presenting the most recent value of the series of temperature readings.
Under operation conditions the Sniffer box in combination with a USB power bank appears to be a nice and handy portable station for sensoring environmental data measurements. When no power bank or other form of portable power supply is available the working range depends on the availability of an AC home power outlet and an extension cord to work with an USB power supply. Another limitation is that measurements can only be done within range of the wifi router. If one wants to collect temperature and humidity data outside the range of the wifi router a SD-card based logger/USB power bank comes into mind.
Download
The sketch, Snifferbox-IOT.ino, can be downloaded here (zip file).