Nano ESP32 sending SMS with Twilio

Hi all,

In case anyone is wondering, the twilio.h library works fine with the Nano ESP32. Just created a little one-room motion alarm that sends me an SMS. Very simple indeed. Create a free account on Twilio.com which will give you login credentials.

Just in case you need it, here's my code (and of course I have replaced all credentials with "XXXX"...). Reasonable well commented, I think. Have fun!

Cheers,
Michael

/*
 Intruder Alarm with text messaging
 By: Michael Willems - michael@willems.ca
 Needs:
    -Arduino Nano ESP32 
    -WiFi connectivity (2.4 GHz)
    -Twilio account
    -twilio-esp32-client library (from Arduino IDE)
    -PIR sensor
    -Five LEDs, 100R resistors, SPDT switch.
 Version 0.2 - 7 Aug 2023
 Alarm is activated with switch (flashing yellow); 60 seconds later it's active (solid yellow)
 Sends SMS to phone upon alarm, bootup, and arm/disarm.
*/

//-------------------------------------------------------------------------------------------
// INCLUDES, DECLARATIONS: 
//-------------------------------------------------------------------------------------------
#include "WiFi.h"
#include "twilio.hpp"

// define WiFi and SMS credentials:
const char* ssid = "XXXX";
const char* password = "XXXX";
Twilio *twilio;

// Values from Twilio (from the dashboard):
static const char *account_sid = "XXXX";
static const char *auth_token  = "XXXX";
static const char *from_number = "XXXX";
static const char *to_number   = "XXXX";
static const char *messageStart    = "I2000 Home Startup";
static const char *messageAlert    = "I2000 Home MOTION DETECTED";
static const char *messageArmed    = "I2000 Home Armed";
static const char *messageDisarmed = "I2000 Home Disarmed";
String response;

// define misc pins:
int PIRpin = 2;
int Switch = 10;
int PushButton = 11;

// on-board LEDs:
int activeled = 13;
int blueled = 16;

// External LEDs:
int OkLed = 3;          // WiFi and SMS OK 
int WiFiErrLed = 4;     // WiFi Error
int SmsErrLed = 5;      // SMS Error
int ArmLed = 6;         // Armed
int TrigLed = 7;        // Motion seen!

// Counters etc:
unsigned long oneseccounter;
unsigned long quartersecondcounter;
unsigned long prearmtimer;
unsigned long prearmdelay = 60000; 
boolean ArmedStat = false;        // are we armed?
boolean PreArmInhibit = false;    // are we stil in pre-arm time, so no alarms yet please?
boolean TriggeredStat = false;    // is the alarm triggered?


//-------------------------------------------------------------------------------------------
// THE SETUP (RUNS ONCE): 
//-------------------------------------------------------------------------------------------
void setup() {
  pinMode(PIRpin, INPUT);
  pinMode(Switch, INPUT_PULLUP);
  pinMode(PushButton, INPUT_PULLUP);
  pinMode(activeled, OUTPUT);
  pinMode(blueled, OUTPUT);
  pinMode(OkLed, OUTPUT);
  pinMode(WiFiErrLed, OUTPUT);
  pinMode(SmsErrLed, OUTPUT);
  pinMode (ArmLed, OUTPUT);
  pinMode(TrigLed, OUTPUT);

  // Set inital LED status:
  digitalWrite (OkLed, LOW);
  digitalWrite (WiFiErrLed, HIGH);
  digitalWrite (SmsErrLed, HIGH);
  digitalWrite (ArmLed, LOW);
  digitalWrite (TrigLed, LOW);

  // Now connect to WiFi and wait until connected:
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite (activeled, LOW);
    analogWrite (blueled, LOW);
    delay(500);
  }
  // We are connected, so indicate this:
  analogWrite (blueled, HIGH);
  digitalWrite (activeled, HIGH);
  digitalWrite (WiFiErrLed, LOW);
  delay(500);

  // start Twilio instance:
  twilio = new Twilio(account_sid, auth_token);

  // Now send SMS:
  String response;
  bool success = twilio->send_message(to_number, from_number, messageStart, response);
  if (success) {
    digitalWrite(SmsErrLed, LOW);
    digitalWrite (OkLed, HIGH);     // because of SMS was sent, WiFi must also be OK
  } else {
    digitalWrite(SmsErrLed, HIGH);
    Serial.println(response);
  }
  // set the timers to start:
  oneseccounter = millis();
  quartersecondcounter = millis();
}


