Jeremy Proffitt
Published © CC BY-NC-SA

Full Alexa Home Automation for the Particle + Skill

Change color, read and set temperatures, lock and turn on/off using Alexa's home automation and the Particle Photon + Skill.

IntermediateProtip2 hours1,746
Full Alexa Home Automation for the Particle + Skill

Things used in this project

Hardware components

Photon
Particle Photon
×1

Software apps and online services

Photon Smart Home Bridge

Story

Read more

Code

Example Code: Turn Item On / Off

C/C++
Simple code, creates a copy of our class, sets up a pin for output, adds the echo device which requires the device name the Alexa will know the device as and a reference to the on/off function that is called when you activate On/Off using Alexa.
// This #include statement was automatically added by the Particle IDE.
#include "EchoPhotonBridge.h"

EchoPhotonBridge epb;

//function OnOff - this turns a device on or off
int functionOnOff(int device, bool onOff, String rawParameters)
{
    digitalWrite(D7, (onOff) ? HIGH : LOW);
}

//  REMINDER: Tell your echo, "Alexa, Discover Devices" after you program your photon so Amazon picks it up.

void setup()
{
    pinMode(D7, OUTPUT);
    epb.addEchoDeviceV2OnOff("Photon Light", &functionOnOff);
}

void loop() 
{
  
}

Example Code: Fan and Light with OLED

C/C++
This example uses PWM to turn on and off and set speed/level on two pins, one was set up for a fan, the second for a light. These can be DC devices controlled through MOSFET's or SSR's to control AC devices. The OLED is the very popular 128x64 OLED I2C device and is useful for troubleshooting.
#include <EchoPhotonBridge.h>
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

#define OLED_RESET D4
Adafruit_SSD1306 display(OLED_RESET);
EchoPhotonBridge epb;

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 

//Pin assignments
#define FAN A4
#define LIGHT A5

//#define DEBUG_PUBLISH_TO "sumologic"

void setup()   {     
    pinMode(FAN, OUTPUT);
    analogWrite(FAN, 0, 500);
    
    pinMode(LIGHT, OUTPUT);
    analogWrite(LIGHT, 0, 500);
      
    
    String deviceName = "Chair Fan";
    epb.addEchoDeviceV2OnOff(deviceName, &functionOnOff);
    epb.addEchoDeviceV2Percent(deviceName, &functionPercent);
    
    deviceName = "Chair Light";
    epb.addEchoDeviceV2OnOff(deviceName, &functionOnOff);
    epb.addEchoDeviceV2Percent(deviceName, &functionPercent);
    
    display.begin(SSD1306_SWITCHCAPVCC, 0x3c);  // initialize with the I2C addr 0x3D (for the 128x64)
    display.clearDisplay();
    display.display();
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.println("Chair");
    display.display();
 
}



void loop() {
  
}

void writeLCD(int Size, String Line1, String Line2, String Line3, String Line4)
{
  display.clearDisplay();
  display.display();
  display.setTextSize(Size);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(Line1);
  display.println(Line2);
  display.println(Line3);
  display.println(Line4);
  display.display();
 
}

//function OnOff - this turns a device on or off
int functionOnOff(int device, bool onOff, String rawParameters)
{
    #ifdef DEBUG_PUBLISH_TO
        Particle.publish(DEBUG_PUBLISH_TO, String("functionOnOff  " + String(device) + "  " + String(onOff) + "  " + rawParameters));
    #endif
    
    writeLCD(2,"Chair",(device==0) ? " Fan" : " Light", "  Is",(onOff) ? "   On" : "   Off");
    
    analogWrite((device == 0) ? FAN : LIGHT, (onOff) ? 250 : 0, 500);
            
    return 0;
}




int functionPercent(int device, int percent, int changeAmount, String rawParameters)
{
    #ifdef DEBUG_PUBLISH_TO
        Particle.publish(DEBUG_PUBLISH_TO, String("functionPercent  " + String(device) + "  " + String(percent) + "  " + String(changeAmount) + "  " + rawParameters));
    #endif
    
    writeLCD(2,"Chair",(device==0) ? " Fan" : " Light", "  at","     " + String(percent) + "%");
    
    analogWrite((device == 0) ? FAN : LIGHT, percent * 2.5, 500);
   
    return percent;
}

