Cactus Buddy (◉ω◉)

Made by Xiaoyi Zhu

Found in DioT 2019: Internet of Plants

Help your mini cactus get enough direct sunlight every day!

0

Solution

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

0

Approach

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

0

Process

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.

0
0

Then I moved on to attach a paper with icon that I sketched to in a way I hoped to convey the sunlight information with and refined my codes to adjust the rotating angles.

0
0

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.

0

Finally, I completed the working prototype and further refined the codes to share more data shared with Particle cloud, publish the data to IFTTT, and added button control (turn on/off the device).

0

Implementation

My final design and working prototype:

0
0

List of Components

  • A Breadboard
  • An Argon Microcontroller
  • A Photo-Resistor
  • A 10kΩ Resistor
  • A Servo
  • A Pushbutton
  • Jumper Wires
0
// 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
0

Next Steps

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.

0

Reflection

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 :)

0

References

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.

https://www.flaticon.com/

x
Share this Project

Courses

49713 Designing for the Internet of Things

· 16 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


Focused on
About

Help your mini cactus get enough direct sunlight every day!

Created

November 7th, 2019