2019/01/12

Voice control with Google home and Arduino (3/3)

*** adafruit.io parameter changed! Please change in the code accordingly or the code below will not work! 2019/07/07 ***

  1. In the fingerprint setting, find this line and update the string as below:
    const char* fingerprint = "77 00 54 2D DA E7 D8 03 27 31 23 99 EB 27 DB CB A5 4C 57 18";
  2. In the verifyFingerprint(), add two lines before !client.connect(host, AIO_SERVERPORT))
    Serial.printf("Using fingerprint '%s'\n", fingerprint);
    client.setFingerprint(fingerprint);



    Continue from Part 2

    This is the part 3 of the "Voice control with Arduino and Google Home Mini" tutorial. This section primarily explain how the program on ESP8226 worked.



    See the demo below:



    Here are the URL links about this tutorial, totaling 3 sections:

    Source code

    Please accquire source code from Github:
    https://github.com/stonez56/GoogleMini_NodeMCU_IFTTT_Adafruit

    Section 1

    This section of code is basically define relay pin numbers and status variables. See the comment in code that pin 13 is actually NodeMCU pin D7. You may see the NodeMCU ping mapping from this article.


    // Relay settings
    #define relay2Pin 13 //NodeMCU pin D7
    #define relay1Pin 15 //NodeMCU pin D8
    int relay1Status = 0; //switch of the relay; either 0=off or 1=on
    int relay2Status = 0; //switch of the relay; either 0=off or 1=on
    

    Section 2

    This section is the basic settings, from Wi-Fi SSID and password to your Adafruit.IO user names and AIO_KEY that I reminded you to make copy is needed here. Exchange all the information below with your own for this program to work.
    There are 4 items needs to be changed with your data:

    • WLAN_SSID
    • WLAN_PASS
    • AIO_USERNAME
    • AIO_KEY
    /***************************************************
      Adafruit MQTT Library ESP8266 Adafruit IO SSL/TLS example
      Must use the latest version of ESP8266 Arduino from:
        https://github.com/esp8266/Arduino
      Works great with Adafruit's Huzzah ESP board & Feather
      ----> https://www.adafruit.com/product/2471
      ----> https://www.adafruit.com/products/2821
      Adafruit invests time and resources providing this open source code,
      please support Adafruit and open-source hardware by purchasing
      products from Adafruit!
      Written by Tony DiCola for Adafruit Industries.
      SSL/TLS additions by Todd Treece for Adafruit Industries.
      MIT license, all text above must be included in any redistribution
     *****************************************/
    #include 
    #include "Adafruit_MQTT.h"
    #include "Adafruit_MQTT_Client.h"
    
    /************* WiFi Access Point *****************/
    
    #define WLAN_SSID       "Your_HOME_SSID"
    #define WLAN_PASS       "Your_HOME_SSID_PASSWORD"
    
    /************* Adafruit.io Setup *****************/
    
    #define AIO_SERVER      "io.adafruit.com"
    #define AIO_SERVERPORT  8883  // 8883 for MQTTS sercure, 1883 for non-Secure
    #define AIO_USERNAME    "stonez56"
    #define AIO_KEY         "4nnxxnnxxnnxxn88223"
    

    Section 3

    In Line 62, the code set up a subscription at Adafruit MQTT service Light 1 to get real time updated value.  "/feeds/light-1" is the subscription name and it must be the same with the one you defined at Adafruit "Feeds".

    In Line 63, it's reserved for future program extension to control RGB color light. 

    In Line 51, it's a MQTT publish feature that allows you to upload message from ESP8226 to Adafruit.IO MQTT server.  You might need it for other projects. 

    /************ Global State (you don't need to change this!) ******************/
    
    // WiFiFlientSecure for SSL/TLS support
    WiFiClientSecure client;
    
    //WiFiClient for non-secure
    //WiFiClient client;
    
    // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
    Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
    
    // io.adafruit.com SHA1 fingerprint
    const char* fingerprint = "AD 4B 64 B3 67 40 B5 FC 0E 51 9B BD 25 E9 7F 88 B6 2A A3 5B";
    
    /****************************** Feeds ***************************************/
    
    // Setup a feed called 'test' for publishing.
    // Notice MQTT paths for AIO follow the form: /feeds/
    //Adafruit_MQTT_Publish light_color = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/light-color");
    //Adafruit_MQTT_Publish light_1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/light-1");
    
    /*************************** Sketch Code ************************************/
    // Bug workaround for Arduino 1.6.6, it seems to need a function declaration
    // for some reason (only affects ESP8266, likely an arduino-builder bug).
    void MQTT_connect();
    void verifyFingerprint();
    
    //set up a feed called 'light_1' / 'light_color' for subscribing to changes
    Adafruit_MQTT_Subscribe light_1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/light-1");
    Adafruit_MQTT_Subscribe light_color = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/light-color");
    
    

    Section 4

    This part is Arduino setup function. Basically, this setup Arduino serial monitor output and connect ESP8226 to your Wi-Fi network, as well as subscribe to MQTT services. 

    void setup() {
      Serial.begin(115200);
      delay(10);
    
      pinMode(relay1Pin, OUTPUT);
      pinMode(relay2Pin, OUTPUT);
    
      Serial.println(F("Home MQTT Light Control System"));
    
      // Connect to WiFi access point.
      Serial.println(); Serial.println();
      Serial.print("Connecting to ");
      Serial.println(WLAN_SSID);
    
      delay(1000);
    
      WiFi.begin(WLAN_SSID, WLAN_PASS);
      delay(2000);
    
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println();
    
      Serial.println("WiFi connected");
      Serial.print("IP address: "); Serial.println(WiFi.localIP());
    
      // check the fingerprint of io.adafruit.com's SSL cert
      verifyFingerprint();
    
      //Subscribe to Adafruit Feed!
      mqtt.subscribe(&light_1);
      mqtt.subscribe(&light_color);
    
    }
    

    Section 5

    The Arduino loop keeps checking with Adafruit server to see if there were new messages. If there were new messages, then further check the subscription name. If the subscription name is equal to light-1, then check the light-1 feed_lastread content. If feed_lastread is ON or OFF then, the program call switchRelay function to either turn on light or turn off light. 

    This part also check the further project extension for color-light status.

    uint32_t x = 0;
    
    void loop() {
    
      String feed_lastread;
      // Ensure the connection to the MQTT server is alive (this will make the first
      // connection and automatically reconnect when disconnected).  See the MQTT_connect
      // function definition further below.
      MQTT_connect();
    
    
      Adafruit_MQTT_Subscribe *subscription;
      while ((subscription = mqtt.readSubscription(5000))) {
    
    
        if (subscription == &light_1) {
    
          Serial.print(F("Light-1:"));
          Serial.println((char *)light_1.lastread);
          feed_lastread = (char *)light_1.lastread;
          feed_lastread.trim(); //
          // Serial.println("Light 1:" + feed_lastread); //for verifying the varialble
          // *** NOTICE: adafruit.io publishes the data as strings, not numbers!!!
          if (feed_lastread == "ON") {
            switchRelay(2, 1);
          }
          if (feed_lastread == "OFF") {
            switchRelay(2, 0);
          }
        }
    
    
        if (subscription == &light_color) {
          Serial.print(F("Color-Light:"));
          Serial.println((char *)light_color.lastread);
          feed_lastread = (char *)light_color.lastread;
          feed_lastread.trim(); //
          // Serial.println("Color Light:" + feed_lastread); //for verifying the variable
          // *** NOTICE: adafruit.io publishes the data as strings, not numbers!!!
          if (feed_lastread == "ON") {
            switchRelay(1, 1);
          } else if (feed_lastread == "OFF") {
            switchRelay(1, 0);
          } else {
            colorLightFunction(feed_lastread.toInt());
          }
        }
      }
    

    Section 5

    This is the SwitchRealy function, it either turn off or turn on the relay module and print out the current status on Arduino serial monitor. 

    /* This turn on/off relay switch
    
    */
    void switchRelay(int relay, int stat) {
    
      if (relay == 2) { //this is light-1; 
        if (stat == 0) {
          digitalWrite(relay2Pin, LOW);
          Serial.println(F("Relay off"));
        }
        if (stat == 1) {
          digitalWrite(relay2Pin, HIGH);
          Serial.println(F("Relay on"));
        }
      }
      if (relay == 1) { //this is color-light; 
        if (stat == 0) {
          digitalWrite(relay1Pin, LOW);
          Serial.println(F("Relay off"));
        }
        if (stat == 1) {
          digitalWrite(relay1Pin, HIGH);
          Serial.println(F("Relay on"));
        }
      }
    }
    
    

    Section 6

    This part is all directly from Adafruit sample code. Just keep them here.

    void verifyFingerprint() {
    
      const char* host = AIO_SERVER;
    
      Serial.print("Connecting to ");
      Serial.println(host);
    
      if (! client.connect(host, AIO_SERVERPORT)) {
        Serial.println("Connection failed. Halting execution.");
        while (1);
      }
    
      //  if (client.verify(fingerprint, host)) {
      //    Serial.println("Connection secure.");
      //  } else {
      //    Serial.println("Connection insecure! Halting execution.");
      //    while(1);
      //  }
    
    }
    
    // Function to connect and reconnect as necessary to the MQTT server.
    // Should be called in the loop function and it will take care if connecting.
    void MQTT_connect() {
      int8_t ret;
    
      // Stop if already connected.
      if (mqtt.connected()) {
        return;
      }
    
      Serial.print("Connecting to MQTT... ");
    
      uint8_t retries = 30;
      while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
        Serial.println(mqtt.connectErrorString(ret));
        Serial.println("Retrying MQTT connection in 5 seconds...");
        mqtt.disconnect();
        delay(5000);  // wait 5 seconds
        retries--;
        if (retries == 0) {
          // basically die and wait for WDT to reset me
          while (1);
        }
      }
    
      Serial.println("MQTT Connected!");
    }
    

    The end.

    2019/01/06

    Voice control with Google home and Arduino (2/3)

    Continue from Part 1

    This is the part 2 of the "Voice control with Arduino and Google Home Mini" tutorial. This section primarily explain how to setup the Adafruit MQTT and IFTTT related services.

    This is the demo of this tutorial:


    Step 1: Adafruit IO setup 

    Watch this video to see how I setup the Adafruit IO MQTT for this tutorial. This video has English Closed Captions, if you needed it.






    • If you would like learn more about MQTT, please visit Adafruit website to see it's great tutorials. Highly recommended for anyone not familiar with this technology to read. 

    AIO Key

    • AIO Key is your personal key that allows your Arduino ESP8226 to talk to Adafruit IO MQTT server. Keep it safe and not to share with others. 
    • Log in to your account and Click "AIO Key" on the left menu.
    • Write down the AIO Key (You will need this in Arduino to connect to Adafruit) See below:
    • Click on the "View AIO Key" button to see your AIO Key (shown below)








    Write down the AIO Key for Arduino ESP2886 coding use later. 

    Step 2: Setup IFTTT Applet

    • IFTTT is stands of "If This Than That". If you were not familiar with IFTTT, you could checkout more information from these resources:
      1. What's IFTTT?
      2. How to setup IFTTT?
    • Here is how I setup my IFTTT Applet for this tutorial. This video has English Closed Captions, if you needed it.

    Step 3: Check Adafruit and IFTTT setup

    • Turn on Google Home Mini and say "Turn on light one".
    • Install IFTTT App on your smartphone, if you used a smartphone rather than a Google Home.
    • Google assistant should reply "Sure, light one on".
    • From the Adafruit feeds page, you should see the data showing up there immediately reflecting the message you sent; in red square below.
    • Then, your setup is successful!

    The 2nd part is completed. In the next section, I will show you all the physical setup and the Arduino codes to make this project work.


    Troubleshooting:


    Until then, see you next time!

    Continue to read: Part 3 Arduino 程式解說 (coming soon)


    2019/01/01

    Voice control with Google Home and Arduino (1/3)

    Preface

    After received my Google Home Mini from Walmart, my family and I are really enjoyed and satisfied with the voice features and sound quality. Voice control lighting is always on my Arduino DIY list. After I received all the components, I went ahead and made this project during my X'mas holiday. The Google Home Mini I bought came with a Chromecast in a Smart TV kit package at price of USD$45 during holiday sales. What a bargain! 

    * Photo from Walmart

    Here are the URL links about this tutorial, totaling 3 sections:


    Goal

    Simply say "Ok Google, turn Light One On or Off" to Google Home Mini and it does the job!  I intended to add "One" there, so I might have the 2nd or 3rd lights that I could control in...hope not in the distant future. :)

    See the demo below:


    How does it work?

    Programming Steps to show you the working flow

    1. Your voice command send to IFTTT through Google Home Mini 
    2. IFTTT Applets engage Google assistance service and inteprete the voice command into text and send to Adfruit.IO MQTT service
    3. MQTT service received the message(from Google home to IFTTT) and based on the Adafruit "Feeds" setting to store the received message on the MQTT server.
    4. Adruino ESP8266 at home was programmed to subscribe new message from Adafruit. As soon as the Adafruit MQTT server has updated message, Adafruit server push the message back to Arduino ESP8226.
    5. ESP8226 recevie the message and act accordingly to either trigger the relay module.
    6. If the messae is "ON" then, ESP8226 turn on light by swith relay module on. Otherwise, the message is "OFF", then trun off light by swith relay module off.

    !!EXTRA CAUTION!!

    SAFETY is first priority! This project involves 110V AC which it is quite dangerous if not handled carefully! Please turn the main power source off before all the AC related connections. Double and triple check for short and correct connections before turn back on AC! I'm just to show you how I made this project and not responsible for anything happened to you or your family and properties in case if there is an accident. 

    Components Needed

    • NODEMCU ESP8226 * 1
    • 10A 110v/250v AC Relay * 1
    • Wall plug outlet * 1
    • Wires for Arduino connection * 4 or 5
    • Wires for Wall plug connection * 3

    Schematic 

    I drew this illustration below to show you how did I connected all components together.



    Connections:

    • ESP8226 D7 to Relay IN
    • ESP8226 GDN to Relay GDN
    • ESP8226 3.3V to Relay VCC
    • Relay NC(Normally Close) to AC Plug outlet top end (refer to above illustration)
    • Relay C(Common) to AC 110V 
    • AC Plug outlet bottom end to AC 110V GND
    • AC Plug ground (not used in this project, my old house does not have this)
    That's all for this section. Next time, I will show you how to setup Adafruit and IFTTT. They are the most important parts of this project. Until next time, see you!

    Please Continue to read: Setting software - Part 2 of this tutorial