Showing posts with label home automation. Show all posts
Showing posts with label home automation. Show all posts

Wednesday, September 26, 2018

Easy Way to Create a Wireless Sensor Network

In this video we look at an easy way with not very much code to setup a wireless network using the nRF24L01 Transceiver and Arduino.



//***************************Master or Receiver code*****************
/*This code was used for a video tutorial on the ForceTronics YouTube Channel
 * This code is free and open for anybody to use and modify at your own risk
*/

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/

const uint8_t pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const uint8_t pinCSN = 10; //This pin is used for SPI comm chip select
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) 
const uint64_t rAddress = 0xB00B1E50C3LL;  //Create pipe address for the network and notice I spelled boobies because I am mature, the "LL" is for LongLong type
const uint8_t rFChan = 89; //Set channel frequency default (chan 84 is 2.484GHz to 2.489GHz)

//Create a structure to hold fake sensor data and channel data
struct PayLoad {
  uint8_t chan;
  uint8_t sensor;
};

PayLoad payload; //create struct object

void setup() {
  wirelessSPI.begin();  //Start the nRF24 module
  wirelessSPI.setChannel(rFChan); //set communication frequency channel
  wirelessSPI.openReadingPipe(1,rAddress);  //This is receiver or master so we need to be ready to read data from transmitters
  wirelessSPI.startListening();    // Start listening for messages
  Serial.begin(115200);  //serial port to display received data
  Serial.println("Network master is online...");
}

void loop() {
  if(wirelessSPI.available()){ //Check if recieved data
     wirelessSPI.read(&payload, sizeof(payload)); //read packet of data and store it in struct object
     Serial.print("Received data packet from node: ");
     Serial.println(payload.chan); //print node number or channel
     Serial.print("Node sensor value is: ");
     Serial.println(payload.sensor); //print node's sensor value
     Serial.println(); 
  }
}

//***************************Node or Transmitter code*****************
/*This code was used for a video tutorial on the ForceTronics YouTube Channel
 * This code is free and open for anybody to use and modify at your own risk
*/

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/

const uint8_t pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const uint8_t pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) 
const uint64_t wAddress = 0xB00B1E50C3LL;  //Create pipe address to send data, the "LL" is for LongLong type
const uint8_t rFChan = 89; //Set channel default (chan 84 is 2.484GHz to 2.489GHz)
const uint8_t rDelay = 7; //this is based on 250us increments, 0 is 250us so 7 is 2 ms
const uint8_t rNum = 5; //number of retries that will be attempted 
const uint8_t chan1 = 2; //D2 pin for node channel check
const uint8_t chan2 = 3; //D3 pin for node channel check
const uint8_t chan3 = 4; //D4 pin for node channel check

//stuct of payload to send fake sensor data and node channel
struct PayLoad {
  uint8_t chan;
  uint8_t sensor;
};

PayLoad payload; //create struct object

void setup() {
  pinMode(chan1,INPUT_PULLUP); //set channel select digital pins to input pullup
  pinMode(chan2,INPUT_PULLUP);
  pinMode(chan3,INPUT_PULLUP);
  wirelessSPI.begin();  //Start the nRF24 module
  wirelessSPI.setChannel(rFChan); 
  wirelessSPI.setRetries(rDelay,rNum); //if a transmit fails to reach receiver (no ack packet) then this sets retry attempts and delay between retries   
  wirelessSPI.openWritingPipe(wAddress); //open writing or transmit pipe
  wirelessSPI.stopListening(); //go into transmit mode
  randomSeed(analogRead(0)); //set random seed for fake sensor data
  setChannel();  //checks current channel setting for transceiver
}

void loop() {
  delay(3000); //send data every 3 seconds
  payload.sensor = random(0,255); //get made up sensor value
  if (!wirelessSPI.write(&payload, sizeof(payload))){  //send data and remember it will retry if it fails
    delay(random(5,20)); //as another back up, delay for a random amount of time and try again
    if (!wirelessSPI.write(&payload, sizeof(payload))){
      //set error flag if it fails again
    }
  }

}

