Motion and button application for BLE sensor - using purple LIS3DH nRF51822.

Files at this revision

API Documentation at this revision

Comitter:
electronichamsters
Date:
Tue Jun 19 03:39:02 2018 +0000
Parent:
12:9bb01e063498
Commit message:
first revision - new example for stuff animal toy

Changed in this revision

LIS3DH.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
diff -r 9bb01e063498 -r 3450483129a3 LIS3DH.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LIS3DH.lib	Tue Jun 19 03:39:02 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/electronichamsters/code/LIS3DH/#972c166f654b
diff -r 9bb01e063498 -r 3450483129a3 main.cpp
--- a/main.cpp	Sun Aug 27 05:48:45 2017 +0000
+++ b/main.cpp	Tue Jun 19 03:39:02 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.  Random button and motion sensing for modifying toys.
 */
 
 
@@ -33,22 +35,51 @@
 #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 +94,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 +170,12 @@
 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
+static Ticker Tic_Motion;   //used to stop re-enabled latched motion interrupt
 
 /* **** NOT USED **** */
 //16byte UUID loading happens here
@@ -158,9 +196,45 @@
 } PACKED;
 
 
+//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)
+{
+    
+    #if MyDebugEnb
+    device.printf("motion seen \r\n");
+    #endif
+    Tic_Motion.attach(motion_response, 30);     //every x seconds, re-enable motion interrupt
+    if (which_button == 0)  //there's a chance motion would over-riding button press event.  avoid this.
+    {
+        which_button = 11;
+        Flag_Update_IO = 1;
+    }
+
+}
+
+
 
 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 +245,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 +355,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 +472,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 +515,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 +558,9 @@
 }
 
 
+
+
+
 /* ****************************************
  * 
  * Main Loop
@@ -443,6 +604,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 +662,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 +771,82 @@
             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
+            //start of jason data:  "but/?"
+            //"but" for button
+            if (which_button<=10)
+            {
+                JSON_loc = 13;
+                AdvData[JSON_loc] = 0x22;       //ADV_Data[13] = "
+                JSON_loc++; //14
+                
+                AdvData[JSON_loc] = 'b';
+                JSON_loc++; //15
+                
+                AdvData[JSON_loc] = 'u';
+                JSON_loc++; //16
+                
+                AdvData[JSON_loc] = 't';
+                JSON_loc++; //17
+                
+                AdvData[JSON_loc] = 0x2f;       // "/"
+                JSON_loc++; //17
+
+                
+                //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", which_button);    //returns total number of characters, which is 1 character.
+                for (int i=0; i < total_chars; i++)
+                {
+                    AdvData[JSON_loc] = buffer[i];
+                    JSON_loc++;
+                } //JSON_loc left at location of next character
+
+            }// if is a button press
+ 
+             if (which_button==11)
+            {
+                JSON_loc = 13;
+                AdvData[JSON_loc] = 0x22;       //ADV_Data[13] = "
+                JSON_loc++; //14
+                
+                AdvData[JSON_loc] = 's';
+                JSON_loc++; //15
+                
+                AdvData[JSON_loc] = 'h';
+                JSON_loc++; //16
+                
+                AdvData[JSON_loc] = 'a';
+                JSON_loc++; //17
+
+                AdvData[JSON_loc] = 'k';
+                JSON_loc++; //17
+                AdvData[JSON_loc] = 'e';
+                JSON_loc++; //17
+                //AdvData[JSON_loc] = 0x2f;       // "/"
+                //JSON_loc++; //17
+
+            }// if is a button press
             
-            AdvData[JSON_loc] = 0x61;       //ADV_Data[15] = a
-            JSON_loc++; //16
+            which_button = 0;   //reset which button
             
-            AdvData[JSON_loc] = 0x67;       //ADV_Data[16] = g
-            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)
             {
                 AdvData[JSON_loc] = 0x2f;       // ADV_Data[17] = /
                 JSON_loc++;  //18
-                AdvData[JSON_loc] = 0x70;       // ADV_Data[18] =p
+                AdvData[JSON_loc] = 'p';
+                JSON_loc++;  //19
+                AdvData[JSON_loc] = 'e';
+                JSON_loc++;  //19
+                AdvData[JSON_loc] = 'r';
+                JSON_loc++;  //19
+                AdvData[JSON_loc] = 0x2f;       // ADV_Data[17] = /
+                JSON_loc++;  //18
+                AdvData[JSON_loc] = 'p';       // ADV_Data[18] =p
                 JSON_loc++;  //19
             }
             
@@ -646,7 +859,7 @@
             //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", button_pressed_ms);    //returns total number of characters, which is 1 character.
             for (int i=0; i < total_chars; i++)
             {
                 AdvData[JSON_loc] = buffer[i];
@@ -701,5 +914,8 @@
 
         
         ble.waitForEvent(); //sleeps until interrupt form ticker or I/O
+
+        
+        //wait_ms(1000);
     }//end forever while
 }//end main