Wireless thermo-hygrometer

Test Program

The test program in Listing 1 [9], which causes the LED on GPIO14 to flash, determines whether programs can be loaded into the ESP8266. To upload and start the program, simply switch the ESP8266 to Flash mode, close the JP1 and JP2 jumpers, and press the reset button. Now click the Upload button (i.e., the icon with the arrow pointing to the right) in the upper left corner of the IDE. The upload will start automatically. If the LED starts flashing, the upload was successful.

Listing 1

Test Program

void setup() {
  pinMode(14, OUTPUT);
void loop() {
  digitalWrite(14, HIGH);
  digitalWrite(14, LOW);

If the upload does not work right away, you should check the hardware: Did you solder everything correctly and select the correct boards manager (Generic ESP8266 Module)? Is the transmission speed 115200 (baud)? In many cases, the problem is choosing the wrong port. You always need a TTYUSB port, not a COM port. Remember to remove the two jumpers when the test is finished.

The sensor needs to send its measured values to the MQTT server. To do this, you install a library by clicking Sketch | Include Library | Manage Libraries; then, search for the PubSubClient and install it. Now you can send MQTT messages from ESP8266.

Sensor Program

Listing 2 shows the sensor program. Put simply, the sensor establishes a wireless connection, reads the AM2321, and sends the data to the MQTT server. A closer look reveals many details of the program code.

Listing 2

Sensor Program

01 #include <Wire.h>
02 #include <ESP8266WiFi.h>
03 #include <PubSubClient.h>
04 // WLAN
05 const char* ssid = "<Your SSID>";
06 const char* pass = "<Your WLAN Password>";
07 //MQTT Server
08 const char* serverIp = "<Your MQTT Server>";
09 const char* topic ="/home/sensor2";
10 const int serverPort = 1883;
11 // Energy Save
12 const int interval = 600;//sec
14 WiFi client client;
15 PubSubClient mqtt(client);
17 void setup() {
18   Wire.begin(4, 5);
19   Serial.begin(115200);
20   Serial.println("\r\n");
21   WiFi.begin(ssid, pass);
22   while (WiFi.status() != WL_CONNECTED) {
23     delay(500);
24     Serial.print(".");
25   }
26   Serial.println(""");
27   Serial.print("Connected: ");
28   Serial.println(ssid);
29   Serial.print("IP address: ");
30   Serial.println(WiFi.localIP());
31   // Measurement
32   Wire.beginTransmission(0x5c);
33   Wire.endTransmission();
34   Wire.beginTransmission(0x5c);
35   Wire.write(0x03);
36   Wire.write(0);
37   Wire.write(4);
38   Wire.endTransmission();
39   delay(3);
40   Wire.requestFrom(0x5c, 8);
41   uint8_t buf[6];
42   for (int i = 0; i < 6; ++i)
43   buf[i] = Wire.read();
44   unsigned short crc = 0;
45   crc = Wire.read(); //CRC LSB
46   crc |= Wire.read() << 8;//CRC MSB
47   unsigned int humidity;
48   signed int temperature;
49   humidity = buf[2] << 8;
50   humidity += buf[3];
51   temperature = buf[4] << 8;
52   temperature += buf[5];
53   if(temperature & 0x8000) temperature = -(temperature & 0x7fff);
54   double temp = temperature;
55   double hum = humidity;
56   temp =temp/10;
57   hum=hum/10;
58   Serial.print("Temperature:");
59   Serial.println(temp);
60   Serial.print("Humidity: ");
61   Serial.println(hum);
62   Serial.print("CRC: ");
63   Serial.println(crc);
64   //JSON
65   char msg[64] =""";
66   sprintf (msg,"{ \"temperature\": \"%-2.2f\", \"humidity\": \"%-2.2f \"\"}",temp,hum);
67   Serial.println(msg);
68   // Connect to MQTT Server
69   mqtt.setServer(serverIp,1883 );
70   while (!mqtt.connected()) {
71     Serial.print("Connecting...");
72     if (!mqtt.connect("Sensor 1")) {
73       Serial.print("failed, rc=");
74       Serial.print(mqtt.state());
75       Serial.println(" retrying in 5 seconds");
76       delay(5000);
77     }
78     Serial.println();
79   }
80   mqtt.loop();
81   mqtt.publish(topic,msg);
82   delay(500); // Wait for MQTT Server
83   Serial.println("goSleep" );
84   ESP.deepSleep(interval*1000000);
85 }
86 void loop()
87 {
88 }

After importing all necessary libraries (lines 1 to 3) the program stores all the required parameters in constants. First is the data for the wireless connection (lines 5 and 6), where you store the appropriate values for your network. Enter the connection data for the MQTT server in the constants that follow (lines 8 to 10).

If you use more than one sensor, they have to send their measured values to different topics; otherwise, they cannot be isolated later. The last parameter (line 12) indicates how long the ESP8266 should sleep after a measurement before starting a new measurement. To conserve the batteries, the microcontroller switches off completely between measurements; the power consumption is then only in the microamp range.

The next two lines (14 and 15) define a connection to the WiFi network and to the MQTT server. Both are client connections. The advantage of MQTT is that the publishers/submitters define which topic they use. The broker provides the topics dynamically, but you have to make sure that the topics match. Because I am working with three sensors in this example, I can simply number them.

After starting a microcontroller, the setup() function always runs first, usually executing just the parts of the program that are required only once. In this case, the function is the complete program because all program parts have to be executed once for a measurement.

The Wire.begin(4, 5) command (line 18) starts an I2C interface on GPIO4 (SDA) and GPIO5 (SCL). The next line initializes the serial output of the program. All messages written here appear on the serial monitor of the Arduino IDE – make sure the monitor uses the same transmission speed as the program (here, 115,200 baud) – which makes it easier to trace bugs in the software and hardware.

The WiFi.begin() command (line 21) establishes and configures a connection to the WiFi network. Because this process takes some time, the following while loop continuously checks the status of the WiFi connection. The loop is only left after the connection has been established. The lines that follow display the connection status on the serial monitor.

Now the actual measurement begins. The first two commands (lines 32 and 33) wake up the AM2321 from energy-saving mode. The next five lines tell it to measure the temperature and humidity, and the delay(3) waits a while before reading the values.

A series of commands follows beginning in line 40 that read the measured values from the I2C bus and store them, formatted in variables. Line 53 is especially interesting; it ensures that even negative numbers are displayed correctly. To transfer the measured values, they are converted to JSON format (lines 65-67), and the string is stored in the msg variable.

Starting in line 69, the software establishes the connection to the MQTT server and transmits the message. Much like connecting to the WiFi network, it tries to establish contact in a loop until communication works. The data transfer is quite unspectacular with the mqtt.publish(topic,msg) command (line 81). The following delay(500) ensures that the ESP8266 does not go into power save mode without transmitting the message completely. If your MQTT server is running very slowly, you might have to increase the wait. The last line, ESP.deepSleep(interval*1000000), in the setup() function puts the ESP8266 back into power save mode.

Now the measurement has been transferred and completed. When the ESP8266 wakes up after the time defined in the interval variable, the program restarts. The loop() function is never called because the program switches the ESP8266 to energy-saving mode at the end of the setup() function. To upload the program to the ESP8266, proceed as described for the test program.

Messages in MQTT

Before you process the messages from the sensors in Node-RED, you first need to check whether they are reaching the MQTT server as expected. To do this, use the MQTT app for Chrome described at the beginning. So that the messages from all three sensors appear in one slide, connect to the /home/+ topic. Now, press the reset buttons on the individual sensors one after the other to send a measured value to the MQTT server. The output of the MQTT app should look like Figure 5. If the sensors provide implausible humidity values, the battery voltage is probably a little too low: The AM2321 sensors require an operating voltage of at least 2.6V.

Figure 5: An example of testing the sensors with the corresponding output from the MQTT app.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Home Assistant with MQTT

    Automating your four walls does not necessarily require commercial solutions. With a little skill, you can develop your own projects on a low budget.

  • Adafruit IO API

    The Adafruit IO API offers a convenient means for network-ready sensors and other components.

  • IoT with RabbitMQ

    Connect multiple protocols and servers together on your IoT projects.

  • ESPHome

    With an ESP32 or Raspberry Pi Pico W microcontroller board, you can easily create your own home automation devices. Thanks to ESPHome, you don't even have to be a programmer.

  • Instrumented Garden

    Place long-range wireless sensors in a garden and keep track of ambient conditions with gauges and time-based graphs.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More