Smart Home Automation, Iteration 1: Qwiic and PIRty
2021-04-01 | By Nate_Larson
License: See Original Project
One goal of a smart home is to automate simple, repetitive tasks using sensors such as the new SparkFun PIR sensor breakout boards. Below are two simple methods of adding some automation to a smart home using these PIR boards to detect room occupancy.
In my work-from-home (WFH) office/lab I have a smart light switch and a couple of smart power strips that control power to a weather display, soldering station, bench-top power supply, and other equipment. I have a bad habit of forgetting my soldering iron on, so my original thought was to use this smart power strip as a timer to automatically turn it off after a pre-defined period. However, since this was on the same control as other equipment on the power strip, I inevitably would find myself working on a project only to have everything power down unexpectedly. Adding occupancy detection to this would be an improvement, and if I was going to control this power strip, why not all the smart devices in the room?
In this first iteration of this project, I decided to use Blynk and an app on my Android phone called Tasker to create a quick proof of concept. I determined I could set up a routine in my Google Home account to control the power of everything in the room using a simple voice command, but I needed to trigger this routine using input from the sensor.
The idea behind this initial attempt was just to get this up and working as quickly as possible. So, I went with the Qwiic SEN-17375 sensor board. I plugged this into the MicroMod ATP carrier board and popped in the ESP32 MicroMod processor. With this, my hardware setup was now complete, all without ever having to heat my soldering iron.
Next, I installed the Blynk app on my smartphone, created an account, and created a new project called 'motion light'.
I set up this project to provide a push notification, which I will use later to tell the smart devices when to turn on or off.
Then I opened the Arduino IDE and installed the Blynk library using the library manager.
Once this was complete, I opened the Blynk example directory, clicked on the “Boards_WiFi” option, and then opened the ESP32_WiFi example.
/*************************************************************
Download latest Blynk library here:
https://github.com/blynkkk/blynk-library/releases/latest
Blynk is a platform with iOS and Android apps to control
Arduino, Raspberry Pi, and the likes over the Internet.
You can easily build graphic interfaces for all your
projects by simply dragging and dropping widgets.
Downloads, docs, tutorials: http://www.blynk.cc
Sketch generator: http://examples.blynk.cc
Blynk community: http://community.blynk.cc
Follow us: http://www.fb.com/blynkapp
http://twitter.com/blynk_app
Blynk library is licensed under MIT license.
This example code is in public domain.
*************************************************************
This example runs directly on ESP32 chip.
Note: This requires ESP32 support package:
https://github.com/espressif/arduino-esp32
Please be sure to select the right ESP32 module
in the Tools -> Board menu!
Change WiFi ssid, pass, and Blynk auth token to run :)
Feel free to apply it to any other example. It's simple!
*************************************************************/
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";
void setup()
{
// Debug console
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
}
void loop()
{
Blynk.run();
}
In this example, you need to add the authorization Token you should have received in your email when you created your project in the Blynk app. Also, you will need to fill in your Wi-Fi name and password. Then you can upload the code and check the serial output to ensure everything is operational.
Now that I knew my board was operational, it was simply a matter of incorporating the PIR sensor into the code. This was easy thanks to the SparkFun Qwiic PIR Arduino Library.
/******************************************************************************
Checks whether the PIR is detecting an object
Fischer Moseley @ SparkFun Electronics
Original Creation Date: June 28, 2019
Revised by Andy England, 1/5/2021
This code is Lemonadeware; if you see me (or any other SparkFun employee) at the
local, and you've found our code helpful, please buy us a round!
Hardware Connections:
Attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
Plug the button into the shield
Print it to the serial monitor at 115200 baud.
Distributed as-is; no warranty is given.
******************************************************************************/
#include <SparkFun_Qwiic_PIR.h>
QwiicPIR pir;
void setup() {
Serial.begin(115200);
Serial.println("Qwiic PIR examples");
Wire.begin(); //Join I2C bus
//check if pir will acknowledge over I2C
if (pir.begin() == false) {
Serial.println("Device did not acknowledge! Freezing.");
while (1);
}
Serial.println("PIR acknowledged. Waiting 30 Seconds while PIR warms up");
for (uint8_t seconds = 0; seconds < 30; seconds++)
{
Serial.println(seconds);
delay(1000);
}
}
void loop() {
//check if there is an available PIR event, and tell us what it is!
if (pir.available()) {
if (pir.objectDetected()) {
Serial.println("Object Detected");
}
if (pir.objectRemoved()) {
Serial.println("Object Removed");
}
pir.clearEventBits();
}
}
After reviewing the various example sketches, I decided the code in Example2_PrintPIRStatus provided what I was looking for and I could easily integrate this with the Blink ESP32_WiFi sketch.
Since the Blynk code running on the microcontroller is sending data over Wi-Fi, maintaining communication is critical, so they recommend not bogging down the MCU with extra code in the main loop of the code, but using a timer that fires at a specified interval to run and additional code. You can read about the timer requirements here, but I decided to have this timer check the PIR sensor once per second. Below is the final MCU code.
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <SparkFun_Qwiic_PIR.h>
QwiicPIR pir;
int on_delay = 2; //number of seconds with presence detected before turning on
int off_delay = 300; //number of seconds without presence detected before turning off
int presence = 0;
bool switchToggle = false;
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";
BlynkTimer timer;
void myTimerEvent()
{
if (pir.rawPIRReading() == true) {
Serial.println("Object Detected");
if (switchToggle){
presence = off_delay;
}
else {
presence += (off_delay/on_delay);
if (presence > off_delay){
presence = off_delay;
}
}
}
else{
Serial.println("Object Removed");
if (switchToggle){
presence --;
}
else {
presence = 0;
}
}
Serial.println(presence);
if (presence == off_delay && !switchToggle){
Blynk.notify("Turn on");
Serial.println("switched on");
switchToggle = !switchToggle;
}
else if (presence == 0 && switchToggle){
Blynk.notify("Turn off");
Serial.println("switched off");
switchToggle = !switchToggle;
}
}
void setup()
{
Serial.begin(115200);
Wire.begin(); //Join I2C bus
//check if pir will acknowledge over I2C
if (pir.begin() == false) {
Serial.println("Device did not acknowledge! Freezing.");
while (1);
}
Serial.println("PIR acknowledged. Waiting 30 Seconds while PIR warms up");
for (uint8_t seconds = 0; seconds < 30; seconds++)
{
Serial.println(seconds);
delay(1000);
}
// Debug console
Blynk.begin(auth, ssid, pass);
// Setup a function to be called every second
timer.setInterval(1000L, myTimerEvent);
}
void loop()
{
Blynk.run();
timer.run(); // Initiates BlynkTimer
}
In the above code, the MCU first verifies the PIR sensor is connected and working, then allows the sensor to settle for 30 seconds. Once that is complete, the board connects to the Blynk service and sets a timer for every 1000ms. Each time the timer is triggered, the MCU polls the PIR sensor. The switchToggle variable represents the status of the switch. If the switch, and thus the light and power strips in the room, are off and a presence is detected for two consecutive cycles, the switch is turned on and Blynk is notified. Additionally, if the switch is on and no presence is detected for 300 seconds, the switch is turned off and the Blynk app is again notified. Now that this code is uploaded to the board and running, each time Blynk is notified to “Turn on” or “Turn off”, this message pops up as a notification on my phone, so I just need to intercept this message and use it to trigger the Google routine using Google Assistant.
For the next step, I used Tasker since I already had it installed on my phone because I use it to automate several other tasks. To complete this, there are a couple of additional plugins needed by Tasker, those being AutoNotification, AutoInput, and AutoVoice.
While this theoretically could be done using a single Tasker profile, I was unable to set a variable according to the notification text received, so I set up two Tasker profiles to use AutoNotifications to watch for any notification from the Blynk app.
If a notification from the Blynk app is detected, the AutoNotification plugin checks the text of the notification, and if it is an exact match to “Turn on” or “Turn off”, it sets a variable to match the text of Google routine we want to trigger.
Once this variable is set, we use the task described here to send this message to Google Assistant. You can import this task using the link above, so you don’t have to recreate this work.
The great thing about this task is that if the phone’s screen is unlocked, it will simply pop up a Google Assistant window and send the message as if it was typed into the keyboard. Otherwise, if the screen is locked, it will open Google Assistant and send the message as a voice prompt.
From here, all that is left to do is go into the Google Home app and create a routine with the name specified previously.
Then, configure that routine to perform the desired application.
This first iteration, while it seems like a lot, is quick to set up and get functional, and can be completed in under an hour. While this method works, there are other ways of performing this task that don’t require all the third-party web services. In the second iteration of this project, I’ll review how we can add local control of smart devices without the use of Google Assistant.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum