49713 Designing for the Internet of Things
· 16 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Help your mini cactus get enough direct sunlight every day!
Taking Care of Your Mini Cactus - Lesson 101
Like most plants, Cacti use photosynthesis for generating its energy and store their own supply of water. A mini-cacti requires about 4 hours of direct sunlight daily. Without adequate sunlight, cacti become thin and sickly.
Wait, but... how do I know it's getting enough sunlight or not?
Don't worry. The Cactus Buddy is here to help you take care of your mini cactus in several ways:
1. Provide real-time feedback on the intensity of the sunlight (direct sunlight / low sunlight / no sunlight)
--> so you'll know where might be the best location to place it
2. Provide daily notification on how much direct sunlight it has been exposed to
--> so you'll know whether it has gotten enough direct sunlight for the day
I decided to apply the idea (from the reading "Breakaway: an ambient display designed to change human behavior") of changing user's behavior by providing abstract information.
To do this, my device should be able to:
1. Sense the intensity of sunlight and display the information in an abstract way
- The intensity of sunlight can be grouped into 3 levels [direct sunlight/low sunlight/no sunlight]
- The 3 levels should be visually communicated in real-time [I was inspired by Lua]
2. Track the total time of the direct sunlight and inform the user in a non-intrusive way
- The device should calculate the total time of direct sunlight for the day
- The notification of the daily statistics and tips sent to the user should be limited to once per day
My idea was to display the icon of various sunlight levels on a rotating panel and to show the in situ status through a cut-out "window." I developed this idea in incremental steps:
In the beginning, I played with the servo to test out the possibility of rotating it to my desired angles. I looked up the servo tutorial from the IoT course site and Particle documentation. And it worked well.
Initially I only tested the device with two rotating angles: 0 degree and 180 degrees. When I proceed to add a third angle, 90 degrees, I encountered some challenges to get it to work. It took some time for me to identify the issue (I only considered the clockwise rotation and forgot to consider the counter-clockwise rotation) and re-structured my codes (adding a pos < 90 condition) to resolve it.
// version 6.0: servo + photoCell sensor (3 light intensity levels) + share more data with Particle cloud + publish data to IFTTT + button (on/off)
Servo myservo; // create servo object to control a servo
int pos = 0; // variable to store the servo position
// Photo cell pin
// Remember to add a 10K Ohm pull-down resistor
int photoCellPin = A0;
// Create a variable to hold the light reading
int photoCellReading = 0;
// Push-button wired to D0
int buttonPin = D0;
// device on/off status controlled by the push-button
int deviceOn = 1;
String deviceOnStr = "";
// Lighting status (Direct Sunlight; Low Sunlight; No Sunlight)
String sunlightStatus = "";
// store no. of hours of Direct Sunlight
double direct_Sunlight_Hours = 0;
String direct_Sunlight_Hours_Str = "";
// store no. of hours of Low Sunlight
double low_Sunlight_Hours = 0;
String low_Sunlight_Hours_Str = "";
void setup()
{
myservo.attach(D2); // attaches the servo on the D2 pin to the servo object
// Only supported on pins that have PWM
// For input, we define the
// pushbutton as an input-pullup
// this uses an internal pullup resistor
// to manage consistent reads from the device
// sets pin as input
pinMode( buttonPin , INPUT_PULLUP);
// Create a cloud variable of type String
Particle.variable("Device_Status", deviceOnStr );
// Create a cloud variable of type integer
Particle.variable("Sunlight_Intensity", &photoCellReading, INT);
// Create a cloud variable of type String
Particle.variable("Sunlight_Status", sunlightStatus);
// Create a cloud variable of type String
Particle.variable("Direct_Sunlight_Hours", direct_Sunlight_Hours_Str );
// Create a cloud variable of type String
Particle.variable("Low_Sunlight_Hours", low_Sunlight_Hours_Str );
}
void loop()
{
// Use analogRead to read the photo cell reading
// This gives us a value from 0 to 4095
photoCellReading = analogRead(photoCellPin);
// find out if the button is pushed
// or not by reading from it.
int buttonState = digitalRead( buttonPin );
// remember that we have wired the pushbutton to
// ground and are using a pulldown resistor
// that means, when the button is pushed,
// we will get a LOW signal
// when the button is not pushed we'll get a HIGH
if( buttonState == LOW ){
// toggle the on/off states of the device
deviceOn = deviceOn * (-1);
}
if( deviceOn == 1 )
{
deviceOnStr = "On";
delay(100);
}
else{
deviceOnStr = "Off";
delay(100);
}
if( deviceOn == 1 ) // if the device is turned on
{
if( photoCellReading < 2000 ) // No Sunlight
{
sunlightStatus = "No_Sunlight";
while( pos > 0){ // goes to 0 degree
pos--; // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(5); // waits 5ms for the servo to reach the position
}
}
else if (photoCellReading > 3700){ // Direct Sunlight
sunlightStatus = "Direct_Sunlight";
// calculate the accumulated time of exposure to direct sunlight
direct_Sunlight_Hours = direct_Sunlight_Hours + 0.1/60/60;
direct_Sunlight_Hours_Str = String( direct_Sunlight_Hours, 3 );
while( pos < 180){ // goes to 180 degrees
pos++; // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(5); // waits 5ms for the servo to reach the position
}
}
else{ // Low Sunlight
sunlightStatus = "Low_Sunlight";
// calculate the accumulated time of exposure to low sunlight
low_Sunlight_Hours = low_Sunlight_Hours + 0.1/60/60;
low_Sunlight_Hours_Str = String( low_Sunlight_Hours, 3 );
while( pos < 90){ // goes to 90 degrees
pos++; // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(5); // waits 5ms for the servo to reach the position
}
while( pos > 90){ // goes to 90 degrees
pos--; // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(5); // waits 5ms for the servo to reach the position
}
}
}
// send daily report to the user
log_to_Notification();
// wait 1/10th of a second and then loop
delay(100);
}
// store the time when you last published to notification
int last_published_Notification = -1;
// store the notification message to the user
String message_To_User = "";
void log_to_Notification(){
// check if 24 hrs have elapsed
if( last_published_Notification + 60000*60*24 < millis() ){
if( direct_Sunlight_Hours < 4)
{
message_To_User = "Most mini-cacti require ~4 hrs of direct sunlight daily. Your cacus had direct sunlight of " + direct_Sunlight_Hours_Str
+ " hrs today. Consider moving it within 4 feet of a window :)";
}
else{
message_To_User = "Most mini-cacti require ~4 hrs of direct sunlight daily. Your cacus had direct sunlight of " + direct_Sunlight_Hours_Str + " hrs today. Good job!";
}
Particle.publish( "log_to_Notification", message_To_User );
last_published_Notification = millis();
}
}
Click to Expand
In this project, I used visual representations to communicate the information on the intensity of sunlight to the user. This can be further enhanced to display more enriched data like temperature and air/soil humidity.
As of now, the device send 1 push notification to the user to inform the daily statistics about the directly sunlight exposure of the cactus. This might be a distraction to the user if they are in the middle of some tasks. Going forward, I may want to find an alternative way to do this. I haven't think of a good way to raise the user's attention enough without being intrusive. I'll keep thinking and update my thoughts here.
I explored and applied the idea of embodied information in this project.
I learned how to work with a servo (yay!) It made my device much more interesting, responsive and dynamic.
I practiced the logical design of my codes and circuit to segregate, track and calculate the data it collected from the sensor.
I enjoyed the pure joy of making a device like this with my hands :)
https://www.indiegogo.com/projects/lua-the-smart-planter-with-feelings#/
https://docs.particle.io/reference/device-os/firmware/photon/
Nassim Jafarinaimi, Jodi Forlizzi, Amy Hurst, and John Zimmerman. 2005. Breakaway: an ambient display designed to change human behavior. In CHI ‘05 Extended Abstracts on Human Factors in Computing Systems (CHI EA ‘05). ACM, New York, NY, USA, 1945-1948.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Help your mini cactus get enough direct sunlight every day!
November 7th, 2019