Alexa for Home Automation

My name is Ranesh and my main project is Alexa for Home Automation. For my first few weeks here, I explored the web communication between Alexa and Particle, and the microprocessor used to control the components. I experimented by making Alexa turn on and off the LED lights and get temperature and humidity readings from the DHT22 temperature sensor. For my modification, I made an electricity budget system. This system monitors how much budget an electrical device has expended and if the devices crosses the budget, it is shut off. The users have the option of asking for status from Alexa or receive notifications on their phones. Additionally, the users can view previous budget analytics as graphs and predict the time duration for a given budget amount on an app.

Build Plan
Schematics

App Screenshots

Electricity Budget RaneshRanesh AlexaRanesh Alexa for Home AutomationSmart Budget

Engineer

Ranesh

Area of Interest

Electrical Engineering and Computer Science

School

Cupertino High School

Grade

Rising Senior

Demo Night Presentation

Final Milestone

Goal

For my final milestone, I made the electricity budget system more user friendly that gives them more autonomy in analyzing the results of their electricity budget. I first added a notification system that lets the users know when they have crossed half of their electricity budget, three-fourths of their budget, and when their devices have been shut off once their devices completely cross the electricity budget. This project is also accompanied by an Android app that lets the users view their past three budget runs in three different graphs and also lets them predict the duration their device can run given a budget based on past data. Finally, I soldered all the connections to the PCB Board to make this project into a finalized product.

Coding Particle

I explored three different ways of sending notifications to the users. First, I considered using IFTTT (if this then that), a software that connects different services, such as Facebook with messaging, etc, to send the notification. Although it was easy to set up the IFTTT applet since there was no coding required and I could directly track the Particle variable and send it as a SMS through their own platform, the applet said that it ran only once in one hour. Upon further research, I figured out that IFTTT has only updated some services to run frequently. After that, I looked into using AWS SNS to send an email notification. However, when I implemented that feature by sending data over a web hook, the only response I was getting back from AWS was an internal error. Finally, I used a program called Pushbullet. This app has been used by developers before, which is why it seemed like a viable alternative. Therefore, I created a web hook in JSON for sending a notification, which basically pushed the value to the POST method of the Pushbullet API by getting the value from the Particle code. In the Particle code, I checked whether the totalEnergyValue variable crossed half of the budget, 75% of it, or when it crossed the budget overall. Since this was checked in the main loop, I had to make sure that the notifications of the same thing weren’t sent repeatedly. That is why I had to check whether the notification of, say 50%, was already sent. Therefore, I used a boolean variable to check for the first time whether the notification was sent. Once the notification was sent, I changed the state of the boolean variable so that the notification wouldn’t be sent again. I was also able to send the data every two seconds to Firebase Database, a service owned by Google, by creating another web hook. In each push command, I sent the totalEnergyValue variable, the index of iteration, and the date.

Coding Android Java Files

Overall, the process flow of my app was the login screen with email, Google, and Facebook authentication, create account page, the graphs of previous runs, and a “Predict Time” page given a budget. Setting up the authentication was the easy part. However, when I was extracting the data from Firebase to create the graphs, some of the graphs were being duplicated. After multiple runs, I still could not locate the error but I noticed a pattern: after five graphs the data was repeating. Therefore, to make sense, I created a feature of showing the latest three runs of the system. The way the data was extrapolated was that while looping through the database, I kept adding the energy values to an Arraylist. Once the energy again came to zero, I made an Arraylist of custom objects (I coded the class for this object) that also took the date and the total budget set. This object was added to the Arraylist of its own type and at the end of the loop, the Arraylist is set to the Adapter for the list, which is then set to the RecyclerView object, which is basically a fancy list with each item being a customizable Card. When the adapter was set, each item from the Arraylist, one by one, was sent over to another class that populated the elements of each card. This included the graph by iterating through each ArrayList of electricity budget per object, the date, and the total budget. I also created a predict budget option. The way this worked is that when the user entered a budget, the program went through the database and it calculated the slope of time over budget of the latest run (since the graph was always linear) and that amount was multiplied by the slope to get a predicted time either in minutes or seconds, converted accordingly.

Coding Android UI

Unlike my prior apps before Bluestamp, I focused a lot on the user interface so that the app doesn’t only have complex functionalities but it is also appealing to the user so that the app is used in the first place. Therefore, I followed the material design conventions that professional Android developers have traditionally used. Few key components of this convention are sharp color contrast, different layers of widgets (such as buttons casting a shadow), even spacing, proper usage of the screen,  and keeping as few widget on the screen as possible while performing the desired functionalities. In order to achieve this, I first focused on the background colors. I wanted to have a blue base, but at the same time include subtle changes in color, hence the shifting colors in the main log in screen and fading colors in create account and predict time screens. Next, I wanted to focus on the proper usage of space, which is why most of my widgets occupy most of the screen and each type of widget is placed close to each other, such as all the edit text fields near each other and all the log in option in the main screens closer to each other. As far as contrasting colors go, I created light black tabs with white background for the graphs. I also set the elevation levels for buttons and the card views containing the graphs to make them more noticeable to the users. I also included some subtle stylistic elements, such as round edges for the buttons, to enhance the user experience. Having a clean and professional user interface not only helps the users in navigating through the app but it also gives the developer credibility of creating reliable products.

