BLE washer / dryer sensor

Revision:
13:4b9bbd8d8d1f
Parent:
12:9bb01e063498
Child:
14:69eb8aa4cbfd
--- a/main.cpp	Sun Aug 27 05:48:45 2017 +0000
+++ b/main.cpp	Tue Jun 19 03:55:00 2018 +0000
@@ -1,5 +1,5 @@
 /*  
- * Copyright (c) Eric Tsai 2017
+ * Copyright (c) Eric Tsai 2018
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +21,8 @@
  * BLE sensor as Beacon advertisements.  Intended to function with specific BLE observer.
  * Tested on nRF51822 targets on mbed.
  * keywords:  todo, tochange
+ *
+ * LIS3DH on purple board.  Use for washer/dryer sensor.
 */
 
 
@@ -33,22 +35,53 @@
 #include "toolchain.h"
 #include "ble/BLE.h"
 #include "TMP_nrf51/TMP_nrf51.h"
-
+#include "LIS3DH.h" //https://developer.mbed.org/users/kenjiArai/code/LIS3DH/
 
 /*******************************************************************************************
  * START tochange: items that may need customization depending on sensors, hardware, and desired behavior
 *******************************************************************************************/
-const uint16_t Periodic_Update_Seconds = 20; //number of seconds between periodic I/O status re-transmits 900s =15 min.
+const uint16_t Periodic_Update_Seconds = 900; //number of seconds between periodic I/O status re-transmits 900s =15 min.
 #define MyDebugEnb 0  //enables serial output for debug, consumes ~1mA when idle
 uint8_t magnet_near=0;  //this I/O, specifically for reed switch sensor
 
+#define sensorEnb 1     //get readings
+#define buttonEnb 1
+
+
 
 /* hardware interrupt pins, selected based on hardware
  *Syntax:  Pin "P0.4" on nRF51822 documentation is mbed "p4".
  * InterruptIn is pulled-up.  GND the pin to activate.
 */
-InterruptIn button1(p0);    //nRF51822 P0.0
-InterruptIn button2(p1);    //nRF51822 P0.1
+#if buttonEnb
+InterruptIn button1(p16);    //nRF51822 
+InterruptIn button2(p15);    //nRF51822 
+InterruptIn button3(p12);    //nRF51822
+InterruptIn button4(p23);    //nRF51822
+InterruptIn button5(p24);    //nRF51822
+InterruptIn button6(p25);    //nRF51822
+InterruptIn button7(p28);    //nRF51822
+InterruptIn button8(p29);    //nRF51822
+InterruptIn button9(p30);    //nRF51822
+
+
+#endif
+
+#if sensorEnb
+InterruptIn lis3dh_int1(p1);    //nRF51822 P0.1
+//LIS3DH data(p6, p7, (0x19 << 1));  //for purple board, sda=p6, scl=p7
+LIS3DH data(p6, p7, LIS3DH_V_CHIP_ADDR); 
+
+//0001 1001  ---> 0011 0010
+#endif
+bool flag_read_acc;
+
+
+
+
+//purple boards
+//InterruptIn button1(p23);    //nRF51822 P0.23
+//InterruptIn button2(p24);    //nRF51822 P0.24
 /******************************************************************************************
  * END tochange
 *******************************************************************************************/
@@ -63,6 +96,7 @@
 static Ticker Tic_Debounce; //debounce I/O
 static Ticker Tic_Periodic; //transmit sensor data on a periodic basis outside I/O events
 
+
 const uint16_t Periodicity = 1800;   //birthday periodicity used for spoof checking, must match gateway. Should be 1800 seconds for 30minutes
 static Timer Tmr_From_Birthday;  //holds number of seconds since birthday, for spoof detection
 static Ticker Tic_Birthday; //resets Tmr_From_Birthday every Periodicity seconds, for spoof detection
@@ -138,6 +172,28 @@
 uint8_t Xmit_Cnt = 1;
 
 
