NodeMCU SMS Temperature Alert

This site has been great fun, but it has run its course, and it is time to move on. Please get what you want from the site before January 1, 2020. Some pages will move to another site but most will go away.

SMS Temperature Alerter

This project is an inexpensive NodeMCU-based temperature instrument that can be set to trigger SMS alerts to your phone if the temperature exceeds a threshold. It uses WiFi to send a message to an event trigger URL at IFTTT, which then sends an SMS message to your phone. The message may contain up to three temperatures. For this project I need 2 temperatures.

The monitor will work for monitoring any temperature(s) from -40C to +100C (-40F to +212F). I'm only using my computer temperatures as an example - it could be any temperatures you are interested in monitoring. You can add more sensors by adding the variables and a line of code for each sensor. There is a limit of three variables in the SMS message, so three temperatures max for this code. You could modify it to send a single string with all of the sensor data if you need more.

The NodeMCU is programmed in the Arduino IDE, and powered by a standard 5V 1A USB charger. The temperature is sensed by the Adafruit ADA1782 MCP9808 I2C Temperature Sensor Breakout Boards. The boards get 3.3V off of the 3V output from the NodeMCU, so no level translation is required. A 4-wire cable connects the temperature sensor to the NodeMCU.

I have two computers that I want to monitor, so I'm using two MCP9808 sensors. Four conductor wire connects the temperature sensors to the NodeMCU, and for that I picked up some bright blue USB cables from Monoprice, and cut the connectors off. In hindsight, make sure you don't get charging cables. The wires are too large and very stiff. A cheap, non-charging cable has four wires of nearly equal size.

A Hammond ABS box holds the NodeMCU, and the cables just lead out to the two computers. The box is hidden behind the computers. The temperature sensors are taped to the CPU heatsinks.

The NodeMCU sits on a piece of perfboard in the box. There are only four pins being used: +3.3V, Ground, D1 (SDA) and D2 (SCL). The perfboard is glued to the top cover of the box with black RTV.

NodeMCU Development Board

NodeMCU

NodeMCU is a firmware platform for running Lua code on an ESP-12 by Espressif Systems. The name has come to mean any of the hardware bits it runs on as well. Most NodeMCU development boards contain a USB-to-serial converter, 3V power supply, and an ESP-12 or ESP-12E module.

The primary purpose of the ESP8266 is to provide a WiFi connection to your wireless router. This lets you use the ESP8266 as a means for your IoT device to communicate with the outside world. The ESP8266 is often used as an add-on module for an Arduino, but the CPU in the ESP8266 is many times more powerful than the Arduino itself.

There is a loadable module available for the Arduino IDE which allows one to write Arduino code for the ESP8266/NodeMCU module.

ESP8266 NodeMcu ESP8266 Module (4pcs),ESP-12E NodeMcu LUA CP2102 Internet WiFi Development Board Works with Arduino IDE/Micropython (Amazon)

NodeMCU Development Boards are also available on ebay for lower prices. NodedMCU on ebay (Affiliate Link)

Debugging the MCP9808 Boards

The I2C master has no address, but needs to know the slave address. We will have two slaves, so two slave addresses. One of the MCP9808 boards must have one jumper wire installed to set it to address 0x19, but start with an un-modified board at address 0x18 while debugging, so there is no confusion.

The Temperature Sensor Test Code

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include 
#include "Adafruit_MCP9808.h"

TwoWire *wire = &Wire;
Adafruit_MCP9808 tempsensor1 = Adafruit_MCP9808();
Adafruit_MCP9808 tempsensor2 = Adafruit_MCP9808();
unsigned long temperature_time;

void setup() {
  Serial.begin(115200);
  wire->begin(D1, D2);
  if (!tempsensor1.begin(0x18, wire)) {
    Serial.println("Couldn't find MCP9808 #1 ! Check your connections and verify the address is correct.");
    while (1);
  }
  if (!tempsensor2.begin(0x19, wire)) {
    Serial.println("Couldn't find MCP9808 #2 ! Check your connections and verify the address is correct.");
    while (1);
  }
  // Set the first read time 5 seconds in the future.
  temperature_time = millis() + 5000;
}

void loop() {
  if (temperature_time <= millis()) {
    // Set the next read to be 5 seconds in the future.
    temperature_time = millis() + 5000;

    // Print out the results.
    Serial.print("Temp1 = ");
    Serial.print(tempsensor1.readTempC());
    Serial.print("C\tTemp2 = ");
    Serial.print(tempsensor2.readTempC());
    Serial.println("C");
  }
  // Print a dot every second.
  Serial.print(".");
  delay(1000);
}
           

If you connect a single un-modified MCP9808 module to the NodeMCU, the code above should output something like this:

"Couldn't find MCP9808 #2 ! Check your connections and verify the address is correct."

Notice it is number 2 it can't find. That is what we want. If you get that, you are good to go, but if you get

"Couldn't find MCP9808 #1 ! Check your connections and verify the address is correct."

you are not reaching the sensor. Check your wiring and try again. Remember, D1 is SDA and D2 is SCL.

If you are good there, address the other module at 0x19 using a jumper between Vdd and A0 and try it. If you get this kind of data, one line every five seconds, both modules are working.

.....Temp1 = 28.00C	Temp2 = 28.00C
.....Temp1 = 28.00C	Temp2 = 28.00C
.....Temp1 = 28.00C	Temp2 = 28.00C
.....Temp1 = 27.94C	Temp2 = 28.00C
.....Temp1 = 28.00C	Temp2 = 27.94C

If you get

"Couldn't find MCP9808 #2 ! Check your connections and verify the address is correct."

You have a wiring problem with the second module. Check the address jumper, the solder joints, etc.

WiFi

So the next thing to do is get the WiFi working. It is a little more complicated, but only in software. It has to implement an HTTPS client in order to talk with the "ifthisthenthat" web service. If you don't already have an IFTTT account set up, there is a walk-through of the process. Setup IfThisThenThat. The account is free.

WIth the IFTTT account set up, you need to be able to connect to your WiFi router and send a message to the IFTTT endpoint you received when you set it up.

The following code is the complete program for temperature and for WiFi.

/*
 * Copyright (c) 2019 David Allmon
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
 
/*
 * NOTE: The options are set in firmware because under actual operating conditions, there
 * is no connection to a computer. Make sure you change the trigger_point and reset_point
 * variables to the values you need. Change the readTempC() to readTempF() to get the
 * temperature in Fahrenheit. If you make that change, you will also want to adjust your
 * trigger_point and reset_point.
 */

#include <Wire.h>
#include <Adafruit_MCP9808.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

// This fingerprint is used to identify the secure server and start a secure session.
// See the link at the bottom of https://www.arduino-board.com/projects/computer-temp-alert if
// you are using a different domain than ifft.com
const uint8_t fingerprint[20] = {0xAA,0x75,0xCB,0x41,0x2E,0xD5,0xF9,0x97,0xFF,0x5D,0xA0,0x8B,0x7D,0xAC,0x12,0x21,0x08,0x4B,0x00,0x8C};

// Create the WiFi object
ESP8266WiFiMulti WiFiMulti;

TwoWire *wire = &Wire;
Adafruit_MCP9808 tempsensor1 = Adafruit_MCP9808();
Adafruit_MCP9808 tempsensor2 = Adafruit_MCP9808();

// ms Timer used to trigger a read of the temperature probes.
unsigned long temperature_time;

// Trigger and reset temperatures. Go up to trigger and an alert happens.
// Drop down to reset and the alert is canceled with another text.
//                               ***** SET THESE TO MEET YOUR NEEDS *****
float trigger_point1=36.0, trigger_point2=50.0;
float reset_point1=32.0, reset_point2=35.0;

// So we only alert once per issue.
bool trigger_state = false;

// The IFTTT web service URL:   ***** CHANGE THIS TO YOUR IFTTT URL *****
char * ws_url = "https://maker.ifttt.com/trigger/computer_temperature/with/key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

// Your WiFi router...        ***** CHANGE THESE TO MATCH YOUR ROUTER *****
char * SSID = "xxxxxxxx";
char * PASSWD = "xxxxxxxx";