//check for low digital pin to set node address
void setChannel() {
  if(!digitalRead(chan1)) payload.chan = 1;
  else if(!digitalRead(chan2)) payload.chan = 2;
  else if(!digitalRead(chan3)) payload.chan = 3;
  else payload.chan = 0;
}

Tuesday, May 30, 2017

Home Automation with Arduino and the Amazon Echo Part 4

In the final conclusion of this four part series on using the Amazon Echo and Arduino for home automation we look at the Arduino hardware setup for monitoring the current consumption of a washer machine and reports its state to the cloud.




You can access code from GitHub: https://github.com/ForceTronics/Arduino_Echo_Home_Automation


Friday, May 26, 2017

Home Automation with the Arduino and the Amazon Echo Part 3

In part 3 instead of controlling a household device with the Echo, Arduino, and the cloud like we did in parts 1 and 2, we are monitoring an appliance (washer) so the data is flowing in the opposite direction.



You can access the code on github:  https://github.com/ForceTronics/Arduino_Echo_Home_Automation



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
  }

}

Monday, September 5, 2016

Combining Arduino, Android, and the Cloud Part 3

In this 3 part series we look at how to create an Android app to monitor and control multiple WiFi enabled Arduinos using the cloud. In part 3 the finale we will look at how to send control data to the cloud using an Android App to control the Arduino WiFi nodes. To download the Android App .aia file to load into MIT App Inventor II use the following link: https://dl.dropboxusercontent.com/u/26591541/CloudHomeAutoEx2.aia


//Arduino MKR1000 Code****************************************************
/*
 This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3 
 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 the Arduino WiFi101 examples and from a Sparkfun example 
 on using their cloud service Phant
 */


#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "YourNetwork"; //  your network SSID (name)
char pass[] = "YourPassword";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)
bool pData = false;  //used to toggle between posting data and getting data

int status = WL_IDLE_STATUS;

//define some constant variables for pins and node number
const int LED_PIN = 6; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 2; //node identifier
const char parseKey[] = "stamp";

//define areas for phant cloud address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";
//The following variables are from Phant library created by Sparkfun.
String _pub;
String _prv;
String _host;
String _params;
static const char HEADER_POST_URL1[] PROGMEM = "POST /input/";
static const char HEADER_POST_URL2[] PROGMEM = ".txt HTTP/1.1\n";
static const char HEADER_PHANT_PRV_KEY[] PROGMEM = "Phant-Private-Key: ";
static const char HEADER_CONNECTION_CLOSE[] PROGMEM = "Connection: close\n";
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: application/x-www-form-urlencoded\n";
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";

//timing for posting to the phant cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); //setup LED pin
  digitalWrite(LED_PIN, LOW); //Turn off LED
  Serial.begin(9600);
  while (!Serial) { //Note the code will not cont unless you open serial monitor
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWifiStatus(); //Print info about the WiFi network that you are connected to
}

void loop() {
  //Delay for set time then post and get data from Phant cloud
  if (lastPost + postRate <= millis())
  {
    if(pData) {
      if (postToPhant()) lastPost = millis();
      else lastPost = millis(); //Even if we fail delay whole cycle before we try again   
    } 
    else {
      if (getFromPhant()) lastPost = millis();
      else lastPost = millis(); //Even if we fail delay whole cycle before we try again 
    }
  }
}

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

 //Set phant data
 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(phantGet()); 
    client.println();
    Serial.println("sent get request.....");
   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 whe 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 == 3) { //if true we are at the point in the data to read control data for node oen
          Serial.print(c);
          int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
          if(dControl == 1 | dControl == 0) digitalWrite(LED_PIN, 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()) {
      Serial.println();
      Serial.println("disconnecting.");
      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
    }
   }
  pData = true; //set to true so we post data to cloud next loop
  return 1; // Return success
}