+//track button press on toy
+Timer Tmr_Click_Duration;
+uint8_t which_button = 0;
+uint16_t button_pressed_ms;
+const uint8_t  reset_addr = 0x31; //LIS3DH_INT1_SOURCE
+
+//track motion
+static Ticker Tic_Motion;   //used to stop re-enabled latched motion interrupt
+static uint8_t Cnt_Activity = 0;
+//const uint8_t SECONDS_RESET = 120;        //Every x seconds, reset ___
+
+// SECONDS_CONSIDER_ACTIVITY should be > SECONDS_RE_ENABLE_MOTION_INT;
+const uint8_t SECONDS_RE_ENABLE_MOTION_INT = 20; //re-enable motion interrupt after X seconds
+//const uint8_t SECONDS_CONSIDER_ACTIVITY = 20;   //must see motion interrupt 
+const uint8_t COUNT_CONSIDER_ACTIVITY = 3; // Cnt_Activity must be greater than this before activity broadcast
+
+//this is like deadband between seeing motion and no motion.
+const uint8_t SECONDS_RESET_ACTIVITY = 140;  //reset Cnt_Activity after X seconds of no activity.
+//Timer Tmr_Btw_Motion;   //?? need to start somewhere;
+static Ticker Tic_Reset_CNT_Activity;
+static bool Flag_Activity=0;
+
 
 /* **** NOT USED **** */
 //16byte UUID loading happens here
@@ -159,8 +215,75 @@
 
 
 