void setup() {
  Serial.begin(115200);

  // Both sensors use the same TwoWire object.
  // D1 and D2 are the SDA and SCL pins on the NodeMCU.
  wire->begin(D1, D2);

  // Begin checks to see that it is indeed an MCP9808,
  // then clears the config reg.
  if (!tempsensor1.begin(0x18, wire)) {
    Serial.println("Couldn't find MCP9808 #1 ! Check your connections and verify the address is correct.");
    while (1);
  }

  // Each sensor needs to be initialized using its address and the global wire pointer.
  if (!tempsensor2.begin(0x19, wire)) {
    Serial.println("Couldn't find MCP9808 #2 ! Check your connections and verify the address is correct.");
    while (1);
  }
  Serial.println("Temperature sensors setup");

  // Setup the WiFi
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(SSID, PASSWD);

  Serial.println("WiFi setup");
}

void loop() {

  // Read temperatures.
  float t1 = tempsensor1.readTempC();
  float t2 = tempsensor2.readTempC();

  Serial.print(t1);
  Serial.print("\t");
  Serial.println(t2);

  // Behave differently if triggered than if not triggered.
  if (trigger_state) {
    if (t1 <= reset_point1 && t2 <= reset_point2) {
      // All is well again.
      trigger_state = false;

      // Send a text to say all is well.
      if (!send_alert(t1, t2)) {
        // Retry logic here...
      }
    }
  } else {
    if ((t1 >= trigger_point1 || t2 >= trigger_point2) && !trigger_state) {
      // Too hot and no alert sent yet.
      trigger_state = true;

      // Send a text to say it is too hot.
      if (!send_alert(t1, t2)) {
        // Retry logic here...
      }
    }
  }
  delay(5000);
}

//
// send_alert sends the temperatures to a webhook at ifttt.com which triggers
// an alert, sending an SMS message to the phone number you've entered in the
// IFTTT alert.
//

bool send_alert(float t1, float t2) {

  char valbuf[20];

  if (strlen(ws_url) < 8) {
    Serial.println("No ws_url!");
    return false;
  }

  // Build the request.
  String url = String(ws_url) + "?value1=";
  sprintf(valbuf, "%.2f", t1);
  url += String(valbuf);
  url += String("&value2=");
  sprintf(valbuf, "%.2f", t2);
  url += String(valbuf);
  Serial.println(url);

  // Try to get a WiFi connection going.
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    // Create an SSL client and link the fingerprint.
    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
    client->setFingerprint(fingerprint);

    // Make the HTTPS client.
    HTTPClient https;

    Serial.println("HTTPS start");
    if (https.begin(*client, url.c_str())) {  // HTTPS

      int responseCode = https.GET();

      // responseCode will be negative on GET error, but there may
      // still be an HTTP error (like a 404 - Not found)
      if (responseCode > 0) {

        // HTTP header has been sent and Server response header has been handled
        Serial.println("Response code: " + String(responseCode));

        // Message received by server.
        if (responseCode == HTTP_CODE_OK || responseCode == HTTP_CODE_MOVED_PERMANENTLY) {
          // And there is a response.
          Serial.println(https.getString());
        }
      } else {
        Serial.println("HTTP error: " + https.errorToString(responseCode));
        return false;
      }

      https.end();
      return true;
    } else {
      Serial.println("Unable to connect");
      return false;
    }
  }
}

If all goes well, the output will look like this until a temperature event occurs.

Temperature sensors setup
WiFi setup
28.12	28.06
28.12	28.06
28.12	28.06

When a temperature event occurs, this happens:

https://maker.ifttt.com/trigger/computer_temperature/with/key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?value1=46.00&value2=28.12
HTTPS start
Response code: 200
Congratulations! You've fired the computer_temperature event

The "Congratulations!..." message is actually the response from the IFTTT.com webservice. And when the thing cools down, this happens. Only the temperatures are different.

31.19	28.06
https://maker.ifttt.com/trigger/computer_temperature/with/key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?value1=31.19&value2=28.06
HTTPS start
Response code: 200
Congratulations! You've fired the computer_temperature event
30.19	28.12

Because I just didn't think of it, I only made one IFTTT web hook, so I'm using the same one for overheating and for cooled off. The ideal thing would be to have another that says "Your computer has cooled down."

Files

Helpful Links


Arduino Board Logo

 

Arduino-Board is the go-to source for information on many available Arduino and Arduino-like boards, tutorials and projects.

Help and Support

Arduino-Board

Stay updated

Sign up if you would like to receive our once monthly newsletter.