Thursday, April 6, 2017

Home Automation with the Arduino and the Amazon Echo Part 2

In this video series we look at how to use Arduino (ESP8266) and the Amazon Echo to do voice controlled home automation.






Link to project material on GitHub: https://github.com/ForceTronics/Arduino_Echo_Home_Automation

//************************************ESP8266 Arduino code*********************
/*
 This sketch was created for a video series called Home Automation with the Arduino and the Amazon Echo Part 2 
 That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to use or modify at your own risk
 Note that this code was leveraged from a Sparkfun example on using their cloud service Phant
 */

// Include the ESP8266 WiFi library
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>

//Set your network name and password
const char WiFiSSID[] = "NetworkName"; //your wifi network name goes here
const char WiFiPSK[] = "NetworkPassword"; //your wifi password goes here

//define constants for pin control and node number
const int light = 4; //NodeMCU GPIO 4 pin is connected to the WiFi AC Switch control
const char parseKey[] = "stamp"; //This is used to parse through data from Phant to find light setting

//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char gPublicKey[] = "YourPublicKey"; //your phant public key goes here
const char gPrivateKey[] = "YourPrivateKey"; //your phant private key goes here

//specify the rate that you post data to cloud
const unsigned long postRate = 1000;
unsigned long lastPost = 0;

void setup() 
{
  initHardware(); //setup arduino hardware
  connectWiFi(); //Connect your WiFi network
  digitalWrite(LED_BUILTIN, HIGH); //turn on LED
}

void loop() 
{ //loop until it is time to post data to phant cloud, variable "postRate" defines the interval in milli seconds
  if (lastPost + postRate <= millis())
  {
    if (getFromPhant()) lastPost = millis(); //get data from Phant
    else lastPost = millis(); //Even if we fail delay whole cycle before we try again
  }
}

//function used to connect to WiFi network
void connectWiFi()
{
  byte ledStatus = LOW;
  // Set WiFi mode to station (as opposed to AP or AP_STA)
  WiFi.mode(WIFI_STA);
  // WiFI.begin([ssid], [passkey]) initiates a WiFI connection
  // to the stated [ssid], using the [passkey] as a WPA, WPA2,
  // or WEP passphrase.
  WiFi.begin(WiFiSSID, WiFiPSK);
  
  // Use the WiFi.status() function to check if the ESP8266
  // is connected to a WiFi network.
  while (WiFi.status() != WL_CONNECTED)
  {
    // Blink the LED
    digitalWrite(LED_BUILTIN, ledStatus); // Write LED high/low
    ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
    
    // Delays allow the ESP8266 to perform critical tasks
    // defined outside of the sketch. These tasks include
    // setting up, and maintaining, a WiFi connection.
    delay(100);
  }
}

//function that sets up some initial hardware states
void initHardware()
{
  pinMode(light, OUTPUT); //turn light off at startup
  digitalWrite(light, LOW);
}

//function that handles getting data from phant cloud
int getFromPhant()

 //Set phant data
 Phant phant(PhantHost, gPublicKey, gPrivateKey);
  
  WiFiClient client; //Create client object to communicate with the phant server

  if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
    // If we fail to connect, return 0.
    return 0;
  }

  //Get data from phant cloud
    client.print(phant.get()); 
    client.println();
   int cTrack = 0; //variable that tracks count to spell stamp
   bool match = false; //tracks when we have a match with "stamp" and we can then get control data
   int pCount = 0; //variable used to track when we have control data
   while(1) { //loop until we get data and server closes connection
    if (client.available()) { //if data is available from phant server
      char c = client.read(); //read a bite of data from server
      if(!match) { //if true than we have not found the word "stamp" so keep looking
        if(c == parseKey[cTrack]) //check if we have a character match with word "stamp"
        {
          if(cTrack == (sizeof(parseKey)-2)) match = true; //if true it means we found a match for "stamp" in data from phant cloud
          cTrack++; //iterate this count if a character match was found
        }
        else { //if true means no character match so reset count
          cTrack = 0;
        }
      }
      else { //if true it means we found a match to "stamp" and we are ready to get control data
        
        if(pCount == 1) { //if true we are at the point in the data to read control data for node oen
          int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
          if(dControl == 1 | dControl == 0) digitalWrite(light, dControl); //make sure data is a one or zer and set LED pin with it
        }
        pCount++; //iterate the parse counter
      }
    }

    // if the server's disconnected, stop the client:
    if (!client.connected()) {
      client.stop(); //stop client, if you don't have this you will create too many clients and server won't let you connect anymore
      break; //This is how we get out of the loop
    }
   }
  
  return 1; // Return success
}

  

