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

Files at this revision

API Documentation at this revision

Comitter:
anewton8
Date:
Sun Dec 06 22:20:05 2015 +0000
Parent:
5:cfceccd5ccb1
Commit message:
Working stuff! Note: webpage can't exceed 2048 characters (whitespace has been removed to fit this)

Changed in this revision

Motordriver.lib Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r cfceccd5ccb1 -r 5c3c1f1c2985 Motordriver.lib
--- a/Motordriver.lib	Tue Oct 20 18:21:16 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://developer.mbed.org/users/littlexc/code/Motordriver/#3110b9209d3c
diff -r cfceccd5ccb1 -r 5c3c1f1c2985 main.cpp
--- 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