Cannot send SMS

I’ve been trying to create SMS alarm using Twilio, Firebase and Arduino IDE. Using sensors I am measuring the temperature. If the temperature is higher than a specified value (ESP reads that value from Firebase Realtime Database), a SMS should be sent using twilio. I am also storing the measures in Firebase Realtime Database. The code worked well, until I tried to add the part where it also pushed measurements (temperatures) to Firebase Realtime Database. It even prints in serial that it is connecting to Twilio api, however, I never receive the message.

Here’s my code:

#/*
 * Twilio SMS and MMS on ESP8266 Example.
 */
 #include "FirebaseArduino.h"
#include "OneWire.h"
#include "DallasTemperature.h"
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266WebServer.h>
#include <sstream> 
#include <iostream> 
#include "twilio.hpp"

// Use software serial for debugging?
#define USE_SOFTWARE_SERIAL 0

// Print debug messages over serial?
#define USE_SERIAL 1

// Your network SSID and password
const char* ssid="SSID";
const char* password = "PASSWORD";

// Find the api.twilio.com SHA1 fingerprint, this one was valid as 
// of July 2020. This will change, please see 
// https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-esp8266-cpp
// to see how to update the fingerprint.
const char fingerprint[] = "BC B0 1A 32 80 5D E6 E4 A2 29 66 2B 08 C8 E0 4C 45 29 3F D0";

// Twilio account specific details, from https://twilio.com/console
// Please see the article: 
// https://www.twilio.com/docs/guides/receive-and-reply-sms-and-mms-messages-esp8266-c-and-ngrok

// If this device is deployed in the field you should only deploy a revocable
// key. This code is only suitable for prototyping or if you retain physical
// control of the installation.
const char* account_sid = "SID";
const char* auth_token = "TOKEN";

// Details for the SMS we'll send with Twilio.  Should be a number you own 
// (check the console, link above).
String to_number    = "+55555";
String from_number = "+66666";
String message_body    = "Hello from Twilio and the ESP8266!";

// The 'authorized number' to text the ESP8266 for our example
String master_number    = "+55555";

// Optional - a url to an image.  See 'MediaUrl' here: 
// https://www.twilio.com/docs/api/rest/sending-messages
String media_url = "";

// Global twilio objects
Twilio *twilio;
ESP8266WebServer twilio_server(8000);

//  Optional software serial debugging
#if USE_SOFTWARE_SERIAL == 1
#include <SoftwareSerial.h>
// You'll need to set pin numbers to match your setup if you
// do use Software Serial
extern SoftwareSerial swSer(14, 4, false, 256);
#else
#define swSer Serial
#endif

String b;
int c;
#define FIREBASE_HOST "firebaseio.com"
#define FIREBASE_AUTH ""

#define ONE_WIRE_BUS 4 
/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices  
// (not just Maxim/Dallas temperature ICs) 
OneWire oneWire(ONE_WIRE_BUS); 
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

float temp1 = 0;

/*
 * Setup function for ESP8266 Twilio Example.
 * 
 * Here we connect to a friendly wireless network, set the time, instantiate 
 * our twilio object, optionally set up software serial, then send a SMS 
 * or MMS message.
 */
void setup() {
        WiFi.begin(ssid, password);
        twilio = new Twilio(account_sid, auth_token, fingerprint);

        #if USE_SERIAL == 1
        swSer.begin(115200);
        while (WiFi.status() != WL_CONNECTED) {
                delay(1000);
                swSer.print(".");
        }
        swSer.println("");
        swSer.println("Connected to WiFi, IP address: ");
        swSer.println(WiFi.localIP());
        #else
        while (WiFi.status() != WL_CONNECTED) delay(1000);
        #endif

        // Response will be filled with connection info and Twilio API responses
        // from this initial SMS send.
        


        twilio_server.begin();

        // Use LED_BUILTIN to find the LED pin and set the GPIO to output
        pinMode(LED_BUILTIN, OUTPUT);

         sensors.begin(); 
         Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); 

}


