An alarm clock that wakes you up naturally!

Dependencies:   4DGL-uLCD-SE DebounceIn mbed RPCInterface

Files at this revision

API Documentation at this revision

Comitter:
ooglezoiden
Date:
Wed May 03 15:05:12 2017 +0000
Parent:
0:397faf7a0a52
Commit message:
added Alexa support

Changed in this revision

RPCInterface.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mywifi.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCInterface.lib	Wed May 03 15:05:12 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/MichaelW/code/RPCInterface/#bcc2e05e5da4
--- a/main.cpp	Thu Mar 16 19:38:55 2017 +0000
+++ b/main.cpp	Wed May 03 15:05:12 2017 +0000
@@ -1,32 +1,104 @@
 #include "mbed.h"
 #include "uLCD_4DGL.h"
 #include "DebounceIn.h"
+#include "mywifi.h"
+#include "mbed_rpc.h"
 
 Timeout alarm;
 Timer t;
-PwmOut lights(p25);
+PwmOut lights(p24);
 uLCD_4DGL uLCD(p9,p10,p11);
 AnalogIn photocell(p15);
 DebounceIn pb1(p8);
 DebounceIn pb2(p7);
-Serial blue(p28,p27);
+DebounceIn pb3(p6);
+Serial blue(p13,p14);
+
+Serial pc(USBTX, USBRX);
+Serial esp(p28, p27);
+char ssid[32] = "Hotspot";
+char pwd[32] = "1234567890";
+char port[32] = "1035"; // must be port forwarded
+char timeout[32] = "28800"; // 28800 is max
+volatile int tx_in=0;
+volatile int tx_out=0;
+volatile int rx_in=0;
+volatile int rx_out=0;
+const int buffer_size = 4095;
+char tx_buffer[buffer_size+1];
+char rx_buffer[buffer_size+1];
+char cmdbuff[1024];
+char rx_line[1024];
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
 
 
-void lightsOn(){
+// ---------------- Light Functions For Alexa ------------------
+
+
+
+void alexaLightsOn(Arguments *in, Reply *out){
     uLCD.cls();
     uLCD.printf("Turning on lights!");
     //lights = 1;
     while(lights<=0.99f){
         lights = lights + .01f;
-        wait(1);
+        wait_ms(100);
+    }
+    while(1);//do nothing until reset
+}
+
+void alexaLightsOff(Arguments *in, Reply *out){
+    uLCD.cls();
+    uLCD.printf("Turning off lights!");
+    //lights = 1;
+    while(lights>=0.01f){
+        lights = lights - .01f;
+        wait_ms(100);
     }
     while(1);//do nothing until reset
 }
 
+void alexaDimLights(Arguments *in, Reply *out){
+    float level = in->getArg<float>();
+    uLCD.cls();
+    uLCD.printf("Dimming lights to %f percent.", level);
+    lights = level;
+}
+
+void lightsOn(){
+    uLCD.cls();
+    uLCD.printf("Turning on lights!");
+    lights = 1.0;
+    //while(lights<=0.99f){
+    //    lights = lights + 0.1f;
+    //    wait(1);
+    //}
+    while(1);//do nothing until reset
+}
+
+void alexaTimer(Arguments *in, Reply *out){
+    int time = in->getArg<int>();
+    alarm.attach(&lightsOn, time);
+    t.start();
+    float curTime;
+    while(1){
+        uLCD.cls();
+        curTime = t.read();
+        uLCD.printf("%f secs since alarm set.\n", curTime);
+    }
+}
+
+// --------------------- Modes ------------------------
+
+
+
 void lightMode(){
     uLCD.cls();
     uLCD.printf("not bright out yet!\n");
-    while(photocell.read() < .9f){
+    while(photocell.read() < .8f){
         uLCD.cls();
         uLCD.printf("not bright out yet!\n");
     }
@@ -108,15 +180,89 @@
     
 }
 
+void alexaMode(){
+    uLCD.cls();
+    uLCD.printf("Alexa mode started!\n");
+    pc.baud(9600);
+    esp.baud(9600);
+    esp.attach(&Rx_interrupt, Serial::RxIrq);
+    esp.attach(&Tx_interrupt, Serial::TxIrq);
+    wait(5);
+    connectToNetwork();
+    uLCD.printf("Connected to network!!\n");
+    wait(0.2);
+    char rpc_in[256];
+    char rpc_out[256];
+    while (1) {
+        getReply();
+        memset(&rpc_in[0], 0, sizeof(rpc_in));
+        memset(&rpc_out[0], 0, sizeof(rpc_out));
+        int length = (int)rx_line[3] - 48; // bytes 0 to 2 are trash; byte 3 is length of message
+        if (length > 0 && length < 256) {
+            for (int i = 0; i < length; i++) {
+                rpc_in[i] = rx_line[i+4]; // bytes 4 to length+3 are the valid data
+            }
+            RPC::call(rpc_in, rpc_out);
+            pc.printf("%s\n", rpc_out);
+        }
+        // lambda function is event-triggered and non-persistent
+        // after it terminates, we need to close the existing connection and start another one
+        strcpy(cmdbuff, "srv:close()\r\n"); 
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "srv=net.createServer(net.TCP,");
+        strcat(cmdbuff, timeout);
+        strcat(cmdbuff, ")\r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "srv:listen(");
+        strcat(cmdbuff, port);
+        strcat(cmdbuff, ",function(conn)\r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "conn:on(\"receive\", function(conn, payload) \r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "print(payload)\r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "end)\r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+        strcpy(cmdbuff, "end)\r\n");
+        sendCMD();
+        wait(.5);
+        getReply();
+    }
+}
+
+
+
+// --------------- Main Function ----------------------
+
+
+
 int main() {
     lights = 0;
-    uLCD.printf("LIGHT_ALARM V1.0 Donn Green\n\n");
+    uLCD.printf("LIGHT_ALARM V2.0 Donn Green\n\n");
     uLCD.printf("Press Button 1 to begin light activation mode\n");
     uLCD.printf("Press Button 2 to begin timer activation mode\n");
+    uLCD.printf("Press Button 3 to begin smart home mode\n");
     pb1.mode(PullDown);
     pb2.mode(PullDown);
+    pb3.mode(PullDown);
     lights.period(1.0f/25000.0f);
-    while(!(pb1||pb2)){
+    RPCFunction rpcOn(&alexaLightsOn, "turnOn");
+    RPCFunction rpcOff(&alexaLightsOff, "turnOff");
+    RPCFunction rpcDim(&alexaDimLights, "dim");
+    RPCFunction rpcSet(&alexaTimer, "set");
+    while(!(pb1||pb2||pb3)){
         //do nothing until a button is pressed
     }
     if(pb1){
@@ -126,4 +272,242 @@
         int time = getTime();
         timerMode(time);
     }
+    else if(pb3){
+        alexaMode();
+    }
 }
+
+
+
+// ------------ WIFI Functions ---------------------
+
+
+
+void connectToNetwork() {
+    pc.printf("# Resetting ESP\r\n");
+    uLCD.cls();
+    uLCD.printf("# Resetting ESP\r\n");
+    strcpy(cmdbuff,"node.restart()\r\n");
+    sendCMD();
+    wait(5);
+    getReply();
+
+    led1=1,led2=0,led3=0;
+    pc.printf("# Setting Mode\r\n");
+    uLCD.cls();
+    uLCD.printf("# Setting Mode\r\n");
+    strcpy(cmdbuff, "wifi.setmode(wifi.STATION)\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=1,led3=0;
+    pc.printf("# Connecting to AP\r\n");
+    pc.printf("# ssid = %s\t\tpwd = %s\r\n", ssid, pwd);
+    uLCD.cls();
+    uLCD.printf("# ssid = %s\t\tpwd = %s\r\n");
+    strcpy(cmdbuff, "wifi.sta.config(\"");
+    strcat(cmdbuff, ssid);
+    strcat(cmdbuff, "\",\"");
+    strcat(cmdbuff, pwd);
+    strcat(cmdbuff, "\")\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=0,led3=1;
+    pc.printf("# Get IP Address\r\n");
+    uLCD.cls();
+    uLCD.printf("# Get IP Address\r\n");
+    strcpy(cmdbuff, "print(wifi.sta.getip())\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=1,led2=0,led3=0;
+    pc.printf("# Get Connection Status\r\n");
+    uLCD.cls();
+    uLCD.printf("# Get Connection Status\r\n");
+    strcpy(cmdbuff, "print(wifi.sta.status())\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=1,led3=0;
+    pc.printf("# Listen on Port\r\n");
+    uLCD.cls();
+    uLCD.printf("# Listen on Port\r\n");
+    strcpy(cmdbuff, "srv=net.createServer(net.TCP,");
+    strcat(cmdbuff, timeout);
+    strcat(cmdbuff, ")\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=0,led3=1;
+    strcpy(cmdbuff, "srv:listen(");
+    strcat(cmdbuff, port);
+    strcat(cmdbuff, ",function(conn)\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=1,led2=0,led3=0;
+    strcpy(cmdbuff, "conn:on(\"receive\", function(conn, payload) \r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=1,led3=0;
+    //strcpy(cmdbuff, "conn:send('");
+    //strcat(cmdbuff, reportStatus());
+    //strcat(cmdbuff, "')\r\n");
+    //sendCMD();
+    //getReply();
+
+    wait(2);
+    led1=0,led2=0,led3=1;
+    strcpy(cmdbuff, "print(payload)\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=1,led2=0,led3=0;
+    strcpy(cmdbuff, "end)\r\n");
+    sendCMD();
+    getReply();
+
+    wait(2);
+    led1=0,led2=1,led3=0;
+    strcpy(cmdbuff, "end)\r\n");
+    sendCMD();
+    getReply();
+
+    strcpy(cmdbuff, "tmr.alarm(0, 1000, 1, function()\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff, "if wifi.sta.getip() == nil then\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff, "print(\"Connecting to AP...\\n\")\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff, "else\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff, "ip, nm, gw=wifi.sta.getip()\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff,"print(\"IP Address: \",ip)\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff,"tmr.stop(0)\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff,"end\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    strcpy(cmdbuff,"end)\r\n");
+    sendCMD();
+    getReply();
+    wait(0.2);
+    
+    pc.printf("\n\n++++++++++ Ready ++++++++++\r\n\n");
+}
+
+void sendCMD()
+{
+    int i;
+    char temp_char;
+    bool empty;
+    i = 0;
+// Start Critical Section - don't interrupt while changing global buffer variables
+    NVIC_DisableIRQ(UART1_IRQn);
+    empty = (tx_in == tx_out);
+    while ((i==0) || (cmdbuff[i-1] != '\n')) {
+// Wait if buffer full
+        if (((tx_in + 1) % buffer_size) == tx_out) {
+// End Critical Section - need to let interrupt routine empty buffer by sending
+            NVIC_EnableIRQ(UART1_IRQn);
+            while (((tx_in + 1) % buffer_size) == tx_out) {
+            }
+// Start Critical Section - don't interrupt while changing global buffer variables
+            NVIC_DisableIRQ(UART1_IRQn);
+        }
+        tx_buffer[tx_in] = cmdbuff[i];
+        i++;
+        tx_in = (tx_in + 1) % buffer_size;
+    }
+    if (esp.writeable() && (empty)) {
+        temp_char = tx_buffer[tx_out];
+        tx_out = (tx_out + 1) % buffer_size;
+// Send first character to start tx interrupts, if stopped
+        esp.putc(temp_char);
+    }
+// End Critical Section
+    NVIC_EnableIRQ(UART1_IRQn);
+    return;
+}
+
+// Read a line from the large rx buffer from rx interrupt routine
+void getReply() {
+    int i;
+    i = 0;
+// Start Critical Section - don't interrupt while changing global buffer variables
+    NVIC_DisableIRQ(UART1_IRQn);
+// Loop reading rx buffer characters until end of line character
+    while ((i==0) || (rx_line[i-1] != '\r')) {
+// Wait if buffer empty
+        if (rx_in == rx_out) {
+// End Critical Section - need to allow rx interrupt to get new characters for buffer
+            NVIC_EnableIRQ(UART1_IRQn);
+            while (rx_in == rx_out) {
+            }
+// Start Critical Section - don't interrupt while changing global buffer variables
+            NVIC_DisableIRQ(UART1_IRQn);
+        }
+        rx_line[i] = rx_buffer[rx_out];
+        i++;
+        rx_out = (rx_out + 1) % buffer_size;
+    }
+// End Critical Section
+    NVIC_EnableIRQ(UART1_IRQn);
+    rx_line[i-1] = 0;
+    return;
+}
+
+// Interupt Routine to read in data from serial port
+void Rx_interrupt() {
+    //led3=1;
+// Loop just in case more than one character is in UART's receive FIFO buffer
+// Stop if buffer full
+    while ((esp.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
+        rx_buffer[rx_in] = esp.getc();
+// Uncomment to Echo to USB serial to watch data flow
+        pc.putc(rx_buffer[rx_in]);
+        rx_in = (rx_in + 1) % buffer_size;
+    }
+    return;
+}
+
+
+// Interupt Routine to write out data to serial port
+void Tx_interrupt() {
+    //led2=1;
+// Loop to fill more than one character in UART's transmit FIFO buffer
+// Stop if buffer empty
+    while ((esp.writeable()) && (tx_in != tx_out)) {
+        esp.putc(tx_buffer[tx_out]);
+        tx_out = (tx_out + 1) % buffer_size;
+    }
+    //led2=0;
+    return;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mywifi.h	Wed May 03 15:05:12 2017 +0000
@@ -0,0 +1,5 @@
+void Tx_interrupt();
+void Rx_interrupt();
+void sendCMD();
+void getReply();
+void connectToNetwork();
\ No newline at end of file