//-------------------------------------------------------------------------------------------
// THE LOOP (RUNS CONTINUOUSLY): 
//-------------------------------------------------------------------------------------------
void loop() {

  // now do the "once every second" things:
  if ((millis() - oneseccounter) > 1000) {

    //Toggle the on-board active LED:
    digitalWrite (activeled, !digitalRead(activeled));
    
    // is WiFi connected? If not, turn off the blue and OK LED, and turn on WiFi Error LED:
    if (WiFi.status() != WL_CONNECTED) {
      analogWrite (blueled, LOW);
      analogWrite (WiFiErrLed, HIGH);
      digitalWrite (OkLed, LOW);      
    }
    else {
    
    // wifi is OK, so turn the on-board blue LED on, and turn WiFi error light off:
    analogWrite (blueled, HIGH);
    analogWrite (WiFiErrLed, LOW);
    digitalWrite (OkLed, HIGH);      
    }

    // Now reset counter so we can start counting another second:
    oneseccounter = millis();
  }   
  // End of "once a second" things.


  // The "every quarter second" thing - for flashing the light while armed+inhibited:
  if ((millis() - quartersecondcounter) > 250) {
    if ((ArmedStat == true) && (PreArmInhibit == true)) {
      digitalWrite (ArmLed, !digitalRead(ArmLed));
    }
    quartersecondcounter = millis();
  }
  // End of the "every quarter second" thing.


  // Now the "always do this" things:

  // Arm/Disarm routines:
  // -------------------
  if (digitalRead(Switch) == LOW){    //switch is turned on (up)
    if ((millis() - prearmtimer) > prearmdelay) {
      PreArmInhibit = false;
      digitalWrite (ArmLed, HIGH);    // turn on "Armed" light just in case it's not on yet
    }
    if (ArmedStat == false) {         // i.e. it was just now turned to ARM...
      ArmedStat = true;               // so next loop it knows it's not only just been armed, so not another SMS
      digitalWrite (ArmLed, HIGH);    // turn on "Armed" light just in case it's not on yet
      // Send "Armed" SMS:
      bool success = twilio->send_message(to_number, from_number, messageArmed, response);
      if (success) {
        digitalWrite(SmsErrLed, LOW);
        digitalWrite (OkLed, HIGH);     // because of SMS was sent, WiFi must also be OK
      } else {
        digitalWrite(SmsErrLed, HIGH);
      }
      // Start Inhibit timer (minute to get out of the room):
      PreArmInhibit = true;
      prearmtimer = millis();
    }
  } else {                            // Switch is turned down (off)
    digitalWrite (ArmLed, LOW);       // so turn off Armed LED
    if (ArmedStat == true) {          // i.e. it was just turned to DISARM...
      // Send "Disarmed" SMS:
      bool success = twilio->send_message(to_number, from_number, messageDisarmed, response);
      if (success) {
        digitalWrite(SmsErrLed, LOW);
        digitalWrite (OkLed, HIGH);   // We can do this because if SMS was sent, WiFi must also be OK
      } else {
        digitalWrite(SmsErrLed, HIGH);
      }
      ArmedStat = false;              // so next loop it knows it's not only just been disarmed, so not another SMS
    }
  }

  // Trigger Event Routines:
  // -----------------------
  if (digitalRead(PIRpin) == HIGH) {  // The PIR is giving an trigger indication...
    digitalWrite (TrigLed, HIGH);     // ..so, turn on the Trigger LED just in case it's not on yet.
    if ((ArmedStat == true) && (PreArmInhibit == false)) {   // we are armed and we are not inhibited
      if (TriggeredStat == false) {   //we were not triggered, but now we are.
        // So, send an SMS: we had a motion alert. 
        bool success = twilio->send_message(to_number, from_number, messageAlert, response);
          if (success) {
            digitalWrite(SmsErrLed, LOW);
            digitalWrite (OkLed, HIGH);
          } else {
            digitalWrite(SmsErrLed, HIGH);
            Serial.println(response);
          }
        TriggeredStat = true;       // Trigger status ON (so we won't send another SMS, for a start!)
      }
    }
  }
  else {                            // the PIR is not giving an trigger indication
    if ((ArmedStat == false) || (PreArmInhibit == true )) {
      digitalWrite (TrigLed, LOW);  // ...we are not [yet] armed, so turn off Trigger LED when PIR stops activating
      TriggeredStat = false;        // also, since we are not armed and not triggered, turn off triggered status 
    }
  }

  //--end of loop code here--
  //
}

//-------------------------------------------------------------------------------------------
// THE FUNCTIONS (CALLED AS NEEDED): 
//-------------------------------------------------------------------------------------------
// tbd  





1 Like

Thank you. I have done some projects with twilio already. Will give this a try too.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.