/* 
 *  In our main loop, we listen for connections from Twilio in handleClient().
 */
void loop() {
  b = Firebase.getString("002/alarm");
  c = b.toInt();
  Serial.print(c);

   sensors.requestTemperatures();
   temp1 = sensors.getTempCByIndex(0);
   StaticJsonBuffer<256> jsonBuffer;
JsonObject& timeStampObject = jsonBuffer.createObject();
timeStampObject[".sv"] = "timestamp";

JsonObject& root = jsonBuffer.createObject();
JsonArray& timestamp = root.createNestedArray("timestamp");
timestamp.add(timeStampObject);
JsonArray& temperature = root.createNestedArray("temperature");
temperature.add(temp1);


Firebase.push("Sensors/001", root);
   if (temp1 > c) {
        String response;
        bool success = twilio->send_message(
                to_number,
                from_number,
                message_body,
                response,
                media_url
        );
   }
        

          delay(20000);
}

I know this is a lot of code, but it is as reduced as it can be. If I remove the part in the loop where it pushes the values to Firebase and it only sends a fixed SMS, when the value (temperature) is too high then the SMS gets send. However, I would also need it to push the values to Firebase. Is it possible that NodeMCU Amica V2 is not powerful enough to do that all in one loop?

Any help would be appreciated!

use Ctrl-T for automated formatting of your code in the Arduino-IDE

Your code has a delay(20000); This means your arduino is 20 seconds long totally busy with - - - waiting

This means while a delay() is executed your microcontroller is unable to do anything else
because internally delay means just loop a short loop a million times per second until the waiting-time is over.
The delay() occupies all the calculation-power that the arduino has. In short delay() is blocking

So learn to use timing based on the command millis(). There are programming-techniques where checking if a period-of time is over just takes a single millisecond. and 99,9% of the time the Arduino is free do to other things.
This is called non-blocking.

especially @Arduino editoral staff that is responsible for the content of the inbuild examples:
WHEN WILL YOU EVER REMOVE THE MOST PROBLEMATIC COMMAND DELAY() FROM THE EXAMPLES AND REPLACE IT WITH MILLIS()?

best regards Stefan
any newbee can apply the most professional habit from the first line of code they write on their own:
add only ONE thing at a time. Test/debug that ONE thing until that ONE thing works reliable - repeat.
The sad thing is: only the REAL professionals write code this way.

Thanks for your advice! I tried changing it into millis, but it still doesn’t work. In fact, now it doesn’t work even with just sending the SMS (without pushing values to Firebase). However, the part which pushes the values to Firebase works fine with millis. This is my code (I used Ctrl-T this time :slight_smile: ) for only sending the SMS if temperature is too high using millis:

#include "OneWire.h"
#include "DallasTemperature.h"
#include "ESP8266WiFi.h"
#include "FirebaseArduino.h"
#include <WiFiManager.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
#include <ESP8266WebServer.h>
#include <string>
using namespace std;
#include <sstream>
#include <iostream>

unsigned long messageStartMillis;
unsigned long currentMillis;
const unsigned long messagePeriod = 5000;

#include "twilio.hpp"

// Use software serial for debugging?
#define USE_SOFTWARE_SERIAL 0

// Print debug messages over serial?
#define USE_SERIAL 1

const char fingerprint[] = "BC B0 1A 32 80 5D E6 E4 A2 29 66 2B 08 C8 E0 4C 45 29 3F D0";

String a;
String b;
int c;

String to_number    = "...";
String from_number = "...";
String message_body    = "Hello from Twilio and the ESP8266!";

// The 'authorized number' to text the ESP8266 for our example
String master_number    = "...";

// Optional - a url to an image.  See 'MediaUrl' here:
// https://www.twilio.com/docs/api/rest/sending-messages
String media_url = "";

const char* account_sid = "...";
const char* auth_token = "...";