+void Reset_CNT_Activity_Callback (void)
+{
+    if (Flag_Activity == 1)
+    {
+        Flag_Activity = 0;
+        Flag_Update_IO = 1;
+    }
+    Tic_Reset_CNT_Activity.detach();
+    Cnt_Activity = 0;
+}
+
+//called on tic
+void motion_response(void)
+{
+    Tic_Motion.detach();
+    #if sensorEnb
+    data.read_reg(reset_addr);  //reset's the latched interrupt
+    #endif
+    
+}
+
+//called on interrupt
+void motion_Callback(void)
+{
+    
+    //after motion seen, wait a while before resetting motion interrupt latch
+    Tic_Motion.attach(motion_response, SECONDS_RE_ENABLE_MOTION_INT);     //every x seconds, re-enable motion interrupt
+    
+    //reject incidental motion (like when loading laundry)
+    Tic_Reset_CNT_Activity.attach(Reset_CNT_Activity_Callback, SECONDS_RESET_ACTIVITY);
+    //if (which_button == 0)  //there's a chance motion would over-riding button press event.  avoid this.
+    //{
+    //    which_button = 11;
+    //    Flag_Update_IO = 1;
+    //}
+    //Tmr_Btw_Motion.start();  ??start here?
+    //if (Tmr_Btw_Motion.read_ms() < SECONDS_CONSIDER_ACTIVITY)
+    //{
+    if (Cnt_Activity>40)
+    {
+        //stop incrementing
+    }
+    else
+    {
+        Cnt_Activity++;
+    }
+    if ((Cnt_Activity > COUNT_CONSIDER_ACTIVITY) && (Flag_Activity == 0))
+    {
+        Flag_Activity = 1;
+        Flag_Update_IO = 1; //send signal, there's good vibrations!
+        //Tmr_Btw_Motion.reset();
+            
+    }
+
+}
+
+
+
+
 void debounce_Callback(void)
 {
+    //stop timer, save time
+    Tmr_Click_Duration.stop();
+    button_pressed_ms =(uint16_t)(Tmr_Click_Duration.read_ms());
+    #if MyDebugEnb
+    device.printf("sending BLE for button %d \r\n", which_button);
+    #endif
+    
+    
     Tic_Debounce.detach();
     Flag_Update_IO = true;  //start advertising
     /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
@@ -171,14 +294,97 @@
 //ISR for I/O interrupt
 void buttonPressedCallback(void)
 {
-    Tic_Debounce.attach(debounce_Callback, 1); //ok to attach multiple times, recent one wins
+    //wait_ms(2);  //debounce
+    //read I/O, mark which button was pressed
+    
+
+#if buttonEnb
+
+    
+    if (button1.read() == 0)    //buttons are pulled up, gnd when pressed
+    {
+        which_button = 1;
+        #if MyDebugEnb
+        device.printf("is 1 button \r\n");
+        #endif
+    }
+    else if (button2.read() == 0)
+    {
+        which_button = 2;
+        #if MyDebugEnb
+        device.printf("is 2 button \r\n");
+        #endif
+    }
+    else if (button3.read() == 0)
+    {
+        which_button = 3;
+        #if MyDebugEnb
+        device.printf("is 3 button \r\n");
+        #endif
+    }
+    if (button4.read() == 0)    //buttons are pulled up, gnd when pressed
+    {
+        which_button = 4;
+        #if MyDebugEnb
+        device.printf("is 4 button \r\n");
+        #endif
+    }
+    else if (button5.read() == 0)
+    {
+        which_button = 5;
+        #if MyDebugEnb
+        device.printf("is 5 button \r\n");
+        #endif
+    }
+    else if (button6.read() == 0)
+    {
+        which_button = 6;
+        #if MyDebugEnb
+        device.printf("is 6 button \r\n");
+        #endif
+    }
+    if (button7.read() == 0)    //buttons are pulled up, gnd when pressed
+    {
+        which_button = 7;
+        #if MyDebugEnb
+        device.printf("is 7 button \r\n");
+        #endif
+    }
+    else if (button8.read() == 0)
+    {
+        which_button = 8;
+        #if MyDebugEnb
+        device.printf("is 8 button \r\n");
+        #endif
+    }
+    else if (button9.read() == 0)
+    {
+        which_button = 9;
+        #if MyDebugEnb
+        device.printf("is 9 button \r\n");
+        #endif
+    }
+    else
+    {
+    }
+#endif
+    
+
+    
+    #if MyDebugEnb
+    device.printf("interrupt button= %d \r\n", which_button);
+    #endif
+    //reset and start timer
+    Tmr_Click_Duration.reset();
+    Tmr_Click_Duration.start();
+    
 }
 
 //ISR for I/O interrupt
 void buttonReleasedCallback(void)
 {
-    
-    Tic_Debounce.attach(debounce_Callback, 1);  
+
+    Tic_Debounce.attach(debounce_Callback, 0.3);
 }
 
 
@@ -198,6 +404,7 @@
 {
     Flag_Update_IO = true;
     Flag_Periodic_Call = true;
+    which_button = 12;  //no real button presses, just arbitrarly pick 12 to represent this.
 }
 
 
@@ -314,13 +521,13 @@
     
     //while loop doesn't actually loop until reading comlete, use a wait.
     while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {};
-    wait_ms(1);
+    wait_ms(2);
 
     //save off RESULT before disabling.
     //uint16_t myresult = (uint16_t)NRF_ADC->RESULT;
     
     //disable ADC to lower bat consumption
-    NRF_ADC->TASKS_STOP = 1;
+    //NRF_ADC->TASKS_STOP = 1;  //perform disable in main loop
     //NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;    //disable to shutdown ADC & lower bat consumption
     
     return (uint16_t)NRF_ADC->RESULT; // 10 bit
@@ -357,7 +564,7 @@
     
     //while loop doesn't actually loop until reading comlete, use a wait.
     while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {};
-    wait_ms(1);     //needed because busy while loop doesn't run.
+    wait_ms(2);     //needed because busy while loop doesn't run.
 
     //save off RESULT before disabling.
     //uint16_t myresult = (uint16_t)NRF_ADC->RESULT;
@@ -400,6 +607,9 @@
 }
 
 
