Lillypad

Milk level notifying system

Made by Vishal Pallikandi

The Lillypad is a platform like device that you keep in you refrigerator. Placing your milk bottle on it allows you to receive automatic SMS notifications when you are running out of milk. It can also update a status incase you acknowledge the notification so that, others back at home can know if you have read the message.

Created: January 28th, 2015

0
0

Description:

 The Lillypad is a platform like device that you keep in you refrigerator. Placing your milk bottle on it allows you to receive automatic SMS notifications when you are running out of milk. It can also update a status incase you acknowledge the notification so that, others back at home can know if you have read the message. It does so by changing the color of the button's glow from red to green.

0

Working: 

The heart of the Lillypad is a Spark core which serves as the brain and also connects to wi-fi. A pressure sensor keeps track of the weight of any object placed on the platform indirectly through pressure and, a custom made capacitive sensor is used to make the glowing touch button. The sensor is just a piece of aluminium foil wrapped around a circular piece of card and hidden behind the button's surface.The capacitive touch sensor works simply by creating a rising edge on a 'send pin' and observing how long the capacitance of the sensor takes to charge through a high resistance. This response is read from a 'receive pin' and the difference in time between send and receive response is indicative of the capacitance. Since capacitance can be created across an insulator, the sensor is able to penetrate the touch surface and respond to the capacitance of the human body.

The glow under the capacitive button is created by a pair of LEDs placed under the button. I used the IFTTT (If this, then that) service to send out SMS notifications and receive acknowledgements.

0

Process:

1. I started by making sketches of different forms

0

2. Next, I made the form that I liked with foam core

0

3. I made the circuit as per the below circuit diagram

0

4. Wrote some code

0
// URLs for Debugging
// https://api.spark.io/v1/devices/<your device ID>/pressure?access_token=<your access token>
// https://api.spark.io/v1/devices/<your device ID>/sendSMS?access_token=<your access token>

#define LED D7 // Indicator to debug the touch button

// touch button events
#define tEVENT_NONE 0
#define tEVENT_TOUCH 1
#define tEVENT_RELEASE 2

// minimum poll time before checking for next touchbutton event
#define POLL_TIME 20

//LED colors
#define red 1
#define green 2
#define blue 3
#define cyan 4
#define off 0


// RGB LED Pins

#define R A5
#define G A4
#define B A3

// pressure sensor
    int pressure=0;   //For pressure storage
    int fiveVolt=A0;  //Supply for the sensor
    int pressureS=A1; //Pin for pressure sensing
    int checkFlag=0;  //To know if event is over
    int sentFlag=0;

// touch button
    int sPin = D3;    //send pin
    int rPin = D2;    //recieve pin
    
    unsigned long tS; //send- time stamp
    unsigned long tR; //recieve time stamp
    
    long tReading;    //time delay reading
    long tBaseline;   //running average of time delay before reading
    
//SMS acknowledgement flag
    int message_Ack=0; //SMS acknowledgement flag
//    int sendSMS=0;     //SMS send flag
    
    int glow=off;

void setup() {
    //RGB LED
    pinMode(R, OUTPUT);
    digitalWrite(R, HIGH);
    pinMode(G, OUTPUT);
    digitalWrite(G, HIGH);
    pinMode(B, OUTPUT);
    digitalWrite(B, HIGH);
    
    //pressure sensor
    pinMode(fiveVolt, OUTPUT);
    pinMode(pressureS, INPUT);
    Spark.variable("pressure", &pressure, INT);
    Spark.variable("sentFlag", &sentFlag, INT);
    //Spark.variable("sendSMS", &sendSMS, INT);
    digitalWrite(fiveVolt,HIGH);

	// Indicator to debug the touch button
	pinMode(LED, OUTPUT);
    
    //touch sensor
    pinMode(sPin,OUTPUT);
    attachInterrupt(rPin,touchSense,RISING);
    
    // first reading to calibrate touchbutton without placement of a finger
    tBaseline = touchSampling();    
    
    //SMS acknowledgement on the cloud
    Spark.function("messageAck",messageAck);

}

