Pill Bottle Fill Level: IoT and LCD Device

Summary

This project uses the mbed with additional sensors in order to measure and display the fill level of a container such as a bottle of pills or milk jug. It then outputs the percentage left to the LCD as well as a web page, so that someone could check the amount of milk left while at the grocery store.

http://i.imgur.com/cfhHBtY.jpg

Hardware

The components involved are listed with links to data sheets or wiki pages.

Sharp IR Sensor: http://sharp-world.com/products/device/lineup/data/pdf/datasheet/gp2y0a21yk_e.pdf
ESP8266 Wi-Fi Huzzah: https://developer.mbed.org/teams/Ece-4180-team-who/wiki/Using-Adafruit-ESP8266-Huzzah
uLCD-144-G2: https://developer.mbed.org/users/4180_1/notebook/ulcd-144-g2-128-by-128-color-lcd/

Proper Pin assignments for each device are below

uLCD

Devicembed
5VVU
TXp27
RXp28
GNDGND
RESp30

IR Sensor

Device=mbed
Analog Inp20
PowerVU
GroundGND

Huzzah Wifi Chip

Huzzahmbed LPC1768External 5V DC supply >=500MA
gndgndgnd
TXRX(p27)
RXTX(p28)
V+5VDC
RSTp26 (optional)

Quote:

Don't forget to use an external supply for 5V. The mbed does not supply enough current by itself.

Setup and Use

Wifi

In order to setup the Wifi correctly for the first time, you must change the SSID and Password settings in the code.

RFID

It is a good idea to secure the IR sensor with glue or tape in order to maintain consistently accurate readings.

Calibration

Depending on bottle size- pill bottle or milk jug, the IR sensor needs to be calibrated the first time. Run the code, place the IR sensor over an empty bottle, and make note of the second number on the LCD screen (labeled "Sensor Value"). Now fill up the bottle and repeat the process. Note this number as well. In order to get the most accurate reading, replace the variables lowlimit and uplimit (located at top of code) with these variables, respectively.

Usage

There are two options when reading the fill percentage. Option 1 is using the LCD Screen, updating about every two seconds. The video shown below demonstrates that option.

Option two involves reading the fill percentage off of a hosted webpage. In order to find the IP for that, run the virtual USB serial terminal. It will give you the IP address that it can be accessed through. Usually it is 10.0.1.127. The video below denmonstrates option two.

Software

Can be downloaded at:

main.cpp

#include "mbed.h"
#include "uLCD_4DGL.h" 

//IR value ranges
float uplimit = .655;
float lowlimit = .467;

Serial pc(USBTX, USBRX);

AnalogIn  ainpin(p20); // ir sensor
DigitalOut led1(LED1);
DigitalOut led4(LED4);
Timer t;

//LCD system setup
float sensorval = 0.0;

int  count,ended,timeout;
char buf[2024];
char snd[1024];
char cPercent[8];
float percent;

 
char ssid[32] = "SSID";     // enter WiFi router ssid inside the quotes
char pwd [32] = "password"; // enter WiFi router password inside the quotes
 
//LCD screen
uLCD_4DGL mylcd(p28,p27,p30);


//Wifi Networking
//wifi chip var
Serial esp(p9, p10); // tx, rx
DigitalOut reset(p11);

//custom functions for calculating pill bottle
int  CalcPixValue(float, float, float);
void DrawProgressBar(int, int, int);
 
 
void SendCMD(),getreply(),ESPconfig(),ESPsetbaudrate();
 void dev_recv()
{
    led1 = !led1;
    while(esp.readable()) {
        pc.putc(esp.getc());
    }
}
 
