Showing posts with label IFTTT. Show all posts
Showing posts with label IFTTT. Show all posts

Tuesday, May 11, 2021

2m / 70cm Ham Radio Traffic Logger

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYmnOfpJVA2y6GyGkoIOYluMaY2jMoXwGHuCfwkxN8XPYeJUn95zCR6ENM9gJrmd-2vhqYp_0OzWCLDiUItELwP690bjO5wu2y8NSGTZy4fF-TfU84jffUY3ztjd0bSz5hzo35BTHrxpsR/s1600/BT_Logger_Schmatic-793823.JPG 

Is the frequency in use (or QRL? in Morse Code)?

-----

We had a curiosity about how often some of the local ham radio repeaters and the 2m calling frequency was being used and decided to put together a rig that could answer the question with real data.    Ham radio has a lot to do with experimentation and tinkering so we set out on a mission to answer the question with "stuff" we had laying around the shack.

-----

Pretty much any newcomer to ham radio has invested $35'ish on a Baofeng hand held.  The little unit is quickly out grown, but it has come in useful time and time again.   This project was just another example of it's unintended usefulness.  Also, like most hobbyist there's never a shortage of WiFi friendly ESP8266s laying around.   Combining the two for an RF activity logger became the objective.

-----

And..... it turned out to be pretty easy and didn't even require opening up the Baofeng.   Anytime the Baofeng hears a signal the LCD display light is activated.   For reasons unknown this presents a voltage spike on the speaker jack.   We suspected this could be the case from the loud "pop" that can be heard when using earphones.

-----

Here is a look at the signal generated on the speaker jack when the display light gets activated:

Weird, huh?   Oh well, we can use that to make the project dead simple.  Just tune the Baofeng to the frequency of interest and let the rig run and log any traffic that hit the antenna.

-----

The schematic at the top of the page shows how we feed the speaker signal into the analog input (A0) of the ESP8266.   To tame the 5 volt signal going into the ESP8266 two diodes are placed back to back.   That's it.   The ESP8266 is programmed to update a Google Drive Sheet via an IFTTT Webhook anytime a voltage is detected.   The activity log looks like this and the source code is below that.  If you duplicate the project, let us know.

-----

-----

/*
 *  Baofeng Traffic Logger
 *  MAY2021
 *  WhiskeyTangoHotel.Com
 *   
 *  Logs to Google Sheet is traffic is dectected on BF HT Radio    !!!  
 *  by monitoring a voltage on the speaker output.  On traffic the !!!
 *  BF display lights and creates a voltage on the speaker jack    !!!
 *  Since no transit, does not require a license, but if you don't !!!
 *  have a ham license, get one.  It's a fun hobby!!!              !!!  
 *  See: http://www.arrl.org/getting-licensed                      !!!
 *  
 *  uC setting for Ardunio IDE (ESP8266 with WiFI)
 *  NodeMCU 1.0 (ESP-12E Module), 80MHz, 921600, 4M (3M SPIFFS)
 *  
*/

// For the Wireless
#include <ESP8266WiFi.h>

// WiFi Connection Information
const char* ssid = "yourSSID";           // PRIVATE: Enter your personal setup information.
const char* password = "yourpassword";   // PRIVATE: Enter your personal setup information.

// IFTTT Information for WebHook widget
String MAKER_SECRET_KEY = "yourIFTTTkey";   // PRIVATE: Enter your personal setup information. Your IFTTT Webhook key here
String TRIGGER_NAME_google_drive = "yourIFTTTWebHookTriggerName";  // this is the Maker IFTTT trigger name for google drive spreadsheet logging
String url_google_drive;  // url that gets built for the IFTTT Webhook logging to google drive spreadsheet
String Status ="Program_Started.....";  // Status payload for Google Sheet.  We log all starts and reboots
const char* host = "maker.ifttt.com";

// Define ESP8266 pins
const int led = 2;  // Blue on board LED is on PIN-D4 (GPIO2) for this NoderMCU 1.0 ESP8266.  Blink it between reads
const int analogInPin = A0;  // ESP8266 Analog Pin ADC0 = A0

int sigValue = 0;  // value to determine if a signal is detected

// Program control variables
int logging = 1; // If 1 then send SMS.  Any other value (0) turns it off.  For debug, typically would be set = 1