Sunday, April 2, 2017

Home Automation with the Arduino and the Amazon Echo Part 1

In this video series we look at how to use Arduino (ESP8266) and the Amazon Echo to do voice controlled home automation.



//*******************json file for Alexa Skill*****************
{
  "intents": [
    {
      "intent": "TurnLightOn"
    },
    {
      "intent": "TurnLightOff"
    }
  ]
}

//********************java script code for Lambda Function*************************
var https = require('https') //include https

exports.handler = (event, context) => {

  try {

    if (event.session.new) {
      // New Session
      console.log("NEW SESSION") //log this for debugging
    }

    switch (event.request.type) {

      case "LaunchRequest":
        // Launch Request
        console.log(`LAUNCH REQUEST`)
        context.succeed(
          generateResponse(
            buildSpeechletResponse("Welcome to the ForceTronics Home Automation Skill, say turn light on or turn light off", true), //response for Alexa if you just call the skill without intent
            {}
          )
        )
        break;

      case "IntentRequest":
        // Intent Request
        console.log(`INTENT REQUEST`)

        switch(event.request.intent.name) { //switch statement to select the right intent
          case "TurnLightOn":
          var endpoint = "https://data.sparkfun.com/input/YourPublicKey?private_key=YourPrivateKey&lightstate=1" //https string to log data to phant phant
          https.get(endpoint, function (result) { //use https get request to send data to phant
          console.log('Success, with: ' + result.statusCode);
          context.succeed(
           generateResponse( //if you succeeded allow Alexa to tell you state of light
                buildSpeechletResponse("The light is turned on", true),
                {}
            )
          )
          }).on('error', function (err) {
            console.log('Error, with: ' + err.message);
            context.done("Failed");
          });
            break;

          case "TurnLightOff": //the turn light off intent
            var endpoint2 = "https://data.sparkfun.com/input/YourPublicKey?private_key=YourPrivateKey&lightstate=0" // phant string to set light state to off
            https.get(endpoint2, function (result) {
            console.log('Success, with: ' + result.statusCode);
            context.succeed(
                generateResponse( //Alexa response if successful
                 buildSpeechletResponse("The light is turned off", true),
                    {}
                )
            )
            }).on('error', function (err) {
            console.log('Error, with: ' + err.message);
            context.done("Failed");
            });
            break;

          default:
            throw "Invalid intent"
        }

        break;

      case "SessionEndedRequest":
        // Session Ended Request
        console.log(`SESSION ENDED REQUEST`)
        break;

      default:
        context.fail(`INVALID REQUEST TYPE: ${event.request.type}`)

    }

  } catch(error) { context.fail(`Exception: ${error}`) }

}

// builds an Alexa response
buildSpeechletResponse = (outputText, shouldEndSession) => {

  return {
    outputSpeech: {
      type: "PlainText",
      text: outputText
    },
    shouldEndSession: shouldEndSession
  }

}

//plays Alexa reponse
generateResponse = (speechletResponse, sessionAttributes) => {

  return {
    version: "1.0",
    sessionAttributes: sessionAttributes,
    response: speechletResponse
  }

}

Tuesday, March 28, 2017

How to Remove Solder Bridges