void pc_recv()
{
    led4 = !led4;
    while(pc.readable()) {
        esp.putc(pc.getc());
    }
}
 
 
int main()
{
    //IR setup
        //IR value ranges
    float uplimit = .655;
    float lowlimit = .647;
    
    //LCD system setup
    mylcd.baudrate(3000000);
    float sensorval = 0.0;
    
    
    
    reset=0; //hardware reset for 8266
    pc.baud(9600);  // set what you want here depending on your terminal program speed
    pc.printf("\f\n\r-------------ESP8266 Hardware Reset-------------\n\r");
    wait(0.1);
    reset=1;
    timeout=2;
    getreply();
 
    esp.baud(9600);   // change this to the new ESP8266 baudrate if it is changed at any time. 
    ESPconfig();        //******************  include Config to set the ESP8266 configuration  ***********************
 
 
 
    pc.attach(&pc_recv, Serial::RxIrq);
    esp.attach(&dev_recv, Serial::RxIrq);
    
    // continuosly get AP list and IP
    while(1) {
        sleep();
        
        //IR sensor
        //sensorval = ainpin.read(); //read in voltage and set it to sensor val (between 0-1)            
        int pix = CalcPixValue(sensorval, uplimit, lowlimit);
        //Print progress bar to LCD
        //DrawProgressBar(pix, 2, 6);
    }
 
}

//IR sensor commands

//given analog value 0-1 num, returns pixel value at which the fill bar should be drawn
int CalcPixValue(float num, float up, float low) 
{
    float range = up-low;
    float height, sensornorm1, sensornorm;
    
    sensornorm1 = (num - low)/(range);
    sensornorm =-1* sensornorm1 + 1;
    
    //correct for small error
    if (sensornorm1<0)
        sensornorm1 = 0;
    else if (sensornorm1 >1.00)
        sensornorm1 = 1;
    //convert to percent
    sensornorm1 = sensornorm1*100.0;
        
    mylcd.cls();
    // print out the values
    mylcd.printf("\n   Percent Full =\n   %f2\n\n\n   SensorValue=\n   %3f", sensornorm1,num);
    
    
    //restrict the value a scaled value of 127 pixels
    height = (sensornorm)*127;
            
    //if outside of range, post to 0% or 100% of bar
    if (num > up) {
        height = 0;}
    else if (num < low) {
        height = 127;}
    return floor(height);
    
}

void DrawProgressBar(int pixVal, int startX, int endX)
{
    //clears value
    

    int count = 0;
    
    while ( (startX + count) <= endX ) 
    {        
        mylcd.line(startX + count, 127, startX + count, pixVal, WHITE);
        count = count + 1;        
    }
}



//Wifi Commands
 
// Sets new ESP8266 baurate, change the esp.baud(xxxxx) to match your new setting once this has been executed
void ESPsetbaudrate()
{
    strcpy(snd, "AT+CIOBAUD=9600\r\n");   // change the numeric value to the required baudrate
    SendCMD();
}
 