//function used to post data to phant cloud
int postToPhant()
{
  // Declare an object from the Phant library - phant
  phant(PhantHost, pPublicKey, pPrivateKey);
  //These calls build the web communication strings with Phant
  phantAdd("adcdata", analogRead(ANALOG_PIN)); //specify field and data used in that field
  phantAdd("wifinode", NODE_NUM);
  
  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.
    pData = false; //set to false so we get data from cloud next loop
    return 0;
  }

  //Send post to phant server
  client.print(phantPost()); 
  
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    String line = client.readStringUntil('\r');
    //Do something with data
  }
  client.stop();
  pData = false; //set to false so we get data from cloud next loop
  return 1; // Return success
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  Serial.println();
}


//This is from phant library, initializes variables
void phant(String host, String publicKey, String privateKey) {
  _host = host;
  _pub = publicKey;
  _prv = privateKey;
  _params = "";
}

//From phant library, builds string of field and data
void phantAdd(String field, int data) {

  _params += "&" + field + "=" + String(data);

}

//From phant library, builds string to get data from Phant cloud
String phantGet() {
  String result = "GET /output/" + _pub + ".csv?page=1 HTTP/1.1\n";
  result += "Host: " + _host + "\n";
  result += "Connection: close\n";

  return result;

}

//From phant library, builds the string used to post data to phant over web services
String phantPost() {

  String params = _params.substring(1);
  String result;
  //String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
  for (int i=0; i<strlen(HEADER_POST_URL1); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_POST_URL1 + i);
  }
  result += _pub;
  for (int i=0; i<strlen(HEADER_POST_URL2); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_POST_URL2 + i);
  }
  result += "Host: " + _host + "\n";
  //result += "Phant-Private-Key: " + _prv + "\n";
  for (int i=0; i<strlen(HEADER_PHANT_PRV_KEY); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_PHANT_PRV_KEY + i);
  }
  result += _prv + '\n';
  //result += "Connection: close\n";
  for (int i=0; i<strlen(HEADER_CONNECTION_CLOSE); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_CONNECTION_CLOSE + i);
  }
  //result += "Content-Type: application/x-www-form-urlencoded\n";
  for (int i=0; i<strlen(HEADER_CONTENT_TYPE); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_CONTENT_TYPE + i);
  }  
  //result += "Content-Length: " + String(params.length()) + "\n\n";
  for (int i=0; i<strlen(HEADER_CONTENT_LENGTH); i++)
  {
    result += (char)pgm_read_byte_near(HEADER_CONTENT_LENGTH + i);
  } 
  result += String(params.length()) + "\n\n";
  result += params;

  _params = "";
  return result;
}

//This function convers the ADC level integer value into float voltage value.
//The inputs are the measured ADC value and the ADC reference voltage level
//The formula used was obtained from the data sheet: (ADC value / 1024) x ref voltage
float convertToVolt(float refVal, int aVAL) {
  return (((float)aVAL/1024)*refVal);
}

//this function calculates temp in F from TMP36 temp sensor
//see TMP36 datasheet to understand algorithm used
float calculateTempF(float v1) { 
 float temp = 0;
 //calculate temp in C, .75 volts is 25 C. 10mV per degree
 if (v1 < .75) { temp = 25 - ((.75-v1)/.01); } //if below 25 C
 else if (v1 == .75) {temp = 25; }
 else { temp = 25 + ((v1 -.75)/.01); } //if above 25
 //convert to F
 temp =((temp*9)/5) + 32;
 return temp;
}