+
+
+
 /* ****************************************
  * 
  * Main Loop
@@ -443,6 +653,55 @@
         }
         device.printf("\r\n");
     #endif
+    
+    //set motion sensor
+
+    #if sensorEnb
+    data.setAct(LIS3DH_V_CHIP_ADDR);
+    #endif
+    //for puppet, go ahead and pull up all the time.
+    
+    #if buttonEnb
+
+    button1.mode(PullUp);
+    button2.mode(PullUp);
+    button3.mode(PullUp);
+    button4.mode(PullUp);
+    button5.mode(PullUp);
+    button6.mode(PullUp);
+    button7.mode(PullUp);
+    button8.mode(PullUp);
+    button9.mode(PullUp);
+    #endif
+    
+    #if sensorEnb
+    lis3dh_int1.mode(PullNone);   //if pulled up, will consume 200uA. LIS3DH has pull up enabled.
+    #endif
+    
+    #if buttonEnb
+    button1.fall(buttonPressedCallback);     //enable interrupt
+    button2.fall(buttonPressedCallback);     //enable interrupt
+    button3.fall(buttonPressedCallback);     //enable interrupt
+    button4.fall(buttonPressedCallback);     //enable interrupt
+    button5.fall(buttonPressedCallback);     //enable interrupt
+    button6.fall(buttonPressedCallback);     //enable interrupt
+    button7.fall(buttonPressedCallback);     //enable interrupt
+    button8.fall(buttonPressedCallback);     //enable interrupt
+    button9.fall(buttonPressedCallback);     //enable interrupt
+    button1.rise(buttonReleasedCallback);     //enable interrupt
+    button2.rise(buttonReleasedCallback);     //enable interrupt
+    button3.rise(buttonReleasedCallback);     //enable interrupt
+    button4.rise(buttonReleasedCallback);     //enable interrupt
+    button5.rise(buttonReleasedCallback);     //enable interrupt
+    button6.rise(buttonReleasedCallback);     //enable interrupt
+    button7.rise(buttonReleasedCallback);     //enable interrupt
+    button8.rise(buttonReleasedCallback);     //enable interrupt
+    button9.rise(buttonReleasedCallback);     //enable interrupt
+    #endif
+    #if sensorEnb
+    lis3dh_int1.rise(motion_Callback);     //enable interrupt
+    #endif
+    
     while (true) 
     {  //Main Loop
 
@@ -452,69 +711,18 @@
             device.printf("current time in seconds: %d \r\n", seconds_Old);
         #endif
 
-        //set both pins to pull-up, so they're not floating when we read state
-        button1.mode(PullUp);
-        button2.mode(PullUp);
+
         
         //expect either button1 or button2 is grounded, b/c using SPDT reed switch
         //the "common" pin on the reed switch should be on GND
-        uint8_t button1_state = button1.read();
-        uint8_t button2_state = button2.read();
+        //uint8_t button1_state = button1.read();
+        //uint8_t button2_state = button2.read();
+        //uint8_t button3_state = button3.read();
         
         
-        //let's just update the pins on every wake.  Insurance against const drain.
-        //if state == 0, pin is grounded.  Unset interrupt and float pin, set the other pin for ISR
-        if ( (button1_state == 0) && (button2_state == 1) )
-        {
-            magnet_near = 1;
-            //button1.disable_irq() //don't know if disables IRQ on port or pin
-            button1.fall(NULL);     //disable interrupt
-            button1.rise(NULL);     //disable interrupt
-            button1.mode(PullNone); //float pin to save battery
-            
-            //button2.disable_irq() //don't know if disables IRQ on port or pin
-            button2.fall(buttonReleasedCallback);     //enable interrupt
-            button2.rise(buttonReleasedCallback);     //enable interrupt
-            button2.mode(PullUp); //pull up on pin to get interrupt
-            #if MyDebugEnb
-            device.printf("=== button 1!  %d seconds=== \r\n", seconds_Old);
-            #endif
-        }  //end if button2
-        else if ( (button1_state == 1) && (button2_state == 0) )       //assume other pin is open circuit
-        {
-            magnet_near = 0;
-            //button1.disable_irq() //don't know if disables IRQ on port or pin
-            button1.fall(buttonReleasedCallback);     //enable interrupt
-            button1.rise(buttonReleasedCallback);     //enable interrupt
-            button1.mode(PullUp); //pull up on pin to get interrupt
-            
-            //button2.disable_irq() //don't know if disables IRQ on port or pin
-            button2.fall(NULL);     //disable interrupt
-            button2.rise(NULL);     //disable interrupt
-            button2.mode(PullNone); //float pin to save battery
-            #if MyDebugEnb
-            device.printf("=== button 2! === %d seconds\r\n", seconds_Old);
-            #endif
-        }  //end if button1
-        else    //odd state, shouldn't happen, suck battery and pullup both pins
-        {
-            magnet_near = 2;
-            //AdvData[4] = 0x33;
-            //button1.disable_irq() //don't know if disables IRQ on port or pin
-            button1.fall(buttonReleasedCallback);     //disable interrupt
-            button1.rise(buttonReleasedCallback);     //disable interrupt
-            button1.mode(PullUp); //float pin to save battery
-            
-            //button2.disable_irq() //don't know if disables IRQ on port or pin
-            button2.fall(buttonReleasedCallback);     //disable interrupt
-            button2.rise(buttonReleasedCallback);     //disable interrupt
-            button2.mode(PullUp); //float pin to save battery
-            #if MyDebugEnb
-            device.printf("no buttons!! %d seconds\r\n", seconds_Old);
-            #endif
-        }  //end odd state
-        
-        
+
+    
+    
         if (Flag_Update_IO) {
             /* Do blocking calls or whatever hardware-specific action is
              * necessary to poll the sensor. */
