nRF51822 BLE project for TMP102 temperature sensor
Dependencies: BLE_API TMP102 mbed nRF51822
Diff: main.cpp
- Revision:
- 10:79e8f92ef156
- Parent:
- 9:b6302fc4e754
- Child:
- 11:4f925834167d
--- a/main.cpp Mon Jul 10 04:19:07 2017 +0000 +++ b/main.cpp Sat Jul 29 21:49:44 2017 +0000 @@ -1,10 +1,8 @@ -/* +/* +Eric Tsai - Eric Tsai - todo: hash mac to create unqiue identifier for "my" sensors. - -BLE sensor - +7/29/2017: added clock algorithm to corresond with gateway spoof checking + */ //required to call the ecb functions @@ -19,7 +17,7 @@ #include "TMP_nrf51/TMP_nrf51.h" //comment out when done with debug uart, else eats batteries -#define MyDebugEnb 1 +#define MyDebugEnb 0 //Pin "P0.4" on nRF51822 = mbed "p4". //InterruptIn is pulled-up. GND the pin to activate. @@ -29,9 +27,16 @@ //InterruptIn button2(p11); // purple board ****** -InterruptIn button1(p23); -InterruptIn button2(p24); +//InterruptIn button1(p23); +//InterruptIn button2(p24); +// universal +InterruptIn button1(p0); +InterruptIn button2(p1); + +// Rigado BMD200 ****** +//InterruptIn button1(p4); +//InterruptIn button2(p5); //Serial device(p9, p11); // tx, rx, purple board and Rigado #if MyDebugEnb @@ -39,12 +44,13 @@ Serial device(p9, p11); //nRF51822 uart : TX=p9. RX=p11 #endif -//InterruptIn button(p4); //Pin P0.4 on = mbed "p3"; - +static Timer myTimer; //timed advertising static Ticker tic_adv; //stop adv static Ticker tic_debounce; //debounce I/O static Ticker tic_periodic; //regular updates +static Ticker tic_clock_reset; //resets clock +const uint16_t Periodicity = 180; //clock periodicity used for spoof checking, should be 1800 seconds for 30minutes //static TMP_nrf51 tempSensor; static bool flag_update_io = false; static bool flag_periodic_call = false; @@ -69,6 +75,9 @@ //full with nullls static uint8_t AdvData[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; /* Example of hex data */ char buffer[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //battery analog reading +char bat_volt_char[6] = {0, 0, 0, 0, 0, 0}; +uint8_t Adv_First_Section[10]; +uint8_t mac_reverse[6] = {0x0,0x0,0x0,0x0,0x0,0x0}; uint8_t magnet_near=0; @@ -81,6 +90,7 @@ static uint8_t src_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4}; static uint8_t des_buf[16] = {0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4,0x1,0x2,0x3,0x4}; +uint8_t Xmit_Cnt = 1; //const static uint8_t AdvData[] = {"ChangeThisData"}; /* Example of character data */ @@ -176,6 +186,15 @@ flag_periodic_call = true; } +void clock_reset_Callback(void) +{ +#if MyDebugEnb + device.printf("===== reset timer ====="); + device.printf("\r\n"); +#endif + myTimer.reset(); +}; + void setupApplicationData(ApplicationData_t &appData) { // two byte ID: 0xFEFE @@ -249,18 +268,69 @@ //https://developer.mbed.org/users/MarceloSalazar/notebook/measuring-battery-voltage-with-nordic-nrf51x/ void my_analogin_init(void) { - NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; + NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | + //(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | + //(ADC_CONFIG_PSEL_AnalogInput4 << ADC_CONFIG_PSEL_Pos) | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); + NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; } uint16_t my_analogin_read_u16(void) { - NRF_ADC->CONFIG &= ~ADC_CONFIG_PSEL_Msk; - NRF_ADC->CONFIG |= ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos; + //10 bit resolution, route Vdd as analog input, set ADC ref to VBG band gap + //disable analog pin select "PSEL" because we're using Vdd as analog input + //no external voltage reference + NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | + (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | + //(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | + (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | + (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | + //(ADC_CONFIG_PSEL_AnalogInput4 << ADC_CONFIG_PSEL_Pos) | + (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); + + //NRF_ADC->CONFIG &= ~ADC_CONFIG_PSEL_Msk; + //NRF_ADC->CONFIG |= ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos; + NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; + NRF_ADC->TASKS_START = 1; + + + //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(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->ENABLE = ADC_ENABLE_ENABLE_Disabled; //disable to shutdown ADC & lower bat consumption + + return (uint16_t)NRF_ADC->RESULT; // 10 bit + //return myresult; +} + +uint16_t my_analog_pin_read(void) +{ + + //10 bit resolution, route PSEL pin as 1/3 input sel, + //set ADC ref to VBG band gap + //set AnalogInput4 as input pin (this is P0.03) + //no external voltage reference + NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | + //(ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | + (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | + (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | + //ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | + (ADC_CONFIG_PSEL_AnalogInput4 << ADC_CONFIG_PSEL_Pos) | + (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); + //set pin select to AnalogInput4 = pin 7 = p0.03 = AIN4 + //NRF_ADC->CONFIG &= ~ADC_CONFIG_PSEL_Msk; + //NRF_ADC->CONFIG |= ADC_CONFIG_PSEL_AnalogInput4 << ADC_CONFIG_PSEL_Pos; + NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; NRF_ADC->TASKS_START = 1; @@ -279,6 +349,34 @@ //return myresult; } + +//hash_first_section(Adv_First_Section, mac_reverse, bat_reading); +void hash_first_section(uint8_t * dest, const uint8_t * mac_addr, const char * bat_volt_str) +{ + dest[0] = mac_addr[3]; + dest[1] = mac_addr[2]; + dest[2] = mac_addr[1]; + dest[3] = mac_addr[0]; + dest[4] = bat_volt_str[0]; + dest[5] = bat_volt_str[1]; + dest[6] = bat_volt_str[2]; + dest[7] = bat_volt_str[3]; + dest[8] = 0x10; + dest[9] = 0x11; +#if MyDebugEnb + + device.printf("hash array: "); + for (int i=0; i<10; i++) + { + device.printf("%x ", dest[i]); + } + device.printf("\r\n"); +#endif +} + + +uint16_t clock_remainder = 0; + int main(void) { @@ -290,7 +388,7 @@ - Timer myTimer; //timed advertising + //Timer myTimer; //moved to global myTimer.start(); @@ -333,11 +431,38 @@ while (ble.hasInitialized() == false) { /* spin loop */ } //every X seconds, sends period update, up to 1800 (30 minutes) - tic_periodic.attach(periodic_Callback, 10); + tic_periodic.attach(periodic_Callback, 1600); + tic_clock_reset.attach(clock_reset_Callback, Periodicity); + + //how to generate random number using die tempearature + uint32_t myTempRand; + uint32_t * p_temp; + //get temperature for random number + //SVCALL(SD_TEMP_GET, myTempRand, sd_temp_get(p_temp)); + //sd_temp_get(& myTempRand); + + ble.getAddress(0,mac_reverse); //NOTE: last byte of MAC (as shown on phone app) is at mac[0], not mac[6]; +#if MyDebugEnb + device.printf("mac = "); + for (int i=0; i<6; i++) //prints out MAC address in reverse order; opps. + { + device.printf("%x:", mac_reverse[i]); + } + device.printf("\r\n"); +#endif while (true) { + //seconds counts to 35 minutes: mySeconds=2142, then 63392 which should be 2450 but isn't. + //00001000,01011110 -> 11110111,10100000 + uint16_t mySeconds =(uint16_t)(myTimer.read_ms()/1000); //problem: mySeconds is only 2 byte + //xmit_cnt++; + //if (mySeconds > 1800) + //{ + // myTimer.reset(); + //clock_remainder = mySeconds - 1800; + //} + //mySeconds = mySeconds + clock_remainder; l3kjl3 - uint16_t mySeconds =(uint16_t)(myTimer.read_ms()/1000); //problem: mySeconds is only 2 byte //reading the ADV value, only goes up to 0-255; //reading the uart: current time in seconds: -1782, goes negative. //need to be able to count 1800 seconds since that's the length of timer. @@ -378,23 +503,29 @@ button1.mode(PullNone); //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 + 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", mySeconds); +#endif } else if ( (button1_state == 1) && (button2_state == 0) ) //assume other pin is open circuit { magnet_near = 0; //AdvData[4] = 0x22; //dont' set ADV data directly. Using json now, need spacing //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 + 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", mySeconds); +#endif } else //odd state, shouldn't happen, suck battery and pullup both pins { @@ -409,6 +540,9 @@ 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", mySeconds); +#endif } @@ -416,8 +550,15 @@ /* Do blocking calls or whatever hardware-specific action is * necessary to poll the sensor. */ + Xmit_Cnt++; //increment transmit counter when updating I/O + + + //read battery voltage //analog reading consumes 940uA if not disabled + + bat_reading = (float)my_analogin_read_u16(); + bat_reading = (bat_reading * 3.6) / 1024.0; #if MyDebugEnb device.printf("bat reading: %f \r\n", bat_reading); @@ -431,104 +572,131 @@ //AdvData[10] = buffer[2];//"3"=0x33 //AdvData[11] = buffer[3];//"2"=0x32 + //try this + //https://developer.mbed.org/users/mbed_official/code/mbed-src/file/cb4253f91ada/targets/hal/TARGET_NORDIC/TARGET_NRF51822/analogin_api.c + NRF_ADC->TASKS_STOP = 1; + float analogreading; + analogreading = (float)my_analog_pin_read(); + analogreading = (analogreading * 3.6) / 1024.0; + #if MyDebugEnb + device.printf("separate analog reading: %.02f \r\n", analogreading); + #endif + //disable ADC NRF_ADC->TASKS_STOP = 1; NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled; //disable to shutdown ADC & lower bat consumption + + //*********************************** //form JSON string in ADV_DATA //1) volts starts at AdvData[8] - memset(&AdvData[0], 0, sizeof(AdvData)); - uint8_t JSON_loc=0; //DEC"vo": <--- - AdvData[JSON_loc] = 0x44; //D - JSON_loc++; - AdvData[JSON_loc] = 0x45; //E - JSON_loc++; - AdvData[JSON_loc] = 0x43; //C - JSON_loc++; - AdvData[JSON_loc] = mySeconds & 0xFF; //reserved for timer - JSON_loc++; - AdvData[JSON_loc] = (mySeconds >> 8) & 0xFF;; //reserved for timer - JSON_loc++; - AdvData[JSON_loc] = 0x22; //" - JSON_loc++; - AdvData[JSON_loc] = 0x76; //V volt - JSON_loc++; - AdvData[JSON_loc] = 0x6f; //o - JSON_loc++; - AdvData[JSON_loc] = 0x6C; //l - JSON_loc++; - AdvData[JSON_loc] = 0x74; //t - JSON_loc++; - AdvData[JSON_loc] = 0x22; //" - JSON_loc++; - AdvData[JSON_loc] = 0x3a; //: - JSON_loc++; - - - //write battery voltage uint8_t total_chars; - memset(&buffer[0], 0, sizeof(buffer)); //clear out buffer - total_chars = sprintf (buffer, "%.2f", bat_reading); //returns total number of characters + memset(&bat_volt_char[0], 0, sizeof(bat_volt_char)); //clear out buffer + total_chars = sprintf (bat_volt_char, "%.2f", bat_reading); //returns total number of characters #if MyDebugEnb - device.printf("char buff: %c%c%c%c \r\n", buffer[0], buffer[1], buffer[2], buffer[3]); + device.printf("char buff: %c%c%c%c \r\n", bat_volt_char[0], bat_volt_char[1], bat_volt_char[2], bat_volt_char[3]); device.printf("num chars: %d \r\n", total_chars); #endif - for (int i=0; i < total_chars; i++) - { - AdvData[JSON_loc] = buffer[i]; - JSON_loc++; -#if MyDebugEnb - device.printf("JSON_loc: %d buf[]:%c \r\n", JSON_loc, buffer[i]); -#endif - } //JSON_loc left at location of next character + + + //memset(&Adv_First_Section[0], 0, sizeof(Adv_First_Section)); //not needed to reset + hash_first_section(Adv_First_Section, mac_reverse, bat_volt_char); + + - //DEC"vo":3.11," - AdvData[JSON_loc] = 0x2c; //, + //------------------------------------------------------------------ + //start writing out ADVData array + //------------------------------------------------------------------ + + memset(&AdvData[0], 0, sizeof(AdvData)); + uint8_t JSON_loc=0; //AdvData[0] + + AdvData[0] = Adv_First_Section[0]; //AdvData[0] = manf ID 01 + JSON_loc++; //1 + AdvData[1] = Adv_First_Section[1]; //AdvData[1] = manf ID 02 + JSON_loc++; //2 + AdvData[2] = Adv_First_Section[2]; //AdvData[2] = reserved + JSON_loc++; //3... + AdvData[3] = Adv_First_Section[3]; //AdvData[3] = reserved + JSON_loc++; + AdvData[4] = Adv_First_Section[4]; //AdvData[4] = voltage 01 + JSON_loc++; + AdvData[5] = Adv_First_Section[5]; //AdvData[5] = voltage 02 + JSON_loc++; + AdvData[6] = Adv_First_Section[6]; //AdvData[6] = voltage 03 + JSON_loc++; + AdvData[7] = Adv_First_Section[7]; //AdvData[7] = voltage 04 + JSON_loc++; + AdvData[8] = Adv_First_Section[8]; //AdvData[8] = reserved + JSON_loc++; + AdvData[9] = Adv_First_Section[9]; //AdvData[9] = reserved JSON_loc++; - - AdvData[JSON_loc] = 0x22; //" start mag - JSON_loc++; - - AdvData[JSON_loc] = 0x6d; //m + +#if MyDebugEnb + + device.printf("ADV first 10 array: "); + for (int i=0; i<10; i++) + { + device.printf("%x ", AdvData[i]); + } + device.printf("\r\n"); +#endif + + + JSON_loc = 10; + //start of encrypted data + //AdvData[10] + AdvData[10] = mySeconds & 0xFF; //reserved for timer JSON_loc++; - - AdvData[JSON_loc] = 0x61; //a + AdvData[11] = (mySeconds >> 8) & 0xFF; //reserved for timer + JSON_loc++; + AdvData[12] = Xmit_Cnt; JSON_loc++; + //start of jason data + JSON_loc = 13; + AdvData[JSON_loc] = 0x22; //" start mag pos=13 + JSON_loc++; //14 - AdvData[JSON_loc] = 0x67; //g - JSON_loc++; + AdvData[JSON_loc] = 0x6d; //m, pos=14 + JSON_loc++; //15 + + AdvData[JSON_loc] = 0x61; //a, pos=15 + JSON_loc++; //16 + + AdvData[JSON_loc] = 0x67; //g, pos=16 + JSON_loc++; //17 if (flag_periodic_call) { //AdvData[JSON_loc] = 0x2f; // "/" //JSON_loc++; - AdvData[JSON_loc] = 0x2f; // "/" - JSON_loc++; - AdvData[JSON_loc] = 0x70; // "p" - JSON_loc++; + AdvData[JSON_loc] = 0x2f; // "/" pos=17 + JSON_loc++;//pos=18 + AdvData[JSON_loc] = 0x70; // "p" poes=18 + JSON_loc++;//pos=19 }//end if period call - AdvData[JSON_loc] = 0x22; //" - JSON_loc++; + AdvData[JSON_loc] = 0x22; //" pos = 17 or 19 + JSON_loc++; //20 - AdvData[JSON_loc] = 0x3a; //: - JSON_loc++; + AdvData[JSON_loc] = 0x3a; //: pos = 18 or 20 + JSON_loc++; //22 //prep magnet location (1 or 0) for char[] memset(&buffer[0], 0, sizeof(buffer)); //clear out buffer //magnet_near is an integer - total_chars = sprintf (buffer, "%d", magnet_near); //returns total number of characters + total_chars = sprintf (buffer, "%d", magnet_near); //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++; //23 } //JSON_loc left at location of next character //MUST null terminate for JSON to read correctly, else get intermittent JSON parse errors at gateway @@ -541,10 +709,10 @@ ApplicationData_t appData; setupApplicationData(appData); - + for (int i=0; i<16; i++) { - src_buf[i] = AdvData[i+3]; + src_buf[i] = AdvData[i+10]; //start of encrypted section is at AdvData[10] } //nrf_ecb_set_key(key_buf); @@ -558,7 +726,7 @@ #endif for (int i=0; i<16; i++) { - AdvData[i+3] = des_buf[i]; + AdvData[i+10] = des_buf[i]; } //ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *) &appData, sizeof(ApplicationData_t)); @@ -572,16 +740,9 @@ //ble_error_t getAddress(Gap::AddressType_t *typeP, Gap::Address_t address) //ble.gap().getAddress(myType, myAddress); //ble.gap().getAddress(Gap::AddressType_t *typeP, Gap::Address_t address); - uint8_t mac[6] = {0x0,0x0,0x0,0x0,0x0,0x0}; - ble.getAddress(0,mac); //NOTE: last byte of MAC (as shown on phone app) is at mac[0], not mac[6]; -#if MyDebugEnb - device.printf("mac = "); - for (int i=0; i<6; i++) - { - device.printf("%x:", mac[i]); - } - device.printf("\r\n"); -#endif + + + ble.gap().startAdvertising(); tic_adv.attach(stop_adv_Callback, 2); /* trigger turn off advertisement after X seconds */