//Arduino ESP8266 Code****************************************************
/*
 This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3 
 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. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>

//Set your network name and password
const char WiFiSSID[] = "YourNetwork";
const char WiFiPSK[] = "YourPassword";

//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
const char parseKey[] = "stamp";
bool pData = false;  //used to toggle between posting data and getting data

//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";

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

void setup() 
{
  initHardware(); //setup arduino hardware
  connectWiFi(); //Connect your WiFi network
  digitalWrite(LED_PIN, HIGH);
}

void loop() 
{ //loop until it is time to post data to phant cloud
  if (lastPost + postRate <= millis())
  {
    if(pData) {
      if (postToPhant()) lastPost = millis();
      else lastPost = millis(); //Even if we fail delay whole cycle before we try again   
    } 
    else {
      if (getFromPhant()) lastPost = millis();
      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_PIN, 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);
    // Potentially infinite loops are generally dangerous.
    // Add delays -- allowing the processor to perform other
    // tasks -- wherever possible.
  }
}

//function that sets up some initial hardware states
void initHardware()
{
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
}

//function that handles posting and 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 whe 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(LED_PIN, 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
    }
   }
  pData = true; //set to true so we post data to cloud next loop
  return 1; // Return success
}

//this function takes data and posts it to the cloud
int postToPhant()

  // Declare an object from the Phant library - phant
  Phant phant(PhantHost, pPublicKey, pPrivateKey);
  //These functions build data and field string that will be sent to phant cloud
  phant.add("adcdata", analogRead(ANALOG_PIN));
  phant.add("wifinode", NODE_NUM);
  
  // Now connect to data.sparkfun.com, and post our data:
  WiFiClient client; //declare client object that will post the data
  const int httpPort = 80; //specify port to post through
  
  if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
  {
    // If we fail to connect, return 0.
    return 0;
  }
 //Send post to phant
  client.print(phant.post());
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    //Serial.print(line); // Trying to avoid using serial
  }
  pData = false; //set to false so we get data from cloud next loop
  return 1; // Return success
}
  

Thursday, December 31, 2015

Building an AC Power Switch Development Board

Ever want to create a design that automates turning on or off an AC powered device such as a light or a heating system? Well this video is for you! In this video we look at how to create a development board for switching on and off AC power. The switch is implemented with a TRIAC which is a semiconductor device so no moving parts like a relay based design. You can access the Eagle PCB layout files from this link https://github.com/ForceTronics/AC-Switch-Proto-Board/tree/master or you can purchase this development board from www.forcetronics.com


Download Eagles files from GitHub: https://github.com/ForceTronics/AC-Switch-Proto-Board

*********************************Arduino code shown in the video********
//This sketch is used to control Thyristor that is used as a switch to turn on and off an AC line powered light. //This code is free for all to use
int8_t dig = 0; //default is high for light off

void setup() {
  //for controlling Thyristor
  pinMode(7, OUTPUT); //set pin to output so it can sink current from optoisolator
  digitalWrite(7, HIGH); //when high the thyristor is off or open
}

void loop() {
  delay(3000); //light turns on / off every 2 seconds
  togLight(); //call function to turn light on / off using digital pin
}

void togLight() {
  if(dig) { 
     digitalWrite(7, HIGH); //turn off light
     dig = 0; //toggle dig value
  }
  else {  
     digitalWrite(7, LOW); //turn light on
     dig = 1; 
   }
}



Sunday, June 1, 2014

Switching AC Line Power with a Thyristor (TRIAC)

In this video we look at how to use a Thyristor (TRIAC) as an AC line power switch. Great tool to use in home automation projects for turning on or off a light or building your own thermostat.


Thyristor Example Circuit


//This sketch is used to control Thyristor that is used as a switch to turn on and off an AC line powered light. //This code is free for all to use
int8_t dig = 1; //default is high for light off

void setup() {
  //for controlling Thyristor
  pinMode(3, OUTPUT); //set pin to output so it can sink current from optoisolator
  digitalWrite(3, HIGH); //when high the thyristor is off or open
}

void loop() {
  delay(2000); //light turns on / off every 2 seconds
  togLight(); //call function to turn light on / off using digital pin
}

void togLight() {
  if(dig) { 
     digitalWrite(3, HIGH); //turn off light
     dig = 0; //toggle dig value
  }
  else {  
     digitalWrite(3, LOW); //turn light on
     dig = 1; 
   }
}