Wi-Fi enabled automatic drink mixer. Open up the webpage, select you drink and/or mixer and hit dispense. Be amazed as it mixes your drinks for you! Extendable and customizable.

Dependencies:   mbed-rtos mbed

Fork of ECE_4180_Lab_4_Robot_Webserver by Chris Price

Revision:
6:5c3c1f1c2985
Parent:
5:cfceccd5ccb1
--- a/main.cpp	Tue Oct 20 18:21:16 2015 +0000
+++ b/main.cpp	Sun Dec 06 22:20:05 2015 +0000
@@ -1,57 +1,45 @@
 // ESP8266 Static page WEB server to control Mbed
 
 #include "mbed.h"
-//#include "DS18B20.h"
-#include "motordriver.h"
 #include "rtos.h"
 
-RawSerial pc(USBTX, USBRX);
+Serial pc(USBTX, USBRX);
 RawSerial esp(p28, p27); // tx, rx
-
-//DS18B20 thermom(A0, DS18B20::RES_12_BIT);
+DigitalOut reset(p29); // Reset for esp
 
 // Standard Mbed LED definitions
 DigitalOut  led1(LED1);      // (PTB18)
 DigitalOut  led2(LED2);    // (PTB19)
 DigitalOut  led3(LED3);     // (PTD1)
 DigitalOut led4(LED4);
-Motor left(p21, p23, p22, 1); // pwm, fwd, rev, has brake feature
-Motor right(p26, p25, p24, 1);
 
-// Digital Out and In pins, can be configured to any suitable pin depending on Platform
-DigitalOut  Out1(p6);
-DigitalOut  Out2(p7);
-DigitalOut  Out3(p8);
-DigitalOut  reset(p29);
+DigitalIn pb(p8);
 
-DigitalIn  In1(p9);
-DigitalIn  In2(p10);
-DigitalIn  In3(p11);
+// Drink stuff
+#define TYPE_DRINK            0
+#define TYPE_MIXER            1
+#define RELAY_NONE           -1
+#define DRINK_RELAY_WHISKY    0
+#define DRINK_RELAY_GIN       1
+#define MIXER_RELAY_COKE      2
+#define MIXER_RELAY_TONIC     3
+DigitalOut gRelays[] = {p22, p23, p24, p25}; // Relay Pins
+int gDrinkRelayVal = RELAY_NONE;
+int gMixerRelayVal = RELAY_NONE;
+int gPourLatch = false;
+void startPour(int type, int drinkRelay, float timeMs);
+void stopDrinkPour(void const *args);
+void stopMixerPour(void const *args);
+RtosTimer *gStopDrinkTimer;
+RtosTimer *gStopMixerTimer;
 
-PwmOut speaker(p21);
-AnalogIn   Ain1(p18);
-AnalogIn   Ain2(p19);
-
+// Webserver stuff
 Timer t1;
 Timer t2;
-
-void motorThread(void const *args);
-bool gMotorLatch = false;
-int gMotorCommand = 0;
-#define CMD_FWD 1
-#define CMD_BACK 2
-#define CMD_LEFT 3
-#define CMD_RIGHT 4
-
 struct tm t;
 
 int bufflen, DataRX, count, getcount, replycount, servreq, timeout;
 int bufl, ipdLen, linkID, weberror, webcounter;
-float temperature, AdcIn, Ht;
-float R1=100000, R2=10000; // resistor values to give a 10:1 reduction of measured AnalogIn voltage
-char Vcc[10];
-char Temp[10];
-char temp[10];
 char webcount[8];
 char lasthit[30];
 char timebuf[30];
@@ -59,15 +47,14 @@
 char type1[16];
 char channel[2];
 char cmdbuff[32];
-char replybuff[1024];
-char webdata[1024]; // This may need to be bigger depending on WEB browser used
-char webbuff[4096];     // Currently using 1986 characters, Increase this if more web page data added
+char replybuff[4096];
+char webdata[4096]; // This may need to be bigger depending on WEB browser used
+char webbuff[8192];     // Currently using 1986 characters, Increase this if more web page data added
 
 void SendCMD(),getreply(),ReadWebData(),startserver(),sendpage(),SendWEB(),sendcheck();
-void gettime(),gettemp(),getbattery(),setRTC(),beep();
+void setRTC();
 
-bool simpleResponse = false;
-void sendSimplePage();
+void otherThread(void const *args);
 
 // manual set RTC values
 int minute      =00;    // 0-59