Example Code: All Supported Alexa Functions

C/C++
This is the test of the Lock, Temperature, On/Off and Color functions. This is a great place to
understand how the different functions work.

You need a 8 or more LED NeoPixel / WS2812 array or anything FastLED capabile attached on pin 6.

Don't forget to ask, "Alexa, Discover Devices" once everything is setup to detect new test devices.
#include <FastLED.h>
FASTLED_USING_NAMESPACE;
#define PARTICLE_NO_ARDUINO_COMPATIBILITY 1

#include <EchoPhotonBridge.h>

#define NUM_LEDS 32
#define FASTLED_PIN 6


CRGB leds[NUM_LEDS];
EchoPhotonBridge epb;

int currentTemp = 81;
int setTemp = 78;

/*

Test Device Names: Photon, Blanket, Test Room

Test Utterances:

Alexa, Turn Photon On
Alexa, Turn Photon Off
Alexa, Make Photon Red
Alexa, Make Photon Blue
Alexa, Set Photon to 10 Percent
Alexa, Set Photon to 90 Percent

Alexa, Turn Test Room On
Alexa, Turn Test Room Off
Alexa, Make Test Room Red
Alexa, Make Test Room Blue
Alexa, Set Test Room to 10 Percent
Alexa, Set Test Room to 90 Percent
Alexa, Lock Test Room

Alexa, Set the Temperature of my blanket to 90 degrees
Alexa, What is the temperature of my blanket?
Alexa, Turn Blanket On
Alexa, Turn Blanket Off

*/


int functionOnOff(int device, bool onOff, String rawParameters)
{
    leds[device] = (onOff) ? CRGB::White : CRGB::Black;
    FastLED.show();
    return 0;
}

int functionPercent(int device, int percent, int changeAmount, String rawParameters)
{
    leds[device + 3].r = 255 - (255 * percent / 100);
    leds[device + 3].g = percent / 100 * 255;
    leds[device + 3].b = percent + 50;
    FastLED.show();
    return 0;
}

int functionColor(int device, int R, int G, int B, String rawParameters)
{
    leds[device].r = R;
    leds[device].g = G;
    leds[device].b = B;
    FastLED.show();
    return 0;
}

int functionTemp(int device, bool requestCurrentTemp, bool requestSetTemp, int temperature, int changeAmount, String rawParameters)
{
    leds[6] = CRGB::White;
    if (requestCurrentTemp) return currentTemp;
    if (requestSetTemp) return setTemp;
    setTemp = temperature;
    leds[6].r = setTemp;
    leds[6].g = setTemp;
    leds[6].b = setTemp;
    FastLED.show();
    return 0;
}

bool virtualLock = false;

//functionLock tells a device to change color or requests the status of a lock.
//(int, bool, bool, String);
int functionLock(int device, bool requestStatus, bool locked, String rawParameters)
{
    if (requestStatus) return ((virtualLock) ? 1 : 0);
    
    virtualLock = locked;
    
    leds[7] = (virtualLock) ? CRGB::Red : CRGB::Green; 
    FastLED.show();
    
    return 0;
}


void setup() 
{
    FastLED.addLeds<WS2812, FASTLED_PIN, GRB>(leds, NUM_LEDS);

    String deviceName = "Photon";
    epb.addEchoDeviceV2OnOff(deviceName, &functionOnOff);
    epb.addEchoDeviceV2Percent(deviceName, &functionPercent);
    epb.addEchoDeviceV2Color(deviceName, &functionColor);
    
    deviceName = "Test Room";
    epb.addEchoDeviceV2OnOff(deviceName, &functionOnOff);
    epb.addEchoDeviceV2Percent(deviceName, &functionPercent);
    epb.addEchoDeviceV2Color(deviceName, &functionColor);
    epb.addEchoDeviceV2Lock(deviceName, &functionLock);
    
    deviceName = "Blanket";
    epb.addEchoDeviceV2OnOff(deviceName, &functionOnOff);
    epb.addEchoDeviceV2Temp(deviceName, &functionTemp);
    
    leds[0] = CRGB::Pink;
    leds[1] = CRGB::Blue;
    leds[2] = CRGB::Orange;
    leds[3] = CRGB::Purple;
    leds[4] = CRGB::Yellow;
    leds[5] = CRGB::Green;
    leds[6] = CRGB::Red;
    leds[7] = CRGB::White;
    FastLED.show();
}

void loop() 
{
    
}

Example Code: Temperature Controlled Fan

C/C++
This sample includes the use of an ST7735 LCD, 1820 One Wire Temp Sensor and controls the output of 2 pins which are hooked up to a fan, one for oscillation and the second for fan speed through two SSR's. Not my favorite code, definately needs some cleanup but does demonstrate temperature control.
#include <OneWire.h>
#include <DS18.h>
#include <Adafruit_ST7735.h>
#include <EchoPhotonBridge.h>
//Load Fast LED Library and set it's options.
#include <FastLED.h>
FASTLED_USING_NAMESPACE;
#define PARTICLE_NO_ARDUINO_COMPATIBILITY 1

//Set Defines to set up Hardware.
#define NUM_LEDS 32
#define FASTLED_PIN 6

#define FAN D0
#define ONEWIRE D2
#define BL  D1
#define CS  A2
#define DC  D4
#define RST A1

#define TEMPLOCKTIME 30 //30 minutes

//Local Variables
int setTemp = 80;
int currentTemp;
String lastUpdate = "";
unsigned long oldTime = 0;
unsigned long tempLockTime = 0;
bool thermostat = true;


CRGB leds[NUM_LEDS];
EchoPhotonBridge epb;
Adafruit_ST7735 tft = Adafruit_ST7735(CS, DC, RST);
DS18 sensor(ONEWIRE);

int functionOnOff(int device, bool onOff, String rawParameters)
{
    tft.setTextColor((onOff) ? ST7735_GREEN : ST7735_RED, ST7735_BLACK);
    tft.setTextSize(1);
    tft.setCursor(0,140);
    tft.fillRect(0,140,128,160,ST7735_BLACK);
    switch (device)
    {
        case 0: //Fan
            analogWrite(FAN, (onOff) ? 250 : 0, 500);
            tft.println((onOff) ? "Fan On" : "Fan Off");
            tempLockTime = millis() + (1000 * 60 * TEMPLOCKTIME);
            updateThermostatDisplay("Paused");
            break;
        case 1: //LCD BackLight
            analogWrite(BL, (onOff) ? 250 : 0, 500);
            tft.println((onOff) ? "Backlight On" : "Backlight Off");
            break;
        case 2: //termostat
            thermostat = onOff;
            updateThermostatDisplay((onOff) ? "On" : "Off");
            break;
        case 3: //Fast LED Array
            for (int i = 0; i < NUM_LEDS; i++) 
            {
                leds[i] = (onOff) ? CRGB::White : CRGB::Black;
            }
                FastLED.show();
            tft.println((onOff) ? "Light On" : "Light Off");
            break;
    }
    return 0;
}

int functionPercent(int device, int percent, int changeAmount, String rawParameters)
{
    tft.setTextColor(ST7735_BLUE, ST7735_BLACK);
    tft.setTextSize(1);
    tft.setCursor(0,140);
    tft.fillRect(0,140,128,160,ST7735_BLACK);
    switch (device)
    {
        case 0: //Fan
            analogWrite(FAN, percent * 2.5, 500);
            tft.println("Fan to " + String(percent) + "%");
            tempLockTime = millis() + (1000 * 60 * TEMPLOCKTIME);
            updateThermostatDisplay("Paused");
            break;
        case 1: //LCD BackLight
            analogWrite(BL, percent * 2.5, 500);
            tft.println("LCD BL to " + String(percent) + "%");
            break;
        case 3: //Fast LED
            
            FastLED.show();
            break;    
    }
    
    return 0;
}

int functionColor(int device, int R, int G, int B, String rawParameters)
{
    for (int i = 0; i < NUM_LEDS; i++) 
    {
        leds[i].r = R;
        leds[i].g = G;
        leds[i].b = B;
    }
    FastLED.show();
    
    return device * 1000000;
}



int functionTemp(int device, bool requestCurrentTemp, bool requestSetTemp, int temperature, int changeAmount, String rawParameters)
{
    if (requestCurrentTemp) return currentTemp;
    if (requestSetTemp) return setTemp;
    setTemp = temperature;
    thermostat = true;
    updateThermostatDisplay("On");
    return 0;
}

void updateThermostatDisplay(String state) 
{
    tft.setCursor(0,80);
    tft.println("Thermostat " + String(setTemp) + " F");
    tft.fillRect(0,80,128,120,ST7735_BLACK);
    tft.setCursor(0,100);
    tft.println(state);
}

void setup() {
    pinMode(FAN, OUTPUT);
    analogWrite(FAN, 0, 500);
    
    pinMode(BL, OUTPUT);
    analogWrite(BL, 250, 500);
    
    FastLED.addLeds<WS2812, FASTLED_PIN, GRB>(leds, NUM_LEDS);

    String deviceName = "Cool Breeze";
    String deviceType = "Fan";
    epb.addEchoDeviceV2OnOff(deviceName + " " + deviceType, &functionOnOff);
    epb.addEchoDeviceV2Percent(deviceName + " " + deviceType, &functionPercent);
    epb.addEchoDeviceV2Temp(deviceName + " " + deviceType, &functionTemp);
    
    deviceType = "BackLight";
    epb.addEchoDeviceV2OnOff(deviceName + " " + deviceType, &functionOnOff);
    epb.addEchoDeviceV2Color(deviceName + " " + deviceType, &functionColor);
    epb.addEchoDeviceV2Percent(deviceName + " " + deviceType, &functionPercent);
    
    deviceType = "Thermostat";
    epb.addEchoDeviceV2OnOff(deviceName + " " + deviceType, &functionOnOff);
   
    deviceType = "Light";
    epb.addEchoDeviceV2OnOff(deviceName + " " + deviceType, &functionOnOff);
    epb.addEchoDeviceV2Color(deviceName + " " + deviceType, &functionColor);
    epb.addEchoDeviceV2Percent(deviceName + " " + deviceType, &functionPercent);
    
    tft.initG();
    tft.fillScreen(ST7735_BLACK);
    //tft.setFont(TIMESNEWROMAN8);
    tft.setTextSize(1);
    tft.setTextColor(ST7735_WHITE);
	tft.setCursor(10,120);
    tft.setTextColor(ST7735_WHITE);
    tft.setTextWrap(true);
    tft.println(deviceName);  
    
    functionOnOff(2,true,""); //Turn on Thermostat.
    oldTime = millis();
}

void loop() {
    
    if(millis() - oldTime >= 1000)
    {
        
        if (sensor.read()) {
            tft.setTextColor(ST7735_BLACK);
            tft.setCursor(20, 20);
            tft.setTextSize(4);
            tft.print(lastUpdate);
            tft.setTextColor(ST7735_WHITE);
            tft.setCursor(20,20);
            lastUpdate = String::format("%1.1f",sensor.fahrenheit());
            tft.print(lastUpdate);
            Particle.publish("sumologic", lastUpdate);
            
            currentTemp = sensor.fahrenheit();
            if (tempLockTime < millis() && thermostat) 
            {
                if (currentTemp > setTemp + 1)
                {
                    functionOnOff(0,true,"");
                }
                else if (currentTemp < setTemp - 1)
                {
                    functionOnOff(0,false,"");                
                }
            }
        }   
        oldTime = millis(); //update old_time to current millis()
    }
}

Full GitHub: EchoPhotonBridge Photon Library + Examples

You can insert this library right into your Particle project, just select library and enter in "EchoPhotonBridge" and click on my library. Or download it and include it in your code.

Credits

Jeremy Proffitt

Jeremy Proffitt

1 project • 7 followers
An SRE by trade, I'm the jack of all trades, master of none with an understanding of failure, risk and reward. I love to create and fix.

Comments