In this video we look at how to remove solder bridges from small surface mount components. When dealing with really small pins the task of removing solder bridges can seem intimidating, but as you will see in this video it is not tough at all if you have the right tools and know how for the job.



Supplies used in solder bridge tutorial

Wednesday, March 22, 2017

Reduce Noise in Your Sensor Measurements with an Active Low Pass Filter Part 3

In this three part series we look at how to design a signal conditioning circuit to increase the accuracy and resolution of your ADC sensor measurements. The signal conditioning circuit consists of a double pole active Sallen Key Low Pass Filter and a non-inverting op amp. The filter portion is meant to attenuate high frequency noise from your sensor signal to increase measurement accuracy. The amplifier portion scales the signal up to the full range of the ADC to ensure you are getting max resolution. In part 3 we test our finished LPF + Amp circuit. 




If you are interested in purchasing the circuit from the video go to forcetronics.com

You can access the Eagle files on Github at: https://github.com/ForceTronics/Salle...


Sunday, March 5, 2017

Reduce Noise in Your Sensor Measurements with an Active Low Pass Filter Part 2

In this three part series we look at how to design a signal conditioning circuit to increase the accuracy and resolution of your ADC measurements. The signal conditioning circuit consists of a double pole active Sallen Key Low Pass Filter and a non-inverting op amp. The filter portion is meant to attenuate high frequency noise from your sensor signal to increase measurement accuracy. The amplifier portion scales the signal up to the full range of the ADC to ensure you are getting max resolution. In part 2 we do the PCB layout of our circuit using Eagle CAD software.





You can access the Eagle files on Github at: https://github.com/ForceTronics/Sallen-Key-Low-Pass-Filter-Design/tree/master


Monday, February 27, 2017

Reduce Noise in Your Sensor Measurements with an Active Low Pass Filter Part 1

In this three part series we look at how to design a signal conditioning circuit to increase the accuracy and resolution of your ADC measurements. The signal conditioning circuit consists of a double pole active Sallen Key Low Pass Filter and a non-inverting op amp. The filter portion is meant to attenuate high frequency noise from your sensor signal to increase measurement accuracy. The amplifier portion scales the signal up to the full range of the ADC to ensure you are getting max resolution.




You can find the online filter calculator used in part one at this link: http://sim.okawa-denshi.jp/en/OPseikiLowkeisan.htmk

You can access the LTspice file on Github at: https://github.com/ForceTronics/Sallen-Key-Low-Pass-Filter-Design/tree/master

Sallen-Key Low Pass Filter Circuit with Amplifier Stage in LTspice

Wednesday, February 1, 2017

Accessing Hidden Pins on the Arduino Zero

In this video we look at how you can access six additional digital pins from your Arduino Zero board. We also take a look at some flexible wired communication options you can take advantage of on the Arduino Zero.






Link to Adafruit tutorial referenced in the video: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-serial

Path on Windows to get to variants.cpp: C:\Users\yourname\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6

Zero pin out chart from video:


//**********************Arduino Code from the video*********************
//This code is free to use and modify at your own risk

bool tog = false; //used to toggle LEDs on and off

void setup() {
  pinMode(38,OUTPUT); //This is the pin labeled "ATN"
  pinMode(22,OUTPUT); //This is MISO pin on ICSP header
  pinMode(20,OUTPUT); //This is SDA pin
  SerialUSB.begin(57600); //this is the native USB port
  Serial.begin(57600); //this is the programming port
  Serial1.begin(57600); //this is for pins D0 and D1
}

void loop() {

  if(tog) { //set each of the pins to high to turn LEDs on
    digitalWrite(38,HIGH);
    digitalWrite(22,HIGH);
    digitalWrite(20,HIGH);
    tog = false;
  }
  else { //set each pin to low to turn them off
    digitalWrite(38,LOW);
    digitalWrite(22,LOW);
    digitalWrite(20,LOW);
    tog = true;
  }

  delay(1500); //delsy for 1.5 seconds
}