Twilio *twilio;
ESP8266WebServer twilio_server(8000);

//  Optional software serial debugging
#if USE_SOFTWARE_SERIAL == 1
#include <SoftwareSerial.h>
// You'll need to set pin numbers to match your setup if you
// do use Software Serial
extern SoftwareSerial swSer(14, 4, false, 256);
#else
#define swSer Serial
#endif

// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 4
/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
/********************************************************************/
//#define FIREBASE_HOST "..."
//#define FIREBASE_AUTH "..."
//#define FIREBASE_HOST "..."
//#define FIREBASE_AUTH "..."
#define FIREBASE_HOST "..."
#define FIREBASE_AUTH "..."

float temp1 = 0;

void setup(void) {
  WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP

  Serial.begin(115200);

  sendStartMillis = millis();
  messageStartMillis = millis();

  twilio = new Twilio(account_sid, auth_token, fingerprint);
  
  WiFiManager wm;

  bool res;
  res = wm.autoConnect("AutoConnectAP", "password"); 

  if (!res) {
    Serial.println("Failed to connect");
    // ESP.restart();
  }
  else {
    Serial.println("connected...yeey :)");
  }
  twilio_server.begin();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

  Serial.println("Dallas Temperature IC Control Library Demo");

  sensors.begin();

}


void loop() {
  currentMillis = millis();
  sensors.requestTemperatures();
  temp1 = sensors.getTempCByIndex(0);
  message();
}

void message() {
  if (currentMillis - messageStartMillis >= messagePeriod)
  {

    Serial.print(temp1);
    b = Firebase.getString("002/alarm");
    Serial.print(a);
    c = b.toInt();
    Serial.print(c);

    if (temp1 > c) {
      Serial.print("Alarm");
    }

    if (temp1 > c) {
      String response;
      bool success = twilio->send_message(
                       to_number,
                       from_number,
                       message_body,
                       response,
                       media_url
                     );
    }
    messageStartMillis = currentMillis;
  }
}

It’s very weird, because it prints into serial that it is connecting to twilio api (follow this link to see the screenshot: Serial - Album on Imgur). Is there anything wrong with millis? Thanks again!

Nothing wrong with millis(), it is printing “alarm” after all.
Is “success” returned true or false?
Add that to the debug output.

Thanks for your reply! I tried adding “success” to the debug output and I figured out that the previous code didn’t work because I was retreiving data from Firebase. To solve that I tried to create a new void just to read the data from firebase, however, it still doesn’t send SMS. Here is a link to the screenhost of what it prints into the console: Serial - Album on Imgur. As mentioned when I add the part which retrieves data from Firebase it prints into serial: Connection failed. So, now I don’t know how to add it together with millis to make it work. Here is my new code:

/*
   Twilio SMS and MMS on ESP8266 Example.
*/
#include "OneWire.h"
#include "DallasTemperature.h"
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266WebServer.h>
#include "FirebaseArduino.h"
#include <WiFiManager.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#include <string>
using namespace std;
#include <sstream>
#include <iostream>
#include "twilio.hpp"

unsigned long variableStartMillis;
unsigned long messageStartMillis;
unsigned long currentMillis;
const unsigned long variablePeriod = 5000;
const unsigned long messagePeriod = 5000;


// Use software serial for debugging?
#define USE_SOFTWARE_SERIAL 0

// Print debug messages over serial?
#define USE_SERIAL 1

// Your network SSID and password
const char* ssid = "**";
const char* password = "**";

// Find the api.twilio.com SHA1 fingerprint, this one was valid as
// of July 2020. This will change, please see
// https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-esp8266-cpp
// to see how to update the fingerprint.
const char fingerprint[] = "BC B0 1A 32 80 5D E6 E4 A2 29 66 2B 08 C8 E0 4C 45 29 3F D0";