@@ -612,28 +820,37 @@
             AdvData[12] = Xmit_Cnt;
             JSON_loc++;
             
-            //start of jason data
-            //"mag":
-            JSON_loc = 13;
-            AdvData[JSON_loc] = 0x22;       //ADV_Data[13] = "
-            JSON_loc++; //14
             
-            AdvData[JSON_loc] = 0x6d;       //ADV_Data[14] = m
-            JSON_loc++; //15
-            
-            AdvData[JSON_loc] = 0x61;       //ADV_Data[15] = a
-            JSON_loc++; //16
-            
-            AdvData[JSON_loc] = 0x67;       //ADV_Data[16] = g
-            JSON_loc++; //17
-            
+            //start of jason data:  "but/?"
+            //"but" for button
+
+                JSON_loc = 13;
+                AdvData[JSON_loc] = 0x22;       //ADV_Data[13] = "
+                JSON_loc++; //14
+                
+                AdvData[JSON_loc] = 'v';
+                JSON_loc++; //15
+                
+                AdvData[JSON_loc] = 'i';
+                JSON_loc++; //16
+                
+                AdvData[JSON_loc] = 'b';
+                JSON_loc++; //17
+                
+                //AdvData[JSON_loc] = 0x2f;       // "/"
+                //JSON_loc++; //17
+
+                
+
+
             //for periodic calls, we want to add an extra mqtt level "p", using "/p"
             //to delineate between MQTT publishes from real world I/O interrupts vs timer interrupts
             if (Flag_Periodic_Call)
             {
+                JSON_loc++;  //19
                 AdvData[JSON_loc] = 0x2f;       // ADV_Data[17] = /
                 JSON_loc++;  //18
-                AdvData[JSON_loc] = 0x70;       // ADV_Data[18] =p
+                AdvData[JSON_loc] = 'p';       // ADV_Data[18] =p
                 JSON_loc++;  //19
             }
             
@@ -646,14 +863,13 @@
             //convert magnet variable to string, for magnet sensor, this is easy
             //since we only have 1 or 0, but this also works for analog values
             memset(&buffer[0], 0, sizeof(buffer));      //clear out buffer
-            total_chars = sprintf (buffer, "%d", magnet_near);    //returns total number of characters, which is 1 character.
+            total_chars = sprintf (buffer, "%d", Flag_Activity);    //returns total number of characters, which is 1 character.
             for (int i=0; i < total_chars; i++)
             {
                 AdvData[JSON_loc] = buffer[i];
                 JSON_loc++; //23
             } //JSON_loc left at location of next character
             
-                        
             //AdvData[JSON_loc] = 0x0;    //since AdvData was cleared to start with, we don't need to null term
 
             ApplicationData_t appData;
@@ -701,5 +917,8 @@
 
         
         ble.waitForEvent(); //sleeps until interrupt form ticker or I/O
+
+        
+        //wait_ms(1000);
     }//end forever while
 }//end main