void loop() {
    static unsigned long lastUpdate = 0;

    
    //basic fuction
    pressure=analogRead(pressureS);
    if (pressure<=80)
    checkFlag=1;
    delay(100);
    if (analogRead(pressureS)>200&&checkFlag==1)
    {
        delay(1000);
        if (analogRead(pressureS)<1000&&sentFlag==0)
        {
        //sendSMS=1;
        Spark.publish("sendSMS");
        sentFlag=1;
        }

    checkFlag=0;
    }
        if (analogRead(pressureS)>=1000&&sentFlag==1)
        {
        sentFlag=0;
        message_Ack=0;
        }


	
	//Update touchsensor every POLL_TIME [ms]
	if (millis() > lastUpdate + POLL_TIME)
	{

		int touchEvent = touchEventCheck();
		
		if (touchEvent == tEVENT_TOUCH)
		{
			digitalWrite(LED, HIGH);
			if (message_Ack==1)
			 {glow=green;
			 ledControl(glow,0);
			}
			 
			else 
			  {glow=red;
			 ledControl(glow,0);
			}
			 
		}
		
		if (touchEvent == tEVENT_RELEASE)
		{
			digitalWrite(LED, LOW);
			glow=off;
			ledControl(glow,255);
		}
		
		lastUpdate = millis();
	}
}

void touchSense()
{
    tR = micros();
}

// sample touch sensor 32 times and get average RC delay [usec]

long touchSampling()
{
    long tDelay = 0;
    int mSample = 0;
    
    for (int i=0; i<32; i++)
    {
        // discharge capacitance at rPin
        pinMode(rPin, OUTPUT);
        digitalWrite(sPin,LOW);
        digitalWrite(rPin,LOW);
        
        // revert to high impedance input
        pinMode(rPin,INPUT);
        
        // timestamp & transition sPin to HIGH and wait for interrupt in a read loop
        tS = micros();
        tR = tS;
        digitalWrite(sPin,HIGH);
        do
        {
        // wait for transition
        } while (digitalRead(rPin)==LOW);
        
        // accumulate the RC delay samples
        // ignore readings when micros() overflows
        if (tR>tS)
        {
            tDelay = tDelay + (tR - tS);
            mSample++;
        }
        
    }
    
    // calculate average RC delay [usec]
    if (mSample>0)
    {
        tDelay = tDelay/mSample;
    }
    else
    {
        tDelay = 0;     // this is an error condition!
    }

    //autocalibration using exponential moving average on data below trigger point
    if (tDelay<(tBaseline + tBaseline/4))
    {
        tBaseline = tBaseline + (tDelay - tBaseline)/8;
    }
	
	/*
	Serial.println(tDelay, tBaseline);
	*/
    
    return tDelay;
    
}

//touch events:
//      tEVENT_NONE     no change
//      tEVENT_TOUCH    sensor is touched (Low to High)
//      tEVENT_RELEASE  sensor is released (High to Low)
int touchEventCheck()
{
    int touchSense;                     // current reading
    static int touchSenseLast = LOW;    // last reading
    
    static unsigned long touchDebounceTimeLast = 0; // debounce timer
    int touchDebounceTime = 50;                     // debounce time
    
    static int touchNow = LOW;  // current debounced state
    static int touchLast = LOW; // last debounced state
    
    int tEvent = tEVENT_NONE;   // default event
    
    
    // read touch sensor
    tReading = touchSampling();
    
    // touch sensor is HIGH if trigger point 1.25*Baseline
    if (tReading>(tBaseline + tBaseline/8)) 
    {
        touchSense = HIGH; 
    }
    else
    {
        touchSense = LOW; 
    }
    
    // debounce touch sensor
    // if state changed then reset debounce timer
    if (touchSense != touchSenseLast)
    {
        touchDebounceTimeLast = millis();
    }
    
    touchSenseLast = touchSense;
    
    
    // accept as a stable sensor reading if the debounce time is exceeded without reset
    if (millis() > touchDebounceTimeLast + touchDebounceTime)
    {
        touchNow = touchSense;
    }
    
    
    // set events based on transitions between readings
    if (!touchLast && touchNow)
    {
        tEvent = tEVENT_TOUCH;
    }
    
    if (touchLast && !touchNow)
    {
        tEvent = tEVENT_RELEASE;
    }
    
    
    // update last reading
    touchLast = touchNow;
    
    return tEvent;
}

int messageAck(String statusSTR)
{
    message_Ack=1;
    return 1;
}


//function to control the color of the RGB LED
void ledControl(int color,int value)
{
    
    //Wipe out previous values of the LED
    analogWrite(R, 255);    
    analogWrite(G, 255);
    analogWrite(B, 255);

    //change the color according to 'color'
    if (color==red)
    analogWrite(R, value);

    if (color==green||cyan)
    analogWrite(G, value);
    
    if (color==blue||cyan)
    analogWrite(B, value);
    
}
Click to Expand
0

5. Added the IFTTT recipes to send and recieve SMS

0

6. Arrange the components inside, close the box, and were ready to go!

x
Share this Project


About

The Lillypad is a platform like device that you keep in you refrigerator. Placing your milk bottle on it allows you to receive automatic SMS notifications when you are running out of milk. It can also update a status incase you acknowledge the notification so that, others back at home can know if you have read the message.