void setup(void){ // This setup code is run once.
  pinMode(led, OUTPUT);     // set up the onboard Blue LED pin as an output.  
  Serial.begin(115200);     // turn on the serial monitor for debug

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(10);
  }
 
  // Is the WiFi working?
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Trying to connect to ");
    Serial.print(ssid);
    Serial.print(" on ");
    Serial.print(WiFi.localIP());
    Serial.println(" ");
    for (int x = 0; x < 20; x++) { //  
      digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is trying to WiFi connect
      //Serial.println("Server Start blink loop....");
      delay(50);   
    } // endfor WiFi blink connect
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println(WiFi.localIP());

  for (int x = 0; x < 10; x++) { // 5 slow LED blinks to slow WIFI Connected.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
  Serial.println("WIFI is Connected....");
  delay(500);   } // endif for WIFI Connected blink  

  // Use WiFiClient class to create TCP connections for WiFi logging
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");  // Boo!!!
    return;
  }

  // Trigger the IFTTT Webhook Channel to update a Google sheet at program start.
  // This can help log power outs, etc.  For first run we defined String Status for identify a startup condition.
  // Create the request for IFTTT google drive
  url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
  Serial.println(" ");  
  Serial.println("Status: Google Sheet update done with trigger:");
  Serial.println (url_google_drive);
  Serial.println(" ");  
    
  // This sends the request to the IFTTT server
  client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
  "Host: " + host + "\r\n" +
  "Connection: close\r\n\r\n");  
  delay(500);  // Delay for web traffic; maybe not required.  

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
     String line = client.readStringUntil('\r');    }

}


void loop(void){    // Loop until the Dallas Cowboys win a Super Bowl
 
  sigValue = analogRead(analogInPin);
 
  // For Degug print SigVal readings in the Serial Monitor
  //Serial.println(sigValue);

  // The blue onboard LED will SLOW blink between to show prog is 'running'.
  // FAST blink when sig is dectected.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
    
  if (sigValue > 500) {  //  Threshold may need adjusting.  Voltage on speaker jack detected.  We have a signal
      Serial.println("!!!_Signal_Detected_!!!");   
      Serial.println(" ");
              
      if (logging == 1) { // is Google Sheet logging turned on?
          Serial.println("***** Logging is ON *****");
          String Status = "!!!_Signal_Detected_!!!";
          // Set up IFTTT Webhook Channel to update the Google Sheet.  
          // Use WiFiClient class to create TCP connections for IFTTT
          WiFiClient client;
          const int httpPort = 80;
          if (!client.connect(host, httpPort)) {
            Serial.println("connection failed");
            return;
          }
          
          // Create the request for IFTTT google drive
          url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
            
          // This sends the request to the IFTTT server
          client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
          "Host: " + host + "\r\n" +
          "Connection: close\r\n\r\n");  
          delay(500);  // Delay for web traffic; maybe not required.  
        
          // Read all the lines of the reply from server and print them to Serial
          while(client.available()){
             String line = client.readStringUntil('\r');    }
                  
          Serial.println("Status: Google Sheet update done with trigger:");
          Serial.println(url_google_drive);
          Serial.println(" ");
          
          // Fast blink the blue onboard LED to show sig was dectected and delay for flood control
          for (int x = 0; x < 600; x++) { // x = 20 for ~ 1 sec, x = 100 for ~5 sec.....
              digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED
              delay(50);   
          } // endfor delay/blink
          
          Serial.println("-------------------------------------");
          Serial.println("Waiting for signal... ");
           
      } else {
        
          Serial.println("Logging is OFF.");
          Serial.println(" ");
      } // endif/else logging  


            
  }
  delay(250); // Delay for onboard blue LED Blink shows program running
    
} // void loop until Cowboys win Super Bowl

-----

Wednesday, February 26, 2020

ESP8266 Doorbell Sends SMS and Updates Google Sheet

-----
On-line shopping has changed the way goods are acquired.  For most packages it is not necessary to be around for the dropoff.  But... for the important stuff it is.  Those packages always seem to show up right when you are in the backyard for mere seconds causing that frustrating "Personal Signature Required for Delivery" note on the door.  This is our DIY effort to solve that problem.
-----
Needed:
     - ESP8266 (microcontroller with WiFi)
     - 1M ohm resistor
     - reed switch
     - IFTTT account (using the WebHook applet)
     - wire and stuff
     - fundamental knowledge on Arduino sketches (simple code edits).
-----
The connections are simple:

 ----
And the rig will look something like this:
-----
A 1M ohm resister connected from 3.3V to the A0 [ADC] input on the ESP8266 keeps the A0 reading at maximum value.   The normally open reed switch is placed right on top of the coils that activate the doorbell.  These coils act like that electromagnet you build in grade school to ring the doorbell and cause the reed switch to close.  This drops the impedance to the 1M resistor and changes the ADC value on the A0 pin for detection of the doorbell.  Then the SMS is sent to your phone and a Google Drive Sheet is updated.
-----
-----
The sketch you need to upload to the the ESP8266 looks like this:
```````````````````````````````````````````````````````````````````````````````
/*
 *  FEB2020
 *  Door Bell Monitoring
 *  WhiskeyTangoHotel.Com
 * 
 *  Build details at:
 *  http://www.whiskeytangohotel.com/2020/02/esp8266-doorbell-sends-sms-and-updates.html
 * 
 *  On Doorbell ring:
 *    Logs to Google Drive (as an appending spreadsheet)
 *    Sends SMS to cell phone
 * 
 *  ESP8266 uC
*/

// For the Wireless
#include <ESP8266WiFi.h>

// WiFi Connection Information
const char* ssid = "yourssid";    // PRIVATE: Enter your personal setup information.
const char* password = "yourwifipassword"; // PRIVATE: Enter your personal setup information.

// IFTTT Information for WebHook widget
String MAKER_SECRET_KEY = "yourIFTTTprivatekey";  // PRIVATE: Enter your personal setup information. Your IFTTT Webhook key here
String TRIGGER_NAME_google_drive = "googlebell";    // this is the Maker IFTTT trigger name for google drive spreadsheet logging
String TRIGGER_NAME_SMS = "doorbell";              // this is the Maker IFTTT trigger name to send SMS.
const char* host = "maker.ifttt.com";
String url_SMS;                      // url that gets built for the IFTTT Webhook sending SMS
String url_google_drive;            // url that gets built for the IFTTT Webhook logging to google drive spreadsheet
String Status ="**_Starting_on:";  // Status payload for Google Sheet.  We log all starts and reboots

// Define and set up some variables
int sensorValue = 0;  // reading from A0.  This pin detects the doorbell (ADC reading between 0-1024)

// Define pins
const int led = 2;     // Blue on board LED is on PIN2.  Active LOW.  Blinks it between reads
const int bell = A0;  // analog input for the doorbell transducer. 1MOhm on board in // with 1MOhm from the reed switch pickup

// Program control variables
int Seconds_dwell_after_detect = 8;  // Prevents logging flood and debounce.   Sensor reads, LED flashing, etc.
int logging = 1; // If 1 then SMS and log to cloud.  Any other value (0) turns it off.

void setup(){  // This is run once.
  pinMode(led, OUTPUT);  // set up the onbaord LED pin as an output.    
  Serial.begin(115200);  // turn on the serial monitor for debug

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(10);
  }
 
  // Is the WiFi working?
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Trying to connect to ");
    Serial.print(ssid);
    Serial.print(" on ");
    Serial.println(WiFi.localIP());
    for (int x = 0; x < 20; x++) { // 
      digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is trying to WiFi connect
      //Serial.println("Server Start blink loop....");
      delay(5);   // Delay so short the LED looks like it is always on
    } // endfor WiFi blink connect
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println(WiFi.localIP());

  for (int x = 0; x < 10; x++) { // 5 slow LED blinks to slow WIFI Connected.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
  Serial.println("WIFI is Connected....");
  delay(500);   } // endif for WIFI Connected blink


  // Use WiFiClient class to create TCP connections for WiFi logging
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");  // Boo!!!
    return;
  }

  // Trigger the IFTTT Webhook Channel to update a Google sheet with the activity of the server starting/restarting
  // This can help log power outs, etc.  For first run we defined String Status for identify a startup condition.
  // Create the request for IFTTT google drive
  url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
  Serial.println (url_google_drive);
  Serial.println(" "); 
   
  // This sends the request to the IFTTT server
  client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
  "Host: " + host + "\r\n" +
  "Connection: close\r\n\r\n"); 
  delay(500);  // Delay for web traffic; maybe not required. 

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
     String line = client.readStringUntil('\r');    }

  String Status = "Payload_String_for_Google_Sheet";
}
 
void loop(){   // Loop forever or until the Dallas Cowboys win a Super Bowl
  // Read the A0 pin and post based on the delay values set above.
  // The blue onboard LED will fast blink while polling
  sensorValue = analogRead(bell);
  //Serial.println (sensorValue);   //debug only

  // Fast Blink Blue LED while waiting for doorbell press
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is running
  Serial.println("Waiting for DoorBell....");
  delay(50);   

  // Use WiFiClient class to create TCP connections for IFTT
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
 
  if (sensorValue < 200 || sensorValue > 300) {  //  A0 values between 200-300 are normal.  Increases (apprx doubles) when DB is pressed
      Serial.println("----------Doorbell Dectected----------");

      if (logging == 1) { // is logging turned on? Non "1" is for debug...  Typically would be set = 1
        Serial.println("***** Logging is ON *****");

        // Build the IFTTT Webhoo Channel for SMS url
        url_SMS = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_SMS + "/with/key/" + MAKER_SECRET_KEY;
        client.print(String("POST ") + url_SMS + " HTTP/1.1\r\n" +
        "Host: " + host + "\r\n" +
        "Connection: close\r\n\r\n");
        Serial.println(" ");
        Serial.println("SMS payload to IFTTT is:");
        Serial.println(url_SMS);   
        Serial.println(" ");  

        // This must be run before any IFTTT webhook
        const int httpPort = 80;
        if (!client.connect(host, httpPort)) {
          Serial.println("connection failed");
          return;
        }
           
        // Set up IFTTT Webhook Channel to update a Google sheet with the activity. 
        Status ="__Doorbell_on:";
        url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
        client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
        "Host: " + host + "\r\n" +
        "Connection: close\r\n\r\n");
        Serial.println(" ");
        Serial.println("IFTTT url payload to Google Drive is:");
        Serial.println(url_google_drive);
        Serial.println(" ");
   
      } else {   // We are not sending to IFTTT.  Debug mode
         Serial.println("Logging is OFF.");
         Serial.println(" ");
      } // endif/else logging 
   
    for (int x = 0; x < Seconds_dwell_after_detect*2; x++) { // DoorBell dectected. Pause and LED flash for visual acknowledgement
      digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED
      Serial.println("Doorbell dectected,  Now in BLINK Loop....");
      delay(500);   } // endfor DoorBell Dwell loop  
       
  }   // end doorbell A0 pressed
}  // end of endless loop
-----
That's it and thanks for stopping by!!!

Sunday, March 25, 2018

Ham Solo: ESP8266 Based Amateur Radio Simplex Confirmation Project

-----
Note:  As presented this project requires a FCC Amateur Radio license.  Amateur Radio is about experimentation.   Even still you must be versed in the band plan and stay away from local repeater stations, stay in accordance to FCC Amateur Radio rules such as 97.201(a), 97.201(b), 97.213(a), 97.215, 97.3(a)(7), and likely a few others.  Even after following all those rules, nobody likes to hear a bunch on random DTMF tones so keep your transmissions short and infrequent.
-----
Most Amateur (or ham) radio operators have wondered how or if their signal is getting received.  After getting a YES/NO answer they may want to decrease power, try a different antenna set up, or change location.  The challenge with this can be a willing participant on the receive side that has promised to remain perfectly still and listen for hours.  If you have a friend or XYL willing to do that then consider yourself fortunate.  For all the others there is this project.
-----
The rig is pretty straight forward and explained in the image above.
   - From the field a DTMF tone is transmitted on a frequency that "the shack" is tuned to.
   - If the radio in the shack hears the DTMF tone it is decoded with this module.
   - Code running on an ESP8266 turns the decoded tone "to English" and sends a SMS text message via IFTTT.
   - If the shack received everything you will get a confirming QSL SMS on your smartphone.
-----
It's all quick and simple.  It takes only a 250 mSec or so transmission time and a delay of maybe 2 seconds to get the confirming QSL SMS.  The short video below gives a good explanation:

-----
Want to build your own?  No problem.
   1st:  Get a FCC Amateur Radio license; it's not hard and is an extremely interesting hobby.
   2nd: Buy some radios (costs range from $30 to infinity).
   3rd:  Buy the DTMF module and an ESP8266.
   4th:  Set up a free IFTTT account for the SMS texting.
   5th:  Hook it all up as shown in the image at the top of this page.
   6th:  Load the source code below into your ESP8266 (you will need the Arduino IDE).
   7th:  Be respectful of the rules and test away.
-----
Before showing the ESP8266 source code here's a short video using 5 of the 8 channels on the Tektronix MSO5 (which is bad ass!!!) to monitor the signals coming off the DTMF module.
-----
The (short/simple) ESP8266 source code is below.  If you duplicate the project or this motivates you to get your FCC Amateur Radio license let us know:
-----
/*
 *  HamControl
 *  MARCH2018
 *  WhiskeyTangoHotel.Com
 *  
 *  This project as described requires a FCC Amateur Radio License!!!!!! 
 *  Be aware of all FCC license and regulation retrictions before use!!!
 *  Follow local band plan and Federal regulations!!!!!!!!!!!!!!!!!!!!!!
 *  Go ahead and get your license.  It's a fun hobby.  See: http://www.arrl.org/getting-licensed
 * 
 *  HamControl:
 *  Use DTMF Tones to control ESP8266 via ham radio.
 *  Primary application was to confirm simplex signal Tx/Rx for antenna testing.
 *  When a DTFM is detected a SMS is sent your cell phone for field comfirmation.
 * 
 *  For DTMF DeCode: SMAKN® XD-61 MT8870 (~$10 USD)  
 *  NOTE:  For Baofeng set volume to ~80%
 * 
 *  uC setting for Ardunio IDE (ESP8266 with WiFI)
 *  NoderMCU 1.0 (ESP-12E Module), 80MHz, 921600, 4M (3M SPIFFS)
 * 
*/

// For the Wireless
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

// WiFi Connection Information
const char* ssid = "Your-SSID-Here";           // PRIVATE: Enter your personal setup information.
const char* password = "Your-WiFi-PW-Here";   // PRIVATE: Enter your personal setup information.
ESP8266WebServer server(80);

// IFTTT Information for WebHook widget
String MAKER_SECRET_KEY = "Your-IFTTT-PrivateKey-Here";   // PRIVATE: Enter your personal setup information. Your IFTTT Webhook key here
String TRIGGER_NAME_SMS = "HamControl_SMS";           // this is the Maker IFTTT trigger name to send SMS if a DTFM tone is recieved.
const char* host = "maker.ifttt.com";
String url_SMS;       // url that gets built for the IFTTT Webhook sending SMS DTMF recieved confirmation.
String DTMF_String;   // used to covert numbers and *,#,A,B,C,D tones to a string value.

// Define and set up some variables
int DTMF;  // What key press was sent by the ham radio.

// Define ESP8266 pins
const int led = 2;  // Blue on board LED is on PIN-D4 (GPIO2) for this NoderMCU 1.0 ESP8266.  Blink it between reads
// Define pins from the DTMF Decoder to the ESP8266 GPIO
const int Q1 = 12;  // PIN-D6 SILK SCREEN LABEL
const int Q2 = 13;  // PIN-D7 SILK SCREEN LABEL
const int Q3 = 15;  // PIN-D8 SILK SCREEN LABEL
const int Q4 = 5;   // PIN-D1 SILK SCREEN LABEL
const int STQ = 4;  // PIN-D2 SILK SCREEN LABEL

// Program control variables
int logging = 1; // If 1 then send SMS.  Any other value (0) turns it off.  For debug, typically would be set = 1

void setup(void){ // This setup code is run once.
  pinMode(led, OUTPUT);     // set up the onboard Blue LED pin as an output.
  pinMode(Q1, INPUT);       // Q1-4 are the output signals from the DTFM IC
  pinMode(Q2, INPUT);       // that are feed into and read by the ESP8266
  pinMode(Q3, INPUT);
  pinMode(Q4, INPUT); 
  pinMode(STQ, INPUT);      // STQ is high when DTFM tone is detected
 
  Serial.begin(115200);     // turn on the serial monitor for debug
 
  // Is the WiFi working?
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Trying to connect to ");
    Serial.print(ssid);
    Serial.print(" on ");
    Serial.print(WiFi.localIP());
    for (int x = 0; x < 20; x++) { // 
      digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is trying to WiFi connect
      //Serial.println("Server Start blink loop....");
      delay(50);  
    } // endfor WiFi blink connect
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
    Serial.println(" ");
  }

  // Use WiFiClient class to create TCP connections for WiFi logging
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");  // Boo!!!
    return;
  }

  server.begin();
  Serial.println("HTTP server started");  // Woo Hoo!!!
  Serial.println(" ");
   
  Serial.println("Entering HamControl main loop. ");
  Serial.println("Waiting for DTMF... ");
  Serial.println("-------------------------------------");
}

void loop(void){    // Loop this code section until hell freezes over

  // The blue onboard LED will blink between to show prog is 'running'.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
   
  if (digitalRead(STQ) == HIGH) {  // If it HIGH then DTFM detected.  Let's get to work.
      Serial.println("DTMF Detected!!!");
      DTMF_String = "Could_not_decode_DTFM!";  // Should be overwritten below, but just in case Mr Murphry shows up...
     
      // Convert the four bit (Q1-Q4 read) to decimal values 1-9 to match the button pushed
      // 0=10, *=11, #=12, A=13, B=14, C=15, D=0
      DTMF = (digitalRead(Q4) * 8) + (digitalRead(Q3) * 4) + (digitalRead(Q2) * 2) + (digitalRead(Q1) * 1);
      DTMF_String = String(DTMF);
      if (DTMF == 10) {
          DTMF_String = "0";
      }
      if (DTMF == 11) {
          DTMF_String = "*";
      }
      if (DTMF == 12) {
          DTMF_String = "HASH";
      }
      if (DTMF == 13) {
          DTMF_String = "A";
      }
      if (DTMF == 14) {
          DTMF_String = "B";
      }
      if (DTMF == 15) {
          DTMF_String = "C";
      }
      if (DTMF == 0) {
          DTMF_String = "D";
      }     
      Serial.println("Key pressed: " + DTMF_String);     
             
      if (logging == 1) { // is SMS logging turned on?
          // Set up IFTTT Webhook Channel to send the SMS. 
          // Use WiFiClient class to create TCP connections for IFTT SMS
          WiFiClient client;
          const int httpPort = 80;
          if (!client.connect(host, httpPort)) {
            Serial.println("connection failed");
            return;
          }
         
          // Build the IFTTT SMS url
          url_SMS = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_SMS + "/with/key/" + MAKER_SECRET_KEY+ "?value1=" + DTMF_String;
          Serial.println(" ");
          Serial.println("SMS payload to IFTTT.");
          Serial.println(url_SMS);
          client.print(String("POST ") + url_SMS + " HTTP/1.1\r\n" +
          "Host: " + host + "\r\n" +
          "Connection: close\r\n\r\n");
          Serial.println(" ");
          Serial.println("Logging is ON.");
          delay(1000);   // pause for webservices and to prevent double tap
          // and fast blink the blue onboard LED to show DTMF was recognized
          for (int x = 0; x < 100; x++) {
              digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED
              delay(50);  
          } // endfor DFTM delay/blink                
          
      } else {
       
          Serial.println("Logging is OFF.");
          Serial.println(" ");
      } // endif/else logging 

      Serial.println("-------------------------------------");
      Serial.println("Waiting for DTMF... ");
           
  } //Endif STQ High?
  delay(250); // Delay for flashing on board BLUE program running status LED
   
} // void loop until hell freezes over
-----
73!

Thursday, August 24, 2017

ToF Laser to Monitor Cat Food Levels


 -----
We live in great times.  There was once a day when the only way to determine if the cat feeder needed more kibble was to actually look at it with your own eyes like some Neanderthal.  Thankfully technology and the magical world of IoT has changed all of that.
----
For this project we use a WiFi enable ESP8266 and a STMicro VL53L0X ToF Sensor mounted to a breakout board.  If you don't find a need to measure feline food consumption the project still provides Arduino code that can be extremely useful for your other IoT projects:
  • Logging data to a Google Drive Spreadsheet (via IFTTT)
  • Logging data to AT&T's M2X machine to machine servers (think nice graphs)
  • Sending SMSs to your mobile device (via IFTTT)
All of the above services are free but; of course, you will need to establish an account if you do not have on.
----
What's happening?
The ESP8266 runs in Arduino mode (source code below) in an endless loop.  Every hour it polls the VL53L0X ToF Sensor mounted on the lid of the cat food feeder.
-----
Since we know how many centimeters the food is from the ToF sensor at full and at empty we are able to scale those values and report/log "percent full" status.  Those values are posted to a Google Drive Spreadsheet and to AT&T's M2X machine to machine servers for logging.  If the food level is considered CRITICALLY LOW a SMS message goes out to our mobile device.  Just to increase the geek factor, CRITICALLY LOW alerts are also displayed on our Pebble watch.
----
The Google Drive Spreadsheet looks like this:
-----
Here is the bad ass AT&T M2X machine to machine server graph (note the increase after we filled the feeder):
-----
The IFTTT SMS alerts are sent if the rig determines food levels critically low:

-----
So..... How's it done?  You will need these:
Easy; hook it up like this:
 And it will look something like this:
-----
 Mount it to the cat feeder and you end up with this:

-----
Now all that is left is to copy/paste the code below into the Arduino IDE.  Upload it to the ESP8266 and your cats will never go hungry again!
-----
/*
 *  AUG2017
 *  STMicro VL53L0X ToF Sensor for
 *  Cat Food Level Monitoring
 *  WhiskeyTangoHotel.Com
 * 
 *  Logs % full values to:
 *    Google Drive (as an appending spreadsheet)
 *    AT&T M2X for historical graphing
 *    Send SMS to cell phone if level condition is RED/CRITICAL
 * 
 *  uC setting for Ardunio IDE
 *  NoderMCU 1.0 (ESP-12E Module), 80MHz, 921600, 4M (3M SPIFFS)
 * 
*/

// For the STMicro VL53L0X ToF Sensor
// I2C SDA to ESP8266 Pin D2.  SCL to ESP8266 Pin D1
#include "Adafruit_VL53L0X.h"   // Thanks again ADAFRUIT!!!
Adafruit_VL53L0X lox = Adafruit_VL53L0X();

// For the Wireless
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

// WiFi Connection Information
const char* ssid = "YourNetworkHere";    // PRIVATE: Enter your personal setup information.
const char* password = "YourNetworkPasswordHere"; // PRIVATE: Enter your personal setup information.
ESP8266WebServer server(80);

// IFTTT Information for WebHook widget
String MAKER_SECRET_KEY = "YourIFTTTCodeHere"; // PRIVATE: Enter your personal setup information. Your IFTTT Webhook key here
String TRIGGER_NAME_google_drive = "Cat_Food";  // this is the Maker IFTTT trigger name for google drive spreadsheet logging
String TRIGGER_NAME_M2X = "cat_food_mx";   // this is the Maker IFTTT trigger name for M2X logging
String TRIGGER_NAME_SMS = "CriticalFoodLevel_SMS";  // this is the Maker IFTTT trigger name to send SMS if low is level is CRITICAL.
const char* host = "maker.ifttt.com";
String url_google_drive;  // url that gets built for the IFTTT Webhook logging to google drive spreadsheet
String url_M2X;   // url that gets built for the IFTTT Webhook logging to AT&T M2X service
String url_SMS;   // url that gets built for the IFTTT Webhook sending SMS if food level is critical

// Define and set up some variables
float Range_inches;  // How far the sensor is from the food at time of reading.  Sensor is on roof of feeder.
float Min_level = 5.0;   // Distance in inches before low food alarm level.  Food is far from sensor on feeder roof
float Max_level = 0.5;   // Distance in inches from sensor for full feeder level.  Food is close to sensor on feeder roof
float Percent_full;  // How full in xx.x% is the food based on the Min/Max_levels defined above
float Caution_alarm = 35.0;  // at xx.x% food level is considered low.  String Status YELLOW
float Critical_alarm = 25.0;  // at xx.x% food level is considered critically low. String Status RED
String Status = "***_Starting_with_Caution_at:_" + String(Caution_alarm) + "%_and_CRITICAL_at:_" + String(Critical_alarm) + "%";  // Update to Out of Range, NORMAL, LOW, CRITICAL, etc. "spaces" will error IFTTT Webhook; use "_"
int Run_number;  // how many times the sensor has been read

// Output pins
const int led = 2;  // Blue on board LED is on PIN2 for this NoderMCU 1.0 ESP8266.  Blink it between reads

// Program control variables
int Seconds_between_posts = 60 * 60;  // how often to post the results of the sensor read. NOT EXACT due to post delays, Sensor reads, LED flashing, etc.
int logging = 1; // If 1 then log to cloud.  Any other value (0) turns it off.  ESP8266 "Start/Restart" message is always logged. 


void setup(void){  // This is run once.
  pinMode(led, OUTPUT);  // set up the onbaord LED pin as an output. 
  Serial.begin(115200);  // turn on the serial monitor for debug

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }

  // Is the ToF sensor connecting via I2C?
  Serial.println("STMicro VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X!!!"));
    while(1);
  }
  // power
  Serial.println(F("VL53L0X Passed... \n\n"));
 
  // Is the WiFi working?
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("Trying to connect to ");
    Serial.print(ssid);
    Serial.print(" on ");
    Serial.print(WiFi.localIP());
    Serial.println(".");
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
    Serial.println(" ");
  }

  // Use WiFiClient class to create TCP connections for WiFi logging
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");  // Boo!!!
    return;
  }

  server.begin();
  Serial.println("HTTP server started");  // Woo Hoo!!!

  // Write to Google Sheet via IFTTT Maker channel that the ESP8266 has started/restarted
  // Trigger the IFTTT Webhook Channel to update a Google sheet with the activity of the server starting/restarting
  // This can help log power outs, etc.  For first run we defined String Status for identify a startup condition.
  // Create the request for IFTTT google drive
  url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
  Serial.println("Status: " + Status);
  Serial.println(" ");
   
  // This sends the request to the IFTTT server
  client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
  "Host: " + host + "\r\n" +
  "Connection: close\r\n\r\n"); 
  delay(500);  // Delay for web traffic; maybe not required. 
}

void loop(void){
  // Loop forever.  Read the sensor and post based on the delay values set above.
  // The blue onboard LED will blink between ToF reads.
 
  // Read the ToF.  Distance in mm  returned. 
  for (int x = 0; x < 10; x++) { // Quick toggle blue on  board LED to show measurement being taken.
    digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is running
    delay(100);    }  // endfor quick toogle Blue LED
  VL53L0X_RangingMeasurementData_t measure;

  Serial.println("-------------------------------------");
  Serial.println("Reading a measurement... ");
  lox.rangingTest(&measure, false);
  // Convert to inches because the USA, for some reason, doesn't want to adopt the metric system...
  Range_inches = measure.RangeMilliMeter/25.4;
  Run_number = Run_number + 1;

  // Scale and normalize the Min Max levels to 0% to 100%.  Clip the range in case of a the Max fill limit was exceeded or a misread.
  Percent_full = ((Range_inches - Min_level) / (Max_level - Min_level)) * 100.0;
  if (Percent_full > 100) {
    Percent_full = 100.00;
  }
  if (Percent_full < 0) {
    Percent_full = 0.0;
  }

  //Serial.println(String(Range_inches));  // Debug use
     
  // Is the ToF Sensor reading 'anything' for a distance?
  if (Range_inches > 100 ) {  // Something's weird.  Ranging error.  The ToF sensor is NOT over 100 inches fron the food. EVER!!!
      Status = "Run:" + String(Run_number) + "__ERROR:_***_Out_of_Range_***";
  } else {  // ToF made a successful reading so log the food level   
    if (Percent_full >= Caution_alarm) {  // above CAUTION LEVEL, All's good
      Status = "Run:" + String(Run_number) + "___GREEN---GOOD";
    } // endif GREEN---GOOD
 
    if (Percent_full < Caution_alarm && Percent_full > Critical_alarm) {  //  CAUTION Zone, YELLOW---REFILL_SOON
      Status = "Run:" + String(Run_number) + "___~~~YELLOW---REFILL_SOON~~~";
    } // end if YELLOW---REFILL_SOON"
 
    if (Percent_full <= Critical_alarm) {  //  CAUTION Zone, RED---REFILL_ASAP"
      Status = "Run:" + String(Run_number)+ "___!!!_RED---REFILL_ASAP_!!!";
      if (logging == 1) { // is logging turned on? Maninly for debug...  Typically would be set = 1
        // Set up IFTTT Webhook Channel to send the SMS. 
        // Use WiFiClient class to create TCP connections for IFTT SMS
        WiFiClient client;
        const int httpPort = 80;
        if (!client.connect(host, httpPort)) {
          Serial.println("connection failed");
          return;
        }     
        url_SMS = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_SMS + "/with/key/" + MAKER_SECRET_KEY+ "?value1=" + String(Percent_full);
        Serial.println("Critical Level: Sending SMS with payload:.");
        Serial.println(url_SMS);
        Serial.println(" ");
        client.print(String("POST ") + url_SMS + " HTTP/1.1\r\n" +
        "Host: " + host + "\r\n" +
        "Connection: close\r\n\r\n");
        //Serial.println("GOOGLE DRIVE URL:");
        //Serial.println(url_google_drive);
        delay(500);   // pause for webservices   
      }         
    } // endif RED---REFILL_ASAP
     
  }

  // Serial print to the monitor for debug
  Serial.println(String(Range_inches) + " inches down / " + String(Percent_full) + "% full");
  Serial.println("Status: " + Status);
  // Create the request for IFTTT Google Drive and M2X updates
  url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Percent_full) + "%" + "&value2=" + Status;
  url_M2X = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_M2X + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Percent_full);
 
  // This sends the request to the IFTTT server.
  //Serial.println("Requesting URL...");   // debug
  //Serial.println(url);   // debug
  if (logging == 1) { // is logging turned on? Maninly for debug...  Typically would be set = 1
    //Serial.println("Logging is ON."); 
    // Set up IFTTT Webhook Channel to update a Google sheet with the activity. 
    // Use WiFiClient class to create TCP connections for IFTT Webhook logging
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;
    }     
    client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
    "Host: " + host + "\r\n" +
    "Connection: close\r\n\r\n");
    Serial.println(" ");
    Serial.println("IFTTT url payload to Google Drive:");
    Serial.println(url_google_drive);
    Serial.println(" ");
    delay(500);   // pause for webservices
 
    // Set up IFTTT Maker Channel to update a AT&T M2X Server with the activity. 
    // Use WiFiClient class to create TCP connections for IFTT Webhook logging
    //WiFiClient client;
    //const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;     }     
    client.print(String("POST ") + url_M2X + " HTTP/1.1\r\n" +
    "Host: " + host + "\r\n" +
    "Connection: close\r\n\r\n");
    Serial.println("IFTTT url payload for M2X:");
    Serial.println(url_M2X);
   
  } else {
     Serial.println("Logging is OFF.");
  } // endif/else logging 
 
  for (int x = 0; x < Seconds_between_posts; x++) { // Delay for next measurement.
    digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is running
    delay(1000);   } // endfor delay for read measurement
}
-----
Thanks and check out our other stuff!!!