//  +++++++++++++++++++++++++++++++++ This is for ESP8266 config only, run this once to set up the ESP8266 +++++++++++++++
void ESPconfig()
{

    wait(1);
    pc.printf("\f---------- Starting ESP Config ----------\r\n\n");
        strcpy(snd,".\r\n.\r\n");
    SendCMD();
        wait(1);
    pc.printf("---------- Reset & get Firmware ----------\r\n");
    strcpy(snd,"node.restart()\r\n");
    SendCMD();
    timeout=5;
    getreply();
    pc.printf(buf);
 
    wait(.2);
 
    pc.printf("\n---------- Get Version ----------\r\n");
    strcpy(snd,"print(node.info())\r\n");
    SendCMD();
    timeout=4;
    getreply();
    pc.printf(buf);
 
    wait(.3);
 
    // set CWMODE to 1=Station,2=AP,3=BOTH, default mode 1 (Station)
    pc.printf("\n---------- Setting Mode ----------\r\n");
    strcpy(snd, "wifi.setmode(wifi.STATION)\r\n");
    SendCMD();
    timeout=4;
    getreply();
    pc.printf(buf);
 
    wait(.2);
 
   
 
    pc.printf("\n---------- Listing Access Points ----------\r\n");
    strcpy(snd, "function listap(t)\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "for k,v in pairs(t) do\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "print(k..\" : \"..v)\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "end\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "end\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "wifi.sta.getap(listap)\r\n");
    SendCMD();
    wait(1);
        timeout=15;
    getreply();
    pc.printf(buf);
 
    wait(.2);
 
    pc.printf("\n---------- Connecting to AP ----------\r\n");
    pc.printf("ssid = %s   pwd = %s\r\n",ssid,pwd);
    strcpy(snd, "wifi.sta.config(\"");
    strcat(snd, ssid);
    strcat(snd, "\",\"");
    strcat(snd, pwd);
    strcat(snd, "\")\r\n");
    SendCMD();
    timeout=10;
    getreply();
    pc.printf(buf);
 
    wait(.5);
 
    pc.printf("\n---------- Get IP's ----------\r\n");
    strcpy(snd, "print(wifi.sta.getip())\r\n");
    SendCMD();
    timeout=3;
    getreply();
    pc.printf(buf);
 
    wait(1);
 
    pc.printf("\n---------- Get Connection Status ----------\r\n");
    strcpy(snd, "print(wifi.sta.status())\r\n");
    SendCMD();
    timeout=5;
    getreply();
    pc.printf(buf);
 
    pc.printf("\n\n\n  If you get a valid (non zero) IP, ESP8266 has been set up.\r\n");
    pc.printf("  Run this if you want to reconfig the ESP8266 at any time.\r\n");
    pc.printf("  It saves the SSID and password settings internally\r\n");
    wait(.10);
        
        
          pc.printf("\n---------- Setting up http server ----------\r\n");
    strcpy(snd, "srv=net.createServer(net.TCP)\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "srv:listen(80,function(conn)\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n");
        SendCMD();
        wait(1);
        strcpy(snd, "print(payload)\r\n");
        SendCMD();
        wait(1);
        
        strcpy(snd, "conn:send(\"<!DOCTYPE html>\")\r\n");
        SendCMD();
      wait(1);
        
        strcpy(snd, "conn:send(\"<html>\")\r\n");
        SendCMD();
      wait(1);
        
        strcpy(snd, "conn:send(\"<h1> Welcome to the bottle monitoring system.</h1>\")\r\n");
      SendCMD();
        wait(1);
        
        
        
        strcpy(snd, "conn:send(\"<h2> Last time your bottle was checked for a fill level it contained </h2>\")\r\n");
        SendCMD();
        wait(1);
        
        //Send most recent IR sensor data to site
        //sensorval = ainpin.read(); //read in voltage and set it to sensor val (between 0-1)            
        int pix = CalcPixValue(sensorval, uplimit, lowlimit);
        
        //reset it
        strcpy(snd,"");
        sprintf(cPercent, "%f",percent);
        strcat(snd,cPercent);
        strcat(snd, "conn:send(\"<h2> percent of the pill's original level ");
        
        strcat(snd," </h2>\")\r\n");
        //strcat(snd, cPercent + "</h2>\")\r\n" );
        SendCMD();
        wait(1);
        
        strcpy(snd, "conn:send(\"</html>\")\r\n");
    SendCMD();
    wait(1);
        
        strcpy(snd, "end)\r\n");
    SendCMD();
    wait(1);
        
        strcpy(snd, "conn:on(\"sent\",function(conn) conn:close() end)\r\n");
    SendCMD();
    wait(1);
        strcpy(snd, "end)\r\n");
    SendCMD();
    wait(1);
        timeout=17;
    getreply();
    pc.printf(buf);
        pc.printf("\r\nDONE");
}
 
void SendCMD()
{
    esp.printf("%s", snd);
}
 
void getreply()
{
    memset(buf, '\0', sizeof(buf));
    t.start();
    ended=0;
    count=0;
    while(!ended) {
        if(esp.readable()) {
            buf[count] = esp.getc();
            count++;
        }
        if(t.read() > timeout) {
            ended = 1;
            t.stop();
            t.reset();
        }
        
    }
}


Please log in to post comments.