Smart Home Controlller with PSoC and LinkIt ONE
One of the main features of a smart home controller is that it should be versatile. By versatile, I mean to every extent possible, and that is exactly what I thought when making this project.
It is basically a proof of concept project showing how you can use analog sensors attached with the PSoC Analog Co-Processor, send them to the Blynk server through LinkIt ONE via WiFi. IFTTT is then used to control your Nest Thermostat, your Philips Hue lights, your Garageio or anything ‘smart’ enough to connect to the internet, based on the analog sensor data from the PSoC.
Without further ado, let’s move on to the project itself.
The Blynk part
I will be using Blynk for this project with which users will have the benefit of connecting their Android as well as iOS devices.
Blynk allows you to connect your hardware to the cloud very quickly and easily. Widgets are present in the Blynk app and they can be dragged and dropped, and then configured to connect with your hardware in a variety of ways. This is my first project with Blynk, and from what I’ve seen, it’s extremely easy to build IoT apps with it.
So head over to blynk.cc on your smartphone, download the Blynk app for your platform (Android or iOS) and also, make an account or log in to your existing one.
Once done, I would recommend those who are new to Blynk to check out the “Getting Started” section here and also the sample LED project to get familiar with it.
When you are at this screen and are ready to proceed, press the QR code icon in the center and it will open your smartphone’s camera to scan a QR code.
It will create an exact copy of my project’s widgets. It will look something like this:
Press the nut icon and then press “Email all”. It will email the auth token for the project to your email address (The one which you registered for Blynk). Open the email address and note down the auth token, you will need it later.
Setting up the PSoC
To develop something for the PSoC Analog Co-processor the PSoC Creator IDE is used. So head over to the Cypress website and make an account if you haven’t already.
Then download PSoC Creator and the design files for the CY8CKIT-048 board, or you could just download the complete setup package from here, which has the PSoC Creator IDE and the files for the CY8CKIT-048 board. Install that, and once you’re done with installation, download the attached project file and open that using the PSoC Creator IDE.
Note: I am using PSoC Creator IDE v3.3, from the complete setup package linked above.
The code is the Environment Sensing Demo project (Thank you very much Michiyuki Yoneda) modified by me to run with UART (It uses I²C originally along with Bridge Control Panel).
The modification I did to the Environment Sensing Demo project is that I added the UART component in the TopDesign.cysch file.
Then I added the following code in the main.c file:
sprintf (stringTemp, "%d", ProcessValues.Temperature);
sprintf (stringIlluminance, "%d", ProcessValues.LightIntensity);
sprintf (stringPIR, "%d", ProcessValues.PIRTrigger);
sprintf (stringHumi, "%d", ProcessValues.Humidity);
sprintf (stringMetalDetected, "%d", ProcessValues.IPSTrigger);
char checkUART = UART_UartGetChar();
if (checkUART == 's') {
UART_UartPutString(stringTemp);
UART_UartPutString(",");
UART_UartPutString(stringIlluminance);
UART_UartPutString(",");
UART_UartPutString(stringPIR);
UART_UartPutString(",");
UART_UartPutString(stringHumi);
UART_UartPutString(",");
UART_UartPutString(stringMetalDetected);
UART_UartPutString(".");
}
Programming and testing the PSoC program:
Ensure that the jumpers and switches are set to the default position as in the picture below:
Attach the PSoC to your PC with a USB Cable and press Ctrl+F5 to program the board.
Once successfully programmed, open a terminal program (Like PuTTY or Tera Term), set the baud rate to 9600 and set the COM port to the “KitProg2 USB-UART” port.
You will see there is no serial output at all from the board. Do not worry, press “s” on your keyboard. You will instantly send a formatted string, containing data from each sensor present on the PSoC.
This means that the program is successfully uploaded on the PSoC and you can go on to the next part of the project.
Setting up the LinkIt ONE
Now that you have programmed the PSoC, set that aside and get the LinkIt ONE. Check the switch positions on the LinkIt ONE and set them up as in the image below.
Then connect that to your PC with a USB cable, open Device manager and under “Ports (COM & LPT)”, find the COM port for “MTK USB Debug Port” and note it.
Note: You will need to have set-up the LinkIt ONE before using the “Getting Started” instructions from the MediaTek Labs website here. I won’t go into the set-up here as there are many resources online, if you have any problems with setting it up, google them or comment.
Go here and download the Blynk Library for the Arduino IDE, and then install it.
Note: If you need instructions for installing Arduino libraries, go here.
You will have a quite a few libraries, just confirm once that “Blynk” and “SimpleTimer” are present as those are needed.
Then, download the LinkIt ONE project file. Open it and make a few changes.
Write the auth token for Blynk which you noted earlier and your WiFi SSID and password, as well as the security protocol:
char auth[] = ""
char ssid[] = ""
char pass[] = ""
int wifi_sec = LWIFI_WPA
Then upload the code to your LinkIt ONE. When it’s done successfully, unplug the LinkIt ONE from your PC, attach the WiFi antenna to the LinkIt ONE and also set the switch to “BAT” as in the image below, but don’t connect the battery yet.
Now get the PSoC, and plug it in the LinkIt ONE as an Arduino shield, using the images below as reference.
Once done, read on!
Testing the PSoC with the LinkIt ONE
On your smartphone, open the Blynk app and press the play button. You will get a message that your device is offline, ignore it.
Connect the battery to the LinkIt ONE. The light on the PSoC will light up and in a few seconds, your the Blynk app on your smartphone will look something like this:
Plug in the USB cable on the LinkIt ONE and in your PC, and the result:
Now take the metal disc included with the PSoC, and hold it close to the proximity sensor on the PSoC.
Troubleshooting:
If you don’t get any values or any result, or keep getting any sort of error
- Read the instructions carefully, maybe you missed something.
- If you have any errors in Blynk, and the rest is fine, check out their troubleshooting section here. I did not have any problems at all with it, everything went very smoothly.
- Comment and I’ll try my best to help you out.
How the code works:
The PSoC waits for a character to be sent (“s” in this case), when the character is received, it instantly sends an unformatted string back containing the sensor values.
The LinkIt ONE sends the character and receives the unformatted string. Using the “LBattery.h” class from its own API, the LinkIt ONE also checks if the battery is charging and the battery percentage. The battery percentage returns four possible values: 0, 33, 66, 100.
Getting all the above values, from the PSoC as well as the LinkIt ONE battery status happens every 80ms, using the SimpleTimer library’s timed functions:
timer.setInterval(80L, getValuesEvent);
Another timed function is present, which sends all the values to the Blynk server. In the attached code, this happens every 1000ms (or 1 second), but the time can (and should) be changed as per the users requirements.
timer.setInterval(1000L, sendValuesEvent);
A function used in void setup()
sets the color of the widgets from the PSoC:
void setSensorWidgets() {
//Set temperature widget color to white
Blynk.setProperty(vTEMP_PIN, "color", WHITE);
//Set light widget color to yellow
Blynk.setProperty(vLIGHT_PIN, "color", YELLOW);
//If motion detected, set LED to red
Blynk.setProperty(vPIR_PIN, "color", RED);
//Set humidity widget color to red
Blynk.setProperty(vHUMI_PIN, "color", BLUE);
//If motion detected, set LED to red
Blynk.setProperty(vPROX_PIN, "color", GRAY);
}
Another function is used every time data is sent to Blynk. This sets the color of the battery percentage widget based on the current value:
void setChargeWidget() {
//Set color of charge indicator LED
Blynk.setProperty(vCHARGE_PIN, "color", "#FF9000");
//Set color of battery percentage, based on value
if (b == 100) {
Blynk.setProperty(vBAT_PIN, "color", "#1EBF00");
}
else if (b == 66) {
Blynk.setProperty(vBAT_PIN, "color", "#A5CB00");
}
else if (b == 33) {
Blynk.setProperty(vBAT_PIN, "color", "#D87200");
}
else if (b == 0) {
Blynk.setProperty(vBAT_PIN, "color", "#E5001E");
}
}
By now, you should have a pretty good idea of how the code works. So now, move on to the next part.
Note: If you need to change the color of the widgets, you can easily do so by editing the LinkIt ONE code. Get the hex value of the color code you want and replace it in the code. If you want to manually change the color from the Blynk app, just comment out setSensorWidgets();
and setChargeWidget();
as needed.
Customizing the Blynk interface
I have set that all the data sent to Blynk is through virtual pins. You can read more about them here.
These are the virtual pins I am using:
#define vBAT_PIN V2 //Set battery level to virtual pin 2
#define vCHARGE_PIN V3 //Set charge status to virtual pin 3
#define vTEMP_PIN V5 //Set temperature value to virtual pin 5
#define vLIGHT_PIN V6 //Set light value to virtual pin 6
#define vPIR_PIN V7 //Set pir value to virtual pin 7
#define vHUMI_PIN V8 //Set humidity value to virtual pin 8
#define vPROX_PIN V9 //Set proximity value to virtual pin 9
When you know this, you can easily modify the Blynk interface by using other widgets.
Note: The Reading Frequency of any widget you use should be set to “PUSH” which means that the widget doesn’t request data every time, the hardware itself sends it as a timed function, using the SimpleTimer Library.
Instead of using horizontal Level widget for ambient light, you could use the Gauge widget:
You could use the Graph widget to plot received data in a graph in real-time:
Or you could use the History Graph widget, which will store all your past values (without the app being on on the smartphone) but it has some conditions, you can read about them here. This is an example of using the History Graph widget:
Along with this, there is another Widget in Blynk called Eventor which you can read about here.
Straight from the Blynk website:
Eventor widget allows you to create simple behaviour rules or events
So using Eventor, you can set simple rules, like if the temperature increases above a specified limit, say 40°C, it sends you a notification on your smartphone. And you don’t need to do any extra coding for it, or re-program your existing hardware. You just need to send the temperature to Blynk like you normally do:
Blynk.virtualWrite(vTEMP_PIN, t);
Note: If you use the notification option with the Eventor widget, remember to add the Notification widget otherwise it will not work.
Along with all the above, Blynk many other Widgets too, which I haven’t yet mentioned. A few of them are:
- Button
- Slider
- Timer
- Joystick
- Terminal
- Video Streaming
- Webhook
- Push Notifications
Note: This will help you in customizing the project for your needs:
- To send an email with Blynk (details here):
Blynk.email("my_email@example.com", "Subject", "Your message goes here");
- To tweet with Blynk (details here):
Blynk.tweet("Hey, Blynkers! My Arduino can tweet now!");
- To send a push notification with Blynk (details here):
Blynk.notify("Hey, Blynkers! My hardware can push now!");
Read on to see how we can use these Widgets to customize your project as per your requirements.
Blynk and IFTTT, and more!
From this point everything I write in this section, is proof of concept. I have not tested it – yet, but there is no reason that it won’t work. So if you have the resources, test it out, and do comment with the results.
That being said, most of you must know about IFTTT. For those who don’t, the Wikipedia definition is below:
IFTTT is a free web-based service that people use to create chains of simple conditional statements, called applets. An applet is triggered by a change on another web services, such as Gmail, Facebook, Instagram, or Pinterest. IFTTT is an initialism for If This Then That.
You should get an idea about IFTTT after reading that. If not, head over to the IFTTT website and check out a few recipes.
When you are a bit familiar with IFTTT, and know a bit about applets and recipes, think of how you can use Blynk with IFTTT.
I did exactly that, and got quite a few ideas. Think of a scenario:
- It’s the middle of the night and you are sleeping. Your Philips Hue bulb changes its dim warm light (Sleep mode) and suddenly starts flashing red and an alert siren sounds. You wake up, sensing danger. You go outside, armed (???) and see your cat jumping about. You breathe a sigh of relief, put the cat back to sleep and then go back to sleep yourself.
Now, what has happened in the above scenario?
The PIR motion sensor on your PSoC has detected motion. It sends the data to the LinkIt ONE, which sends it to Blynk. In Blynk, using the Webhook widget (Go here for details) the motion detected by the PIR sensor goes to the IFTTT Maker Channel (Again go here for details) as a POST request. That in turn triggers your Philips Hue light and tells it to flash red. For details about the alert siren, read the next section.
How can that be done – the technical part?
Night-time could be set using the Timer widget in Blynk. That way the user can change it through the Blynk app itself, no need for uploading code again to the LinkIt ONE.
Description of the Timer widget straight from the Blynk website:
Timer triggers actions at a specific time. Even if smartphone is offline. Start time sends 1 (HIGH). Stop time sends 0 (LOW).
You could add something like this to the attached LinkIt ONE code:
First define this as a global variable:
int timerValue;
Add this to the main code:
BLYNK_WRITE(vTIMER_PIN)
{
// You'll get HIGH/1 at startTime and LOW/0 at stopTime.
// this method will be triggered every day
// until you remove widget or stop project or
// clean stop/start fields of widget
int timerValue = param.asStr();
}
And then wrap the following code snippet in a new or existing timed function, as you need it:
//Check if it is night-time
if (timerValue == 1) {
//If yes, check if motion is triggered
if (p == 1) {
//Trigger webhook pin if motion detected
Blynk.virtualWrite(vWEBHOOK_PIN, value);
}
else if (p == 0) {}
}
else if (timerValue == 0) {
//Do nothing
}
You could just as well tweet and get it to work. That way, the IFTTT trigger would be a Twitter applet and the LinkIt ONE code would be something like:
//Check if it is night-time
if (timerValue == 1) {
//If yes, check if motion is triggered
if (p == 1) {
//Send tweet if motion detected
Blynk.tweet("Motion is detected!");
}
else if (p == 0) {}
}
else if (timerValue == 0) {
//Do nothing
}
The Webhook pin will be set to trigger the IFTTT Maker channel. Once that is done, an applet needs to be made, with the Maker channel as the trigger and the resulting action will be that your Philips Hue light will flash red.
Note: Surely you could do the same thing with the Philips Hue motion detector accessory, but this is DIY plus you get all the sensors data in one customizable interface.
You yourself set up the trigger (HTTP/S request to the IFTTT Maker channel) and the resulting action; this means that instead of flashing your Philips Hue light, you could even get your smart Dishwasher to start once the PSoC detects motion.
You could literally get anything ‘smart’ (even if it isn’t ‘smart’, read the next section to make it ‘smart’), and easily make it work with “IF This Then That” statements, using the analog sensor data from the PSoC. The possibilities would be limited by your own imagination and abilities, both on the PSoC side for analog sensors and on the IFTTT and Blynk side.
Think of the number of ways you could do that. You could use Blynk to send an email once a condition is met, for example room temperature, and IFTTT to check if the email is received and IFTTT again to set a resulting action, setting up the Nest Thermostat, or alerting you with an SMS.
Garageio can be used as well, with Blynk tweeting something and IFTTT waiting for the tweet and controlling your garage door, once it gets the tweet.
You can use Amazon Alexa to alert you whenever temperature rises, motion is detected or humidity is low, using the webhook, email or Twitter widget.
An IFTTT applet would need to be made, as well as a small addition to the LinkIt ONE code. But believe me, the hard part is already done, this is very easy and anyone with minimal experience with HTTP/S requests can do it. Read on if you need an example on how to make an IFTTT applet.
Even without IFTTT, Blynk itself is very powerful to get most of your requirements. For example, the GPS widgets in Blynk:
The LinkIt ONE code has variables I have not defined. each user can use them for there own needs:
//Define email address you need to set for IFTTT
#define emailAddress ""
//Define light sensor threshold
#define lightThreshold ""
//Define temperature maximum and minimum values
#define maxTemp ""
#define minTemp ""
//Define humidity maximum and minimum values
#define maxHumi ""
#define minHumi ""
You could use the proximity sensing of the PSoC too, to customize it for anything you like.
Note: Using the Webhook widget we can currently send a request to one URL at a time, configured through the Blynk app; therefore, you will need to adjust and use e-mail, notification, and tweets, depending upon the task and its priority.
The thing is, if you’re able to get IFTTT running with the motion sensor, you can just as well do the same with the temperature, humidity, proximity and ambient light sensors; now you should think why I used the word ‘versatile’ for this in the start of the project.
Make an IFTTT applet work with Blynk:
Above, I have described ways to integrate IFTTT with Blynk. This part will describe how you can make a simple IFTTT applet based on PSoC values.
In the LinkIt ONE code, you will need to add something like:
//Check if temperature is greater than 40
if (t > maxTemp) {
//If yes, send an e-mail
Blynk.email("my_email@example.com", "Subject", "Your message goes here");
}
else() {
//Do nothing
}
This would need to be wrapped in an existing timed function or create a new timed function with the SimpleTimer library (details here):
timer.setInterval(2000L, tempAlertEvent);
Look at the pictures below for the IFTTT part:
When done, congratulations, you have made a SMS alert which checks the temperature from the PSoC, if it is more than 40°C, it sends an SMS alert on your mobile phone.
Uploading data to Thingspeak, through Blynk:
Thingspeak is a very popular platform for IoT applications where you can use MATLAB analytics and visualizations on your data.
We can send the PSoC sensor data to Thingspeak too. Normally, this would need code like this:
WiFiClient client;
if (client.connect("api.thingspeak.com", 80)) {
client.print("POST /update HTTP/1.1n");
client.print("Host: api.thingspeak.comn");
client.print("Connection: closen");
client.print("X-THINGSPEAKAPIKEY: " + apiKeyThingspeak1 + "n");
client.print("Content-Type: application/x-www-form-urlencodedn");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("nn");
client.print(postStr);
}
This isn’t complete, it’s just to give an idea how to do it (Code snippet obtained from Blynk website).
The biggest advantage of using Thingspeak in this situation, is that you can view your data on a PC as well (also the powerful MATLAB visualizations); Blynk can only display the data on a smartphone app.
But, with the Webhook widget, we can easily upload the values to Thingspeak with very little code. You can read about how to do that on the Webhook part of the Blynk website here.
When I get the time, I’ll edit this with proper instructions on how to send data to Thingspeak through Blynk.
Final touches
Now that we have discussed the setup of IFTTT and Blynk, we move towards final touches of the smart home controller.
As for every microcontroller project, this also needs an enclosure. The enclosure will be designed using Blender, an open-source software.
I wanted the system to be ‘versatile’, that is why I decided that I would use the Grove Starter Kit from Seeedstudio. The Grove system comprises of small plug and play modules (sensors, lights, actuators,etc) and a base shield, which you can plug in a microcontroller. You can read about the Grove system here.
I will be using the Arduino 101 Grove Starter kit for this. It has the Grove Base Shield v2 along with quite a bit of stuff. You can find that here.
I thought a display should also be present in the project, to show the sensor values. Because of that, I chose the Grove Starter kit containing the RGB Backlight LCD Display v4.0 which works using the I²C protocol. But for some reason, I couldn’t get it to work with the LinkIt ONE, Grove Base Shield v2 and the PSoC, however much I tried, despite the help of Michiyuki Yoneda from Cypress. However, I will still include the display in the enclosure with the hope that I get it to work sometime in future.
An LED will be needed to indicate when the LinkIt ONE’s battery is charging. Pin 8 is used for that and I will be using the Grove LED Socket and a red LED. You can easily change the pin number in the code.
In the scenario in the last section, I had said that an alert siren would sound. That would be done using the Grove Buzzer, if the user requires. It can easily be used by setting it as an output and setting it as “HIGH” whenever you need it (when motion is detected for example).
Plug in Grove Base Shield on the LinkIt ONE, then plug in the cables on the Grove modules you need to use.
Note: In the code attached, I have only used the LED Socket module. If you need to add more modules, you need to change the code as well!
Wireless Charging:
I will add wireless charging to the project using the FT1235 5W transmitter and an FT1236 5W receiver, developed by Futara Elettronica.
I soldered the receiver and transmitter coils to each of them, and then soldered the pin headers.
Then cut a spare USB micro Type B cable, find the right wires for VCC and Ground using a multimeter and the screenshot from Wikipedia below:
Attach the OUT pin on the transmitter to the VCC on the micro-B cable, and GND to ground respectively.
Once done, confirm the wiring again. If you reverse them, it would damage the LinkIt ONE, and probably the PSoC too!
Then on the transmitter side, get a 5volts 2A power adapter and wire it up correctly to VIN and GNDA.
Attach the battery to the LinkIt ONE, and plug in the modified USB micro-B cable you made earlier. You should see the LED on the Grove Socket light up (Charge indicator LED). If not, check your wiring.
Some pictures to help you set it up, though it’s very simple!
And a picture the LinkIt ONE being powered wirelessly, to show it all works:
The Display:
Using a display was a feature I wanted to add, but I couldn’t get it to work with the PSoC as a shield, but when using 2 wires for UART and connecting them to the Grove Base Shield it worked. So I didn’t include this now in the final submission. If I get it to work I certainly will edit this.
I had even set up the zeRGBa widget in Blynk to set the rgb backlight for the I²C display and it worked perfectly – without the PSoC connected. When I attached the PSoC, the code would just hang until I removed it, and once removed, it worked flawlessly.
If you don’t have smart devices (Philips Hue,etc):
If you do not have smart devices like Philips Hue, Garageio or the Nest Thermostat, do not worry.
There is another alternative! You can use relays (The Grove relay can be found here), connect them to the Grove Base Shield v2. With each relay, you can connect bulbs, garage door motors and other actuators.
It would just be a matter of setting any digital pin “HIGH” to control the relay. And the Blynk part is also very easy.
You could use the Grove Stepper motor, by making a mechanism with your curtains and getting them to work with the PSoC ambient light sensor values, when the value falls below the threshold, you can define an action.
The Enclosure:
Plug in all the boards, all the cables and the modules you need, it should look something like this.
Also, a switch could be used, on the LinkIt ONE battery’s positive terminal, to cut off power when not needed.
Look at the attached design of the enclosure. I do not yet have the luxury of a 3D printer, or even access to one, so I can’t print an enclosure currently. Maybe sometime in future, when I get one, I’ll add pictures of the actual result, but for now it’s just a rendering.
The wireless receiver is present at the base of the box.
Note: The purpose of the enclosure is just to show what I intended to make, and this is in no way exactly according to dimensions of the actual products.
The Ending:
Although it looks complicated, the end user has very less work to do, compared to the tasks this can accomplish. The basic Blynk interface, PSoC and basic LinkIt ONE code is already present, the end user will have to customize it to his/her own liking.
For the PSoC, I have focused more on collection of the data, and used all the five onboard sensors as a proof of concept. This means you just need to create the schematic for the sensor you want to interface , attach it to the PSoC, and send the value to LinkIt ONE as I did.
The ample code memory in the LinkIt ONE along with the features of GSM, GPRS and the external SD card, can accomplish much more with the same hardware. For example, with a bit of addition in code, the LinkIt ONE can also dump all the values on a micro SD card.
Be certain to leave your comments and tell me what you think of it.