Bluestamp Experience

Overall, my experience at Bluestamp has been wonderful. Before coming to Bluestamp, I knew Android App development and Java. However, the flexibility of the program allowed me to explore difference programming languages, such as Node.js, JSON, and C++/Arduino. More importantly, however, I got to learn the different applications of programming. From making apps to making a whole IoT system that controls and analyses the performance of hardware components, I feel that I have enabled myself to fully realize and utilize the untapped potential of programming. IT wasn’t only the technical knowledge that I gained. Through the milestone videos and demo night presentation, I have become a more confident communicator than I previously was while at the same time having fun hanging out with my peers and instructors from all over the country. The combination of soft and technical skills I learned here has shaped me into a more experienced engineer who is ready to take on new challenges.

App

SmartBudget App

SmartBudget Ranesh
Ranesh Alexa
Home Automation
Alexa Ranesh
Electricity Budget
Particle Code

Code for Pushing Notification

if(totalEnergyValue >= Budget*0.5 && !fiftyPercent && Budget != 0){
                fiftyPercent = true;
                Particle.publish("pushbullet", "You are half way to your budget target.", 60, PRIVATE);
            }

            if(totalEnergyValue >= Budget*0.75 && !seventyfivePercent && Budget != 0){
                seventyfivePercent = true;
                Particle.publish("pushbullet", "You are 75% to your budget target.", 60, PRIVATE);
            }

            if(Budget != 0){
                counter+=2;
            }

            if(totalEnergyValue >= Budget && Budget != 0){
                digitalWrite(D3, LOW);
                Serial.println("You have crossed your limits!");
                Particle.publish("pushbullet", "You have crossed your electricity budget and your devices have been turned off.", 60, PRIVATE);
                Budget = 0;
                fiftyPercent = false;
                seventyfivePercent = false;
                counter = 0;
            }

Code for Publishing Data to Firebase Database

if(totalEnergyValue < Budget && Budget != 0){
                char buf[256];
	            snprintf(buf, sizeof(buf), "{\"a\":%d,\"b\":%.3f,\"c\":%d}", counter, totalEnergyValue, !datacollectionBegin);
	            Serial.printlnf("publishing %s", buf);
	            Particle.publish("budgetData", buf, PRIVATE);
	            datacollectionBegin = true;
            }

Android Studio Code
[/vc_column]

Third Milestone

Goal

For my third milestone, I decided to modify my base project by making a home budget system using Alexa. Essentially, a user can tell Alexa to turn on or off a device (in this case a fan) and the user can set a electricity budget via Alexa. Next, the users can ask Alexa to give the status of their electricity consumption as compared with the budget set, which is reported in percentage. Finally, when the electricity consumption crosses the budget set, the device is automatically turned off, thus saving the users’ their electricity costs.

Setting up Alexa Skill Set

To accomodate the new changes, I first had to set up new statements and slots that Alexa would detect and take values from respectively. I created four new slots for this functionality: statusSlot, dollars, cents, and devices. The statusSlot would detect the request of the users asking for the percentage of the electricity consumption, the dollars and cents slots would take the budget value in dollars and cents, and the devices value would handle the specific requests for turning on or off a specific device. For this last command, I used the onoff slot previously created to handle the user’s request of turning a particular device on or off. For the statements themselves that Alexa would recognize, I had to code multiple variations for the budget input in order to account for dollar vs dollars and cent vs cents when the user said “one” for either of those values and in order to detect when the user just said dollars, cents, or gave both values.

Coding AWS Lambda

My main changes regarding the AWS lambda was accounting for the appropriate data extraction from each slot value and sending them to the Particle API. First, I handled the status value; when the user says “electricity” and “status” afterwards”, the path to the Particle API is directed to “getEletricity” method (tagged by using “getElec” in the path name). Then, it checks for two values that are returned from the Particle API. If the JSON return value is zero, then the budget was not set in the first place, and the user is prompted to do so. If a certain value is returned, then that value is the percent value and Alexa then tells the appropriate message using that value. Next, I check for the device by using the “devices” slot. Although I am just using a fan, I also account for the light since I will be implementing that next. As of now, when the user says the command with fan as a slot value, then the pin to which the fan is connected, D3, is set as the pin value. Then the program goes to check whether the pin value is populated. If it is, then it checks the “onoff” slot and depending on whether the user said “on” or “off”, the state of the pin is either set to “HIGH” or “LOW”. When the pin value is checked to by “D3”, then both the pin and the pin value are sent to the Particle API in the same way as with LED lights in milestone #1. Finally, I took the budget amount as dollars and cents. For this, however, I did not use if-else statements but just two if statements since the user could send a combination of both the values. The program then checked whether a monetary amount was entered by checking a boolean variable checkBudgetValue which was set to true while checking if either the dollar or the cent variables were not null. The cent value was concatenated to the dollar value and a decimal point after the dollar value and then sent over to the Particle API.

Coding Particle IDE