// Twilio account specific details, from https://twilio.com/console
// Please see the article:
// https://www.twilio.com/docs/guides/receive-and-reply-sms-and-mms-messages-esp8266-c-and-ngrok

// If this device is deployed in the field you should only deploy a revocable
// key. This code is only suitable for prototyping or if you retain physical
// control of the installation.
const char* account_sid = "**";
const char* auth_token = "**";

// Details for the SMS we'll send with Twilio.  Should be a number you own
// (check the console, link above).
String to_number    = "**";
String from_number = "**";
String message_body    = "Hello from Twilio and the ESP8266!";

// The 'authorized number' to text the ESP8266 for our example
String master_number    = "**";

// Optional - a url to an image.  See 'MediaUrl' here:
// https://www.twilio.com/docs/api/rest/sending-messages
String media_url = "";

// Global twilio objects
Twilio *twilio;
ESP8266WebServer twilio_server(8000);

//  Optional software serial debugging
#if USE_SOFTWARE_SERIAL == 1
#include <SoftwareSerial.h>
// You'll need to set pin numbers to match your setup if you
// do use Software Serial
extern SoftwareSerial swSer(14, 4, false, 256);
#else
#define swSer Serial
#endif

// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 4
/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
/********************************************************************/

#define FIREBASE_HOST "**"
#define FIREBASE_AUTH "**"

float temp1 = 0;
//float temp2 = 0;
String b;
int c;


void setup() {
  WiFi.begin(ssid, password);
  twilio = new Twilio(account_sid, auth_token, fingerprint);

#if USE_SERIAL == 1
  swSer.begin(115200);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    swSer.print(".");
  }
  swSer.println("");
  swSer.println("Connected to WiFi, IP address: ");
  swSer.println(WiFi.localIP());
#else
  while (WiFi.status() != WL_CONNECTED) delay(1000);
#endif

  // Response will be filled with connection info and Twilio API responses
  // from this initial SMS send.


  twilio_server.begin();

  messageStartMillis = millis();
  variableStartMillis = millis();

  // Use LED_BUILTIN to find the LED pin and set the GPIO to output
  pinMode(LED_BUILTIN, OUTPUT);

  sensors.begin();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

}

void loop() {
  currentMillis = millis();
  sensors.requestTemperatures();
  temp1 = sensors.getTempCByIndex(0);
  variable();
  message();
}

void variable () {
  if (currentMillis - variableStartMillis >= variablePeriod)
  {
    b = Firebase.getString("002/alarm");
    c = b.toInt();
    Serial.print(c);
    variableStartMillis = currentMillis;
  }
}

void message () {
  if (currentMillis - messageStartMillis >= messagePeriod) {
    Serial.print(temp1);
    if (temp1 > 30) {
      String response;
      bool success = twilio->send_message(
                       to_number,
                       from_number,
                       message_body,
                       response,
                       media_url
                     );
#if USE_SERIAL == 1
      swSer.println(response);
#endif
    }
    messageStartMillis = currentMillis;
  }
}

Does it connect to WiFi?
You haven't show us that bit of the log.

You really need to add more debugging output, but to me it looks like it never gets to...

swSer.println(response);

You can copy and paste from the serial monitor and save us all the effort of following a imgur link.

I'm sure that it connects to WiFi. This is what it prints to serial monitor:

.
Connected to WiFi, IP address: 
192.168.1.72
3028.813028.943029.063029.133029.193029.253029.313029.443029.503029.313029.133028.883028.813029.063029.313029.503030.003030.31connecting to api.twilio.com
Using fingerprint 'BC B0 1A 32 80 5D E6 E4 A2 29 66 2B 08 C8 E0 4C 45 29 3F D0'
Connecting to host api.twilio.com
Connection failed!

The swSer.println(response); is where it writes connection failed in the serial. Otherwise (if I remove the part where the data is retrieved from Firebase) the swSer.println(response); returns a bunch of data about the connection with Twilio and the SMS is successfully send. Thanks for all your help.