@@ -97,8 +84,76 @@
     }
 }
 
+
+// Stop drink relay
+void stopDrinkPour(void const *args) {
+    //drinkTimer.detach();
+    gRelays[gDrinkRelayVal] = 0;
+    gDrinkRelayVal = RELAY_NONE;
+   // pc.printf("Relays: %d,%d,%d,%d\n\r", gRelays[0], gRelays[1], gRelays[2], gRelays[3]);
+}
+
+void stopMixerPour(void const *args) {
+    //mixerTimer.detach();
+    gRelays[gMixerRelayVal] = 0;
+    gMixerRelayVal = RELAY_NONE;
+   // pc.printf("Relays: %d,%d,%d,%d\n\r", gRelays[0], gRelays[1], gRelays[2], gRelays[3]);
+}
+
+void startPour(int type, int relayVal, float timeMs) {
+    switch (relayVal) {
+        case DRINK_RELAY_WHISKY:
+        case DRINK_RELAY_GIN:
+        case MIXER_RELAY_COKE:
+        case MIXER_RELAY_TONIC:
+            // Good values
+            break;
+        case RELAY_NONE:
+            return; // Do nothing for this pour
+        default:
+            pc.printf("StartPour invalid relay val %d!\n\r", relayVal);
+            return;
+    }
+
+    // Pour!
+    gRelays[relayVal] = 1;
+    //pc.printf("Relays: %d,%d,%d,%d\n\r", gRelays[0], gRelays[1], gRelays[2], gRelays[3]);
+    if (type == TYPE_DRINK) {
+        //drinkTimer.attach(&stopDrinkPour, 1.0);
+        gStopDrinkTimer->start(1000);
+    } else if (type == TYPE_MIXER) {
+        //mixerTimer.attach(&stopMixerPour, 0.5);
+        gStopMixerTimer->start(500);
+    }
+}
+
+void otherThread(void const *args) {    
+    pb.mode(PullUp);
+    RtosTimer stopDrinkTimer(stopDrinkPour, osTimerOnce);
+    RtosTimer stopMixerTimer(stopMixerPour, osTimerOnce);
+    
+    gStopDrinkTimer = &stopDrinkTimer;
+    gStopMixerTimer = &stopMixerTimer;
+    
+    while (1) {
+        if (gPourLatch) {
+            startPour(TYPE_DRINK, gDrinkRelayVal, 1000);
+            startPour(TYPE_MIXER, gMixerRelayVal, 500);
+            gPourLatch = false;
+        }
+        //gRelays[0] = !pb;
+        Thread::wait(50);
+    }
+}
 int main()
 {   
+    gRelays[0] = 0;
+    gRelays[1] = 0;
+    gRelays[2] = 0;
+    gRelays[3] = 0;
+
+    Thread tT(otherThread);
+    
     reset=0;
     pc.baud(115200);
 
@@ -113,22 +168,16 @@
     if (time(NULL) < 1420070400) {
         setRTC();
     }
-    beep();
+
     startserver();
 
-    Thread mThreadYo(motorThread);
+    //Thread tPourThread(pourThread);
 
     while(1) {
         if(DataRX==1) {
             ReadWebData();
-            beep();
             if (servreq == 1 && weberror == 0) {
-                if (simpleResponse == true) {
-                    sendSimplePage();
-                    simpleResponse = false;
-                } else {
-                    sendpage();
-                }
+                sendpage();
             }
             esp.attach(&callback);
             pc.printf(" IPD Data:\r\n\n Link ID = %d,\r\n IPD Header Length = %d \r\n IPD Type = %s\r\n", linkID, ipdLen, type);
@@ -140,104 +189,90 @@
         }
     }
 }
-void sendSimplePage() {
-    strcpy(webbuff, "<!DOCTYPE html><html><head></head><body>OK</body></html>");
-
-// end of WEB page data
-    bufl = strlen(webbuff); // get total page buffer length
-    sprintf(cmdbuff,"AT+CIPSEND=%d,%d\r\n", linkID, bufl); // send IPD link channel and buffer character length.
-    timeout=200;
-    getcount=7;
-    SendCMD();
-    getreply();
-    SendWEB();  // send web page
-    memset(webbuff, '\0', sizeof(webbuff));
-    sendcheck();
-}
 
 // Static WEB page
 void sendpage()
 {
-    gettemp();
-    getbattery();
-    gettime();
+// WEB page data
+    strcpy(webbuff, "\
+<html>\
+<head>\
+<meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;'>\
+<title>Sir MixaBot</title>\
+<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' integrity='sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7' crossorigin='anonymous'>\
+<style>\
+body {\
+background: url(http://i.imgur.com/NrfPRXU.jpg?1);\
+background-size: cover;\
+background-repeat: no-repeat;\
+}\
+select {\
+width: 100%;\
+}\
+.center {\
+    margin: auto;\
+}\
+.container {\
+    display:inline-block;\
+}\
+h1 {\
+font-family: 'Lucida Bright', Georgia, serif;\
+font-size: 72px;\
+font-style: normal;\
+font-variant: normal;\
+font-weight: 400;\
+line-height: 60px;\
+color: rgba(100, 100, 100, 1.0);\
+-webkit-text-stroke: 1px black;\
+background: rgba(255, 255, 255, 0.9);\
+background-size: contain;\
+padding: 5px;\
+} \
+form {\
+width: 200px;\
+margin-top: 10px;\
+background: rgba(255, 255, 255, 0.9);\
+background-size: contain;\
+-webkit-box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.7);\
+-moz-box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.7);\
+box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.7);\
+border-radius: 8px;\
+padding: 8px;\
+font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Geneva, Verdana, sans-serif;\
+font-size: 14px;\
+font-style: normal;\
+font-variant: normal;\
+font-weight: 400;\
+line-height: 20px;\
+}\
+</style>\
+</head>\
+<body>\
+<h1>Sir MixaBot</h1>\
+<div class='container'>\
+<form method='POST'>\
+<label>Drink</label>\
+<select name='drink'>\
+<option value=''>-- None --</option>\
+<option value='whisky'>Whisky</option>\
+<option value='gin'>Gin</option>\
+</select>\
+<br />\
+<br />\
+<label>Mixer</label>\
+<select name='mixer'>\
+<option value=''>-- None --</option>\
+<option value='coke'>Coke</option>\
+<option value='tonic'>Tonic</option>\
+</select> \
+<br />\
+<br />\
+<button type='submit' class='btn btn-block btn-lg btn-danger'>Dispense</button>\
+</form>\
+</div>\
+</body>\
+</html>");
 
-// WEB page data
-    strcpy(webbuff, "<!DOCTYPE html>");
-    strcat(webbuff, "<html><head><title>ESP8266 Mbed LPC1768</title></head>");
-    strcat(webbuff, "<body>");
-    strcat(webbuff, "<div style=\"text-align:center; background-color:#F4F4F4; color:#00AEDB;\"><h1>ESP8266 Mbed IoT Web Controller</h1>");
-    strcat(webbuff, "Hit Count - ");
-    strcat(webbuff, webcount);
-    strcat(webbuff, "<br>Last Hit - ");
-    strcat(webbuff, lasthit);
-    strcat(webbuff, "</div><br /><hr>");
-    strcat(webbuff, "<h3>Mbed RTC Time -&nbsp&nbsp");
-    strcat(webbuff, timebuf);
-    strcat(webbuff, "</h3>\r\n");
-    strcat(webbuff, "<p><form method=\"POST\"><strong> Analog 1:&nbsp&nbsp<input type=\"text\" size=6 value=\"");
-    strcat(webbuff, Temp);
-    strcat(webbuff, "\"> </sup>V <form method=\"POST\"> <strong> &nbsp&nbspAnalog 2:&nbsp&nbsp<input type=\"text\" size=4 value=\"");
-    strcat(webbuff, Vcc);
-    strcat(webbuff, "\"> </sup>V");
-    if(led1==0) {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"led1\" value=\"0\" checked>  LED 1 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"led1\" value=\"1\" >  LED 1 on");
-    } else {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"led1\" value=\"0\" >  LED 1 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"led1\" value=\"1\" checked>  LED 1 on");
-    }
-    if(Out1==0) {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out1\" value=\"0\" checked>  Digital Out 1  off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out1\" value=\"1\" >  Digital Out 1 on");
-    } else {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out1\" value=\"0\" >  Digital Out 1 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out1\" value=\"1\" checked>  Digital Out 1 on");
-    }
-    if(Out2==0) {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out2\" value=\"0\" checked>  Digital Out 2 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out2\" value=\"1\" >  Digital Out 2 on");
-    } else {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out2\" value=\"0\" >  Digital Out 2 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out2\" value=\"1\" checked>  Digital Out 2 on");
-    }
-    if(Out3==0) {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out3\" value=\"0\" checked>  Digital Out 3 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out3\" value=\"1\" >  Digital Out 3 on");
-    } else {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"Out3\" value=\"0\" >  Digital Out 3 off");
-        strcat(webbuff, "<br><input type=\"radio\" name=\"Out3\" value=\"1\" checked>  Digital Out 3 on");
-    }
-    if(In1==0) {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"In1\" value=\"0\" >  Digital In 1");
-    } else {
-        strcat(webbuff, "<p><input type=\"radio\" name=\"In1\" value=\"1\" checked>  Digital In 1");
-    }
-    if(In2==0) {
-        strcat(webbuff, "<br><input type=\"radio\" name=\"In2\" value=\"0\" >  Digital In 2");
-    } else {
-        strcat(webbuff, "<br><input type=\"radio\" name=\"In2\" value=\"1\" checked>  Digital In 2");
-    }
-    if(In3==0) {
-        strcat(webbuff, "<br><input type=\"radio\" name=\"In3\" value=\"0\" >  Digital In 3");
-    } else {
-        strcat(webbuff, "<br><input type=\"radio\" name=\"In3\" value=\"1\" checked>  Digital In 3");
-    }
-    strcat(webbuff, "</strong><p><input type=\"submit\" value=\"send-refresh\" style=\"background: #3498db;");
-    strcat(webbuff, "background-image:-webkit-linear-gradient(top, #3498db, #2980b9);");
-    strcat(webbuff, "background-image:linear-gradient(to bottom, #3498db, #2980b9);");
-    strcat(webbuff, "-webkit-border-radius:12;border-radius: 12px;font-family: Arial;color:#ffffff;font-size:20px;padding:");
-    strcat(webbuff, "10px 20px 10px 20px; border:solid #103c57 3px;text-decoration: none;");
-    strcat(webbuff, "background: #3cb0fd;");
-    strcat(webbuff, "background-image:-webkit-linear-gradient(top,#3cb0fd,#1a5f8a);");
-    strcat(webbuff, "background-image:linear-gradient(to bottom,#3cb0fd,#1a5f8a);");
-    strcat(webbuff, "text-decoration:none;\"></form></span>");
-    strcat(webbuff, "<p/><h2>How to use:</h2><ul>");
-    strcat(webbuff, "<li>Select the Radio buttons to control the digital out pins.</li>");
-    strcat(webbuff, "<li>Click 'Send-Refresh' to send.</li>");
-    strcat(webbuff, "<li>Use the 'Send-Refresh' button to refresh the data.</li>");
-    strcat(webbuff, "</ul>");
-    strcat(webbuff, "</body></html>");
 // end of WEB page data
     bufl = strlen(webbuff); // get total page buffer length
     sprintf(cmdbuff,"AT+CIPSEND=%d,%d\r\n", linkID, bufl); // send IPD link channel and buffer character length.
@@ -301,44 +336,31 @@
         strcpy(webdata, webbuff + x);
         weberror=0;
         int numMatched = sscanf(webdata,"+IPD,%d,%d:%s", &linkID, &ipdLen, type);
-        if( strstr(webdata, "led1=1") != NULL || strstr(webdata, "keycode=fwd") != NULL) {
-            gMotorLatch = true;
-            gMotorCommand = CMD_FWD;
-            
-            simpleResponse = true;
-        }
-        if( strstr(webdata, "led1=0") != NULL ) {
-            led1=0;
-        }
-        if( strstr(webdata, "Out1=1") != NULL || strstr(webdata, "keycode=back") != NULL) {
-            gMotorLatch = true;
-            gMotorCommand = CMD_BACK;
-            simpleResponse = true;
-        }
-        if( strstr(webdata, "Out1=0") != NULL ) {
-            Out1=0;
-        }
-        if( strstr(webdata, "Out2=1") != NULL || strstr(webdata, "keycode=left") != NULL) {
-            gMotorLatch = true;
-            gMotorCommand = CMD_LEFT;
-            simpleResponse = true;
-        }
-        if( strstr(webdata, "Out2=0") != NULL ) {
-            Out2=0;
-        }
-        if( strstr(webdata, "Out3=1") != NULL || strstr(webdata, "keycode=right") != NULL) {
-            gMotorLatch = true;
-            gMotorCommand = CMD_RIGHT;
-            simpleResponse = true;
-        }
-        if( strstr(webdata, "Out3=0") != NULL ) {
-            Out3=0;
-        }
+        
         sprintf(channel, "%d",linkID);
         if (strstr(webdata, "GET") != NULL) {
             servreq=1;
         }
         if (strstr(webdata, "POST") != NULL) {
+            int drinkVal = RELAY_NONE;
+            int mixerVal = RELAY_NONE;
+            if(strstr(webdata, "drink=whisky") != NULL) {
+                drinkVal = DRINK_RELAY_WHISKY;
+            } else if (strstr(webdata, "drink=gin") != NULL ) {
+                drinkVal = DRINK_RELAY_GIN;
+            }
+            
+            if(strstr(webdata, "mixer=coke") != NULL) {
+                mixerVal = MIXER_RELAY_COKE;
+            } else if (strstr(webdata, "mixer=tonic") != NULL ) {
+                mixerVal = MIXER_RELAY_TONIC;
+            }
+            
+            if (gDrinkRelayVal == RELAY_NONE && gMixerRelayVal == RELAY_NONE) {
+                gDrinkRelayVal = drinkVal;
+                gMixerRelayVal = mixerVal;
+                gPourLatch = true;
+            }
             servreq=1;
         }
         webcounter++;
@@ -352,8 +374,6 @@
 // Starts and restarts webserver if errors detected.
 void startserver()
 {
-    gettemp();
-    gettime();
     pc.printf("\n\n RTC time   %s\r\n\n",timebuf);
     pc.printf("++++++++++ Resetting ESP ++++++++++\r\n");
     strcpy(cmdbuff,"AT+RST\r\n");
@@ -413,7 +433,6 @@
     }
     t2.reset();
     t2.start();
-    beep();
 }
 // ESP Command data send
 void SendCMD()
@@ -446,35 +465,6 @@
     }
     t1.stop();
 }
-// Analog in example
-void getbattery()
-{
-    AdcIn=Ain1.read();
-    Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy
-    sprintf(Vcc,"%2.3f",Ht);
-}
-// Temperature example
-void gettemp()
-{
- 
-    AdcIn=Ain2.read();
-    Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy  
-    sprintf(Temp,"%2.3f",Ht);
-}
-// Get RTC time
-void gettime()
-{
-    time_t seconds = time(NULL);
-    strftime(timebuf,50,"%H:%M:%S %a %d %b %y", localtime(&seconds));
-}
-
-void beep()
-{
-    speaker.period(1.0/2000); // 2000hz period
-    speaker = 0.5; //50% duty cycle - max volume
-    wait_ms(60);
-    speaker=0.0; // turn off audio
-}
 
 void setRTC()
 {
@@ -485,56 +475,4 @@
     t.tm_mon = (month-1);       // 0-11  "0" = Jan, -1 added for Mbed RCT clock format
     t.tm_year = ((year)+100);   // year since 1900,  current DCF year + 100 + 1900 = correct year
     set_time(mktime(&t));       // set RTC clock
-}
-
-// Control motor related things
-void motorThread(void const *args) {
-    pc.printf("motorThread started\n\r");
-    
-    while (1) {
-        while (gMotorLatch == false) {
-            Thread::wait(100);
-        }
-        
-        pc.printf("motorThread Latched!\n\r");
-        
-        gMotorLatch = false;
-        
-        float lSpeed = 0.0f;
-        float rSpeed = 0.0f;
-        float delayMs = 1000;
-        switch(gMotorCommand) {
-            case CMD_FWD:
-                lSpeed = 0.5f;
-                rSpeed = 0.5f;
-                break;
-            
-            case CMD_BACK:
-                lSpeed = -0.5f;
-                rSpeed = -0.5f;
-                break;
-            
-            case CMD_LEFT:
-                lSpeed = -0.5f;
-                rSpeed = 0.5f;
-                delayMs = 500;
-                break;
-            
-            case CMD_RIGHT:
-                lSpeed = 0.5f;
-                rSpeed = -0.5f;
-                delayMs = 500;
-                break;
-            
-            default:
-                delayMs = 0;
-                break;
-        }
-        
-        left.speed(lSpeed);
-        right.speed(rSpeed);
-        Thread::wait(delayMs);
-        left.speed(0);
-        right.speed(0);
-    }
 }
\ No newline at end of file