In the Particle IDE, I created three key methods: getElectricityStatus, setBudget, and turnOnOff, and they do what they exactly sound like. For the setBudget function, I essentially set the global variable BUDGET to whatever budget was passed in, and the loop function basically checked to see whether the total energy consumption was over the Budget. If so, then the fan was turned off by setting the D3 pin to LOW. That way, the relay switch, which controls the circuit connection to the fan, breaks the connection. The total energy consumption was calculated by multiplying the current, voltage, the delay interval (two seconds), the conversion factor from seconds to hours, and the conversion factor from milli Amperes to Amperes. I did not calculate kilowatts-hour but just watts-hour because to reach a set kilowatt-hour amount would take a long time, which is not suitable for the demonstration purposes. I then converted that amount to a cost by multiplying thirteen cents, the cost per kilowatt-hour in California but in this case used for watt-hour. For the getElectricityStatus, the method returned the percent by dividing total Energy Value tallied with the total budget set. And finally, for turnOnOff method, I decoded the pin from the state from a single string parameter, which was then used to set the appropriate pin to either HIGH or LOW based on the appropriate state.

Circuiting

I had to change my previous circuit drastically to accomodate the new loads. For example, I had to set a whole new potential reference for the computer fan to work since the 3.3 V from Particle would not be enough to power the fan. To do so, I connected the Anker (a battery pack) with a breakout board. The VCC and Ground terminals were then hooked up to the positive and negative terminals of the breadboard. Then, I hooked up the fan’s positive terminal to the breadboard’s and the fan was then connected to the current sensor. The other end of the current sensor was connected to the relay switch’s COMMON pin. The NO (normally open) slot from the relay switch was connected to the 9 V potential from Anker and the VCC, GROUND, and COMMON pin from the current sensor was connected to the 3.3 V potential from the Photon, the ground, and the A0 pin which reads the current data coming in.

Particle Code

Initialization Code

#include 
#include 

#include "PietteTech_DHT.h"
#define DHTTYPE DHT22
#define DHTPIN D2
#define DELAY_INTERVAL 2000

void dht_wrapper();

//Library Instantiation
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);

//Global variables for Water Supplies
bool showerIsOn = false;
bool isDHTStarted = false;
unsigned int DHTnextSampleTime;
std::vector humidityVal;
double INITIAL_STATE = -1;
int counter = 0;
int BUFFER = 30;
double convertFromMilliToBase = .001;
double convertFromBaseToKilo = .001;
double convertFromSecToMin = 1/60;
double convertFromMinToHour = 1/60;
double prevBudget = 0;
//Global variables for power measurement output
int currentValue = 0;
double totalEnergyValue = 0;
double voltage = 3.3;
float Budget = 0;
bool alreadyOff = false;
bool alreadyOn = false;
bool fiftyPercent = false;
bool seventyfivePercent = false;
int counterSecData = 0;
bool datacollectionBegin = false;
int temperature = 0;

int humidity = 0;

void setup() {

    Serial.begin(9600);
    //Particle.subscribe("hook-response/awsHumidity", myHandler, MY_DEVICES);
    Particle.function("setBgt", setBudget);
    Particle.function("getElec", getElectricityStatus);
    pinMode(D3, OUTPUT);
    pinMode(D4, OUTPUT);
    Particle.function("turnonoff", turnOnOff);
    digitalWrite(D3, LOW);
    digitalWrite(D4, LOW);
    //Particle.variable("totalEnergyVal", &totalEnergyValue);
    //Particle.variable("Bgt", &Budget);
}

Code for Getting and Setting the Electricity Budget

float setBudget(String args){
    //prevBudget = 0;
    Budget = args.toFloat();
    Serial.print("My budget is $");
    Serial.println(Budget);
    return Budget;
}

double getElectricityStatus(String args){
    Serial.print("The total energy value in getElec is $");
    Serial.println(totalEnergyValue);
    if(Budget == 0){
        return 0;

    }else if(totalEnergyValue > Budget){

        return (totalEnergyValue - Budget)*-1;

    }else{
        return (totalEnergyValue/Budget)*100;
    }   
}

Code for Turning On/Off the Electrical Device

int turnOnOff(String args){
    int pos = args.indexOf(',');
    int pin = 0;
    int state = 0;
    if(-1 == pos){
        return -1;
    }

    String strPin = args.substring(0, pos);
    String strValue = args.substring(pos + 1);

    if(strPin.equalsIgnoreCase("D3")){
        pin = D3;
    }else if(strPin.equalsIgnoreCase("D4")){
        pin = D4;
    }

    if(strValue.equalsIgnoreCase("HIGH")){
        state = HIGH;
        alreadyOn = true;
        alreadyOff = false;
    }else if(strValue.equalsIgnoreCase("LOW")){
        state = LOW;
        alreadyOff = true;
        alreadyOn = false;
    }

    digitalWrite(pin, state);
    return 1;

}

Main Loop Code

void loop() {
    if(millis() > DHTnextSampleTime){

        /*The following code is to determine when the shower is on/off based on humidity.*/

        if(!isDHTStarted){

            if(Budget != 0){
                counter+=2;
            }

            if(totalEnergyValue >= Budget && Budget != 0){
                digitalWrite(D3, LOW);
                Serial.println("You have crossed your limits!");

                counter = 0;
            }

            Serial.print("The total kilowatt-hour is: ");
            Serial.println(totalEnergyValue/(convertFromMilliToBase*convertFromBaseToKilo*convertFromSecToMin*convertFromMinToHour));

            DHTnextSampleTime = millis() + DELAY_INTERVAL;
            counter++;
        }

    }
}

AWS Lambda Code

Code for Setting the Electricity Budget, Getting the Budget Status, and Turning On/Off the Electrical Device

Particle.prototype.intentHandlers = {
    // register custom intent handlers
    ParticleIntent: function (intent, session, response) {

		var lightSlot = intent.slots.light;
		var onoffSlot = intent.slots.onoff;
		var statusSlot = intent.slots.statusSlot;
		var dollarSlot = intent.slots.dollars;
		var deviceSlot = intent.slots.devices;
		var centSlot = intent.slots.cents;

		var onoff = "";
		var dollars = "";
		var device = "";
		var cent = "";

		onoff = onoffSlot ? intent.slots.onoff.value : "off";
		dollars = dollarSlot ? intent.slots.dollars.value : "";
		device = deviceSlot ? intent.slots.devices.value : "";
		cent = centSlot ? intent.slots.cents.value : "";
		//response.tell(cents);
		//response.tell(cent.length);

		var status = statusSlot ? intent.slots.statusSlot.value : "";

		//response.tell(device);

		var speakText = "";

		console.log("Sensor = " + sensor);
		console.log("Light = " + light);
		console.log("OnOff = " + onoff);
		//response.tell(light);
		var op = "";
		var pin = "";
		var pinvalue = "";
		var checkBudgetInput = false;

		// Replace these with action device id and access token
		var deviceid = "410022000247363339343638";
		var accessToken = "bd3b676c56061a314c1f7d1d455258aab7f1c0c2";

		var sparkHst = "api.particle.io";

		console.log("Host = " + sparkHst);

		// Check slots and call appropriate Particle Functions

		if (device == "fan"){
			pin = "D3";
		}else if (device == "light"){
			pin = "D4";
		}
		else if(status == "shower"){
			op = "getShwr";
		}else if (status == "electricity"){
			op = "getElec";
			//response.tell(op);
		}
		/*else if (cent.length > 0 && dollars == null){
			op = cent;
			response.tell(cent);
			checkBudgetInput = true;
		}*/

		if(dollars != null/*dollars.length > 0*/){
			//response.tell(cents);
			/*if(dollars.length > 0){
				op = dollars;
			}
			if(cents.length > 0){
				op += "."+cents;

			}*/

			op = dollars;
			//response.tell(dollars + cent);
			//response.tell("Im here");
			checkBudgetInput = true;
		}

		if (cent != null){
			op = cent;
			//response.tell(cent);
			checkBudgetInput = true;
		}

		//response.tell(cent);

		//response.tell(pin);

		// User is asking for temperature/pressure
		if(op.length > 0){
			var sparkPath = "/v1/devices/" + deviceid + "/" + op;
			//response.tell(sensor);
			console.log("Path = " + sparkPath);
			if (op == "getElec"){
				if(op == "getElec"){

					makeParticleRequest(sparkHst, sparkPath, "", accessToken, function(resp){
						var json = JSON.parse(resp);

						console.log(sensor + ": " + json.return_value);

						if(json.return_value < 0){ //response.tell(op); response.tellWithCard("You are " + (json.return_value/-1) + " over your budget." , "Particle", "Particle!"); }else if (json.return_value == 0){ response.tellWithCard("You have not set your budget yet. Please ask particle to set your electricity budget.", "Particle", "Particle!") }else{ response.tellWithCard("You are " + json.return_value + " percent to your budget target." , "Particle", "Particle!"); } }); } }else if(checkBudgetInput){ var sparkPath = "/v1/devices/" + deviceid + "/setBgt"; var args = dollars; console.log("Path = " + sparkPath); /*if(cents == null){ }*/ if(dollars != null && cent == null){ args = dollars; //response.tell(dollars); }else if (dollars != null && cent != null){ args = dollars + "." + cent; }else if (dollars == null && cent != null){ args = "0." + cent; } makeParticleRequest(sparkHst, sparkPath, args, accessToken, function(resp){ var json = JSON.parse(resp); console.log("Budget " + json.return_value); if(dollars == null){ dollars = 0; } if(cent == null){ cent = 0; } response.tellWithCard("OK, your electricity budget is set to " + dollars + " dollars and " + cent + " cents", "Particle", "Particle!"); response.ask("Continue?"); }); checkBudgetInput = false; } } // User is asking to turn on/off lights else if(pin.length > 0){
			//response.tell("Im here");
			if(onoff == "on"){
				pinvalue = "HIGH";

			}
			else{
				pinvalue = "LOW";
			}

			if(pin == "D3" || pin == "D4"){
				var sparkPath = "/v1/devices/" + deviceid + "/turnonoff";
			}

			console.log("Path = " + sparkPath);

			var args = pin + "," + pinvalue;

			makeParticleRequest(sparkHst, sparkPath, args, accessToken, function(resp){
				var json = JSON.parse(resp);

				console.log("Temperature: " + json.return_value);

				if(json.return_value == -1){
					response.tellWithCard("I could not recognize your request.", "Particle", "Particle!");
				}else if (json.return_value == 1){
					if(pin == "D3"){
						response.tellWithCard("OK, your fan is turned " + onoff, "Particle", "Particle!");
					}else if (pin == "D4"){
						response.tellWithCard("OK, your light is turned " + onoff, "Particle", "Particle!");
					}else{
						response.tellWithCard("OK, " + light + " light turned " + onoff, "Particle", "Particle!");
					}

				}

				response.ask("Continue?");
			});
			//response.tell(args);
		}

                else{

                    makeParticleRequest(sparkHst, sparkPath, "", accessToken, function(resp){
                        var json = JSON.parse(resp);

                        console.log(sensor + ": " + json.return_value);

                        if(json.return_value < 0){
                        //response.tell(op);
                            response.tellWithCard("You are " + (json.return_value/-1) + " over your budget." , "Particle", "Particle!");
                        }else if (json.return_value == 0){
                            response.tellWithCard("You have not set your budget yet. Please ask particle to set your electricity budget.", "Particle", 
                            "Particle!")
                        }else{
                             response.tellWithCard("You are " + json.return_value + " percent to your budget target." , "Particle", "Particle!");
                        }
                    });
                }
            }else if(checkBudgetInput){
                var sparkPath = "/v1/devices/" + deviceid + "/setBgt";
                var args = dollars;
                console.log("Path = " + sparkPath);
                /*if(cents == null){

                }*/
                if(dollars != null && cent == null){
                    args = dollars;
                    //response.tell(dollars);
                }else if (dollars != null && cent != null){
                    args = dollars + "." + cent;
                }else if (dollars == null && cent != null){
                    args = "0." + cent;
                }
                makeParticleRequest(sparkHst, sparkPath, args, accessToken, function(resp){
                    var json = JSON.parse(resp);

                    console.log("Budget " + json.return_value);
                    if(dollars == null){
                        dollars = 0;
                    }
                    if(cent == null){
                        cent = 0;
                    }

                    response.tellWithCard("OK, your electricity budget is set to " + dollars + " dollars and " + cent + " cents", "Particle", "Particle!");
                    response.ask("Continue?");
                });
                checkBudgetInput = false;

            }
}
		else{
			response.tell("Sorry, I could not understand what you said");
		}

		/*exports.handler = function (event, context, callback) {
		    // Create an instance of the Particle skill.
		    console.log("event name: " + event.Humidity);

		    //var particleSkill = new Particle();
		    //particleSkill.execute(event, context);
		    response.tell(event.Humidity);
		    callback("How ya doin", event.Humidity);
		};*/

    },
    HelpIntent: function (intent, session, response) {
        response.ask("You can ask me what is the temperature or humidity. You can also tell me to turn on Red or Green light!");
    }
};

Alexa Skill Set Code

Skills for Setting the Budget, Getting the Budget Status, and Turning On/Off the Electrical Device

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "particle",
            "intents": [

                {
                    "name": "ParticleIntent",
                    "slots": [

                        {
                            "name": "onoff",
                            "type": "LITERAL"
                        },
                        {
                            "name": "statusSlot",
                            "type": "LITERAL"
                        },
                        {
                            "name": "dollars",
                            "type": "AMAZON.NUMBER"
                        },
                        {
                            "name": "cents",
                            "type": "AMAZON.NUMBER"
                        },
                        {
                            "name": "devices",
                            "type": "LITERAL"
                        }
                    ],
                    "samples": [
                        "ParticleIntent {dollars}",

                        "ParticleIntent {cents}",

                        "ParticleIntent check {electricity|statusSlot} status",
                        "ParticleIntent set electricity budget to {dollars} dollars",
                        "ParticleIntent set electricity budget to {cents} cents",
                        "ParticleIntent set electricity budget to {cents} cent",
                        "ParticleIntent set electricity budget to {dollars} dollars and {cents} cents",
                        "ParticleIntent set electricity budget to {dollars} dollar",
                        "ParticleIntent set electricity budget to {dollars} dollar and {cents} cents",
                        "ParticleIntent set electricity budget to {dollars} dollar and {cents} cent",
                        "ParticleIntent turn {off|onoff} the {fan|devices}",
                        "ParticleIntent turn {on|onoff} the {fan|devices}",
                        "ParticleIntent turn {off|onoff} the {light|devices}",
                        "ParticleIntent turn {on|onoff} the {light|devices}"
                    ]
                }

            ],
            "types": []
        }
    }
}

Second Milestone

Goal

For my second milestone, I got the Alexa to tell the user room temperature (measured in celsius) and humidity based on what the user asks it. For this, I used a DHT22 sensor that was connected to D2 pin of the particle. As far as the coding goes, the AWS Lambda essentially sends over the parameters to the specific method that it would expect value from (either temperature or humidity). The Particle API then uses the DHT library to carry out the function and then it returns the respective value, which Alexa tells user.

Setting up Alexa Skill Set

First of all, I defined two sample utterances for temperature/humidity sensors: “What is the temperature/humidity here” and just “Temperature/Humidity”. Having another simpler utterance option ensures that the user has more than one way to get the appropriate information out of Alexa. In my case, I had to use the second, simpler utterance so that Alexa did not mix up the slot (key) words with other “fluff” words.

Coding AWS Lambda

In AWS Lambda, the code essentially looks for if the user said either “temperature” or “humidity”. If that is the case, then depending on either temperature or humidity, the path of referring the return function from Particle IDE is set according to that method’s respective tag name (“gettmp” or “gethmd”). After, AWS Lambda bundles all those parameters and sends a JSON request to the Particle API. However, in this case, the Lambda expected a return value from JSON, which then made Alexa say an appropriate statement with that respective value.

Coding Particle IDE

In the Particle IDE, the DHT library was used to get the specific functions that would enable me to get values on temperature and humidity detected by the temperature sensor. Therefore, after setting the loop interval for 10 seconds (a long delay so that the readTempeature method has enough time to read the temperature), the readTemperature/Humidity were type casted to integer values and then stored in variables temperature and humidity. Finally, they were returned  via the two getter functions (getTemperature and getHumidity).

Circuiting

The circuiting was modified a bit for the particle to accommodate the temperature sensor. First of all, the ground pin and the 3.3V pin were connected to negative (blue) and positive (red) side of the breadboard so that there were reference voltage grounds were created. Then, pin 1 of the temperature sensor was connected to the red side, pin 4 was connected to the blue side (to establish a voltage difference in the temperature sensor), and pin 3 was connected to pin D2 of the photon device with 10k ohm resistor connected in parallel to limit the current flow.

References

Please refer to the base project description here and the GitHub code here.

Schematics
milestone_1_fritzing-min
Particle Code

Temperature and Humidity Code

// This #include statement was automatically added by the Particle IDE.
#include <DHT.h>

// This #include statement was automatically added by the Particle IDE.
#include "DHT.h"

#define DHTPIN D2
#define DHTTYPE DHT22

#define DELAY 2000

DHT dht(DHTPIN, DHTTYPE);
int temperature = 0;

int humidity = 0;
int lastTemp = 26;
int lastHumidity = 50;
// Returns temperature
int getTemperature(String args){
    return temperature;
    //return (int)dht.readTemperature();
}

// Returns humidity
int getHumidity(String args){
    return humidity;
    //return (int)dht.readHumidity();
}

void setup() {
    Serial.begin(115200);
    //Serial.begin(2000);

    dht.begin();
    //pinMode(D2, INPUT);
    // Particle Functions
    Spark.function("gettmp", getTemperature);
    Spark.function("gethmd", getHumidity);

}

void loop() {
    // Get temperature and humidity

    //temperature = 0;
    //humidity = 0;
    temperature = (int)dht.readTemperature();
    //delay(2000);
    humidity = (int)dht.readHumidity();
    Particle.publish("temp",temperature+"");
    Particle.publish("humidity", humidity+"");
    /*if(temperature == 0){
        lastTemp = temperature;
    }
    if(humidity == 0){
        lastHumidity = humidity;
    }*/
    Serial.println();
    Serial.print("Temperature: ");
    Serial.println(temperature);
    Serial.print("Humidity: ");
    Serial.print(humidity);
    Serial.println();

    delay(DELAY);
}

AWS Lambda Code

Temperature and Humidity Code

Particle.prototype.intentHandlers = {
    // register custom intent handlers
    ParticleIntent: function (intent, session, response) {
    var sensorSlot = intent.slots.sensor;

    var sensor = "";
    sensor = sensorSlot ? intent.slots.sensor.value : "";

    var speakText = "";

    console.log("Sensor = " + sensor);
    //response.tell(light);
    var op = "";

    // Replace these with action device id and access token
    var deviceid = "410022000247363339343638";
    var accessToken = "bd3b676c56061a314c1f7d1d455258aab7f1c0c2";

    var sparkHst = "api.particle.io";

    console.log("Host = " + sparkHst);

    // Check slots and call appropriate Particle Functions
    if(sensor == "temperature"){
        speakText = "Temperature is 69°";

        op = "gettmp";

    }
    else if(sensor == "humidity"){
        speakText = "Humidity is 75%";

        op = "gethmd";
    }

    // User is asking for temperature/pressure
    if(op.length > 0){
    var sparkPath = "/v1/devices/" + deviceid + "/" + op;
    //response.tell(sensor);
    console.log("Path = " + sparkPath);
    if(op == "gettmp" || op == "gethmd"){
        makeParticleRequest(sparkHst, sparkPath, "", accessToken, function(resp){
        var json = JSON.parse(resp);

        console.log(sensor + ": " + json.return_value);

        response.tellWithCard(sensor + " is " + json.return_value + ((sensor == "temperature") ? "°" : "%"), "Particle", "Particle!");
        });
    }
    else{
        response.tell("Sorry, I could not understand what you said");
    }

    /*exports.handler = function (event, context, callback) {
        // Create an instance of the Particle skill.
        console.log("event name: " + event.Humidity);

        //var particleSkill = new Particle();
        //particleSkill.execute(event, context);
        response.tell(event.Humidity);
        callback("How ya doin", event.Humidity);
    };*/

    },
    HelpIntent: function (intent, session, response) {
        response.ask("You can ask me what is the temperature or humidity. You can also tell me to turn on Red or Green light!");
    }
};

Alexa Skill Set Code

Temperature and Humidity Skills

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "particle",
            "intents": [

                {
                    "name": "ParticleIntent",
                    "slots": [
                        {
                            "name": "sensor",
                            "type": "LITERAL"
                        }

                    ],
                    "samples": [

                        "ParticleIntent {humidity|sensor}",
                        "ParticleIntent {temperature|sensor}",

                        "ParticleIntent what is the {temperature|sensor} here",
                        "ParticleIntent what is the {humidity|sensor} here",

                    ]
                }

            ],
            "types": []
        }
    }
}

First Milestone

Goal

For my first milestone, I got the red and green LED lights to turn on and turn off by giving verbal commands to Alexa. The general process flow is that the Alexa recognizes the specific commands that the user gives, which is then passed to the endpoint of the Alexa skill set, which is the AWS Lambda service. The AWS Lambda then takes key parameters called slots and sends the data over to the particle API. The particle handles this process by passing the parameters to one of its functions, which then turns on or off the respective LEDs.

Setting Up Alexa Skill Set

First off, I defined the prompts that Alexa would respond to when it would perform the respective actions. For this, I first used an intent schema file downloaded from Github. This JSON file basically serves to use a predefined function of the Alexa which determines how Alexa will handle the request. In that intent, I defined three slots: sensor, light, and onoff. Although I am not using sensor right now, the slots define how to handle conditional user commands. For example, if I say “Alexa, ask particle to turn on red light”, the two conditional key words are “red”, “light”, and “on” because they can change depending on what the user says (“on” to “off, “red” to “green”, etc).  These slot types are LITERAL, which essentially means that it could accept any length of user commands that I could code it to take in, but since its best to keep them short so that Alexa doesn’t get confused, I limited the slots to take in basic commands such as on, off, red, etc.

Coding AWS Lambda

Next, I modified the GitHub code for AWS Lambda, which had two files: Index.js and AlexaSkill.js. AlexaSkill.js handled the background process of handling the exceptions, errors, and calling certain functions when the user gave his or her command. The main code was in Index.js, which sent specific parameters to the Particle API depending on user input, and then the Particle API would perform specific actions upon recieving those parameters. Essentially, what AWS Lambda did was it first connected the Lambda to the Alexa Skill Set by using its APP ID. After forming this connection, Lambda would receive all the inputs that Alexa would receive. Therefore, in order to handle the input types, the ParticleIntent function took three inputs: intent, session, and response. The first thing that function did was pull the slot data from the intent value that was passed in and stored it as string values. These slot values were for sensor, light, and onoff. The sensor slot is not being used yet (which will be my second milestone), but there were two other empty string variables that I used: pin and pinValue. Variable pin stored either pin value D0 or D1 depending on whether variable light stored red or green and variable pinValue stored the state of the pin as either HIGH or LOW depending if variable onoff had “on” or “off” respectively. Then, the lambda code checked whether the string length stored in variable pin was greater than zero. This way, the code checked whether the user was asking for temperature or telling Alexa to control the lights (if it would have been temperature, then pin variable would never be instantiated in the first place since there would be no slot returned from intent for light). After that, the code basically defined a path to the control function defined in Particle by referring to it as “ctrlled” (this is the ‘tag’ of the function in Particle which other programs could refer to it via cloud). Next, the code packaged the pin and pinValue variables by attaching them into a string called args, and all the variables defined in the previous steps, sparkHst (referring to Particle API), sparkPath (path to the control function), args (combined string of pin and pinValue), and accessToken (used to access the particular Photon device that I had) to a user-defined function (written by the coder) called makeParticleRequest. This function then packages all the variables into a single variable called options, which is then sent over to the Particle API in utf-8 encoding.

Coding Particle IDE

In order to do this, I connected the red LED to pin D0 and green LED to pin D1. These two pins are digital pins, which means they either pass the maximum voltage that Particle can allow for (3.3 V) or they don’t pass any. After initializing these pins as output pins and setting the voltage as zero (stated as LOW in the code), the controlled function took the args String passed from AWS Lambda and separated it into two values: strPin and strValue. Then, the two integer values were defined, pin and value, that were set to default D0 and HIGH. Next, the if-else statements first checked what pin was passed by comparing the strPin to either “D0” or “D1” string. Respectively, the integer value pin was set as either D0 or D1. Similarly, the pin value was checked by comparing strValue to either HIGH or LOW, and the integer variable value was set as either HIGH or LOW. Finally, the digitalWrite function, which gives the Photon device command to control current depending on pin and value of voltage, was used to perform the action by passing in the integer variables pin and value.

Circuiting

The circuiting was relatively simple, with the red LED connected to the pin D0 and the green circuit connected to the pin D1. The red pin was connected to the 10k ohm resistor while the green pin was connected to 220 ohm resistor (since it was not lighting as bright with the 10k ohm resistor, thus requiring more current to pass through it by lowering the resistance value), which ran to the ground. Finally, I ensured that the LEDs won’t malfunction because they accepted anywhere from 3.3V to 5V while the Photon device sent a total voltage of 3.3V from its digital pins.
Particle Code

LED Code

int controlled(String args){
    int pos = args.indexOf(',');

    if(-1 == pos){
        return -1;
    }

    String strPin = args.substring(0, pos);
    String strValue = args.substring(pos + 1);

    Serial.println();
    Serial.print("Pin: ");
    Serial.print(strPin);
    Serial.print(" ");
    Serial.print("Value: ");
    Serial.print(strValue);
    Serial.println();

    int pin = D0;
    int value = HIGH;

    if(strPin.equalsIgnoreCase("D0")){
        pin = D0;
    }
    else if(strPin.equalsIgnoreCase("D1")){
        pin = D1;
    }
    else{
        return -2;
    }

    if(strValue.equalsIgnoreCase("HIGH")){
        value = HIGH;
    }
    else if(strValue.equalsIgnoreCase("LOW")){
        value = LOW;
    }
    else{
        return -3;
    }

    digitalWrite(pin, value);

    return 1;
} 
void setup() {
    Serial.begin(115200);
    //Serial.begin(2000);

    dht.begin();

    pinMode(D0, OUTPUT);
    pinMode(D1, OUTPUT);

    Particle.function("ctrlled", controlled);

}

AWS Lambda Code

LED Code

Particle.prototype.intentHandlers = {
    // register custom intent handlers
    ParticleIntent: function (intent, session, response) {
        var lightSlot = intent.slots.light;
        var onoffSlot = intent.slots.onoff;

        var light = "";
        var onoff = "";

        light = lightSlot ? intent.slots.light.value : "";
        onoff = onoffSlot ? intent.slots.onoff.value : "off";

        var speakText = "";

        console.log("Light = " + light);
        console.log("OnOff = " + onoff);

        var pin = "";
        var pinvalue = "";

        // Replace these with action device id and access token
        var deviceid = "410022000247363339343638";
        var accessToken = "bd3b676c56061a314c1f7d1d455258aab7f1c0c2";

        var sparkHst = "api.particle.io";

        console.log("Host = " + sparkHst);

        // Check slots and call appropriate Particle Functions

        if(light == "red"){
            pin = "D0";
        }
        else if(light == "green"){
            pin = "D1";
        }

        // User is asking to turn on/off lights
        if(pin.length > 0){
            //response.tell("Im here");
            if(onoff == "on"){
                pinvalue = "HIGH";

            }
            else{
                pinvalue = "LOW";
            }

            var sparkPath = "/v1/devices/" + deviceid + "/ctrlled";
            console.log("Path = " + sparkPath);

            var args = pin + "," + pinvalue;

            makeParticleRequest(sparkHst, sparkPath, args, accessToken, function(resp){
            var json = JSON.parse(resp);

            console.log("Temperature: " + json.return_value);

            response.ask("Continue?");
            });
            //response.tell(args);
        }
        else{
            response.tell("Sorry, I could not understand what you said");
        }

        /*exports.handler = function (event, context, callback) {
            // Create an instance of the Particle skill.
            console.log("event name: " + event.Humidity);

            //var particleSkill = new Particle();
            //particleSkill.execute(event, context);
            response.tell(event.Humidity);
            callback("How ya doin", event.Humidity);
        };*/

    },
    HelpIntent: function (intent, session, response) {
        response.ask("You can ask me what is the temperature or humidity. You can also tell me to turn on Red or Green light!");
    }
};

Alexa Skill Set Code

LED Skills

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "particle",
            "intents": [

                {
                    "name": "ParticleIntent",
                    "slots": [

                        {
                            "name": "light",
                            "type": "LITERAL"
                        },
                        {
                            "name": "onoff",
                            "type": "LITERAL"
                        },

                    ],
                    "samples": [

                        "ParticleIntent {green|light} ",
                        "ParticleIntent {red|light} ",

                        "ParticleIntent turn {off|onoff} {green|light} light",
                        "ParticleIntent turn {off|onoff} {red|light} light",
                        "ParticleIntent turn {on|onoff} {green|light} light",
                        "ParticleIntent turn {on|onoff} {red|light} light"

                    ]
                },

                {
                    "name": "Lights",
                    "slots": [
                        {
                            "name": "onoff",
                            "type": "LITERAL"
                        },
                        {
                            "name": "light",
                            "type": "LITERAL"
                        }
                    ],
                    "samples": [
                        "ParticleIntent turn {off|onoff} {green|light} light",
                        "ParticleIntent turn {on|onoff} {red|light} light",
                        "ParticleIntent turn {off|onoff} {red|light} light",
                        "ParticleIntent turn {on|onoff} {green|light} light"
                    ]
                }
            ],
            "types": []
        }
    }
}

Starter Project

Description

My starter project was to create a MiniPOV, which is essentially a circuit with LED lights that changes color as it is moved and it can also display uploaded images when connected to the computer. The way this circuit works is that the current from the battery first goes to the capacitors, where charge from the current is stored in the electric field, which then stabilizes the voltage output. Then, the 2.2k ohm resistors restrict the current flow to the transistors so that the transistors do not malfunction. The transistors work to amplify the current which then goes through the microprocessor (Atmel ATMega328). This microprocessor is the “brain” of the circuit because controls the current flow to simulate the lights blinking through the LEDs according to MiniPOV’s movement. Finally, the current goes through the 47 ohm resistors which also controls the current flow to the LEDs so that the LEDs don’t dissipate more power than they are supposed to and as a result do not malfunction.

Learning Experience

One of the valuable skills I learned during this experience is how to solder, especially keeping a safe distance from the soldering iron (which I learned the hard way). Besides that, I gained valuable insight on how each component of the circuit board works in relation with the other components and especially the high stakes when the components are soldered incorrectly.

References

Please refer to the project description here.

Leave a Comment

Start typing and press Enter to search