test
Dependencies: BLE_API nRF51822 mbed
Fork of KS7 by
main.cpp
- Committer:
- masaaki_makabe
- Date:
- 2016-08-10
- Branch:
- KS3
- Revision:
- 34:55b9048a1055
- Parent:
- 31:b5e19d153db4
File content as of revision 34:55b9048a1055:
#include "mbed.h" #include "exio.h" #include "BLE.h" #include "DFUService.h" #include "common.h" #include <stdlib.h> #include <arm_math.h> #include "CurrentTimeService.h" #include "MMA845x.h" #include "common.h" // BLE #define INTERVAL_500MSEC (500UL) #define CONNTIMEOUT_3000MSEC (3000UL) #define ADV_TIMEOUT (0) #define DEVICE_NAME "Kitchen Scale" #define BLE_TXPOWER_4DBM (4) // Device Information Service (DIS) (20 character limit) // https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml #define MANUFACTURER_NAME_STRING "Hacarus" // Manufacturer Name String - shall represent the name of the manufacturer of the device. #define MODEL_NUMBER_STRING "0001" // Model Number String - shall represent the model number that is assigned by the device vendor. #define SERIAL_NUMBER_STRING "000780c0ffeef00d" // Serial Number String - shall represent the serial number for a particular instance of the device. #define FIRMWARE_REVISION_STRING "v1.00.009@rev0028" // Firmware Revision String - shall represent the firmware revision for the firmware within the device. // Weight Scale Service (Original) //#define UUID_WEIGHT_SCALE_SERVICE (0x181D) #if defined(PCB_VER1) || defined(PCB_VER2) // Switch #define SW_THRESHOLD (0.5) #define SW_SAMPLECOUNT (3) #endif // Mode #define MODE_OFF (0) // LED OFF #define MODE_START (1) // LED OFF -> ON #define MODE_ON (2) // LED ON #define MODE_END (3) // LED ON -> OFF /*S-----------------------------------------------------------*/ State_t _state = S_WATCH; Mode_t _mode = M_SCALE; /*E-----------------------------------------------------------*/ // Led #define LED_INTERVAL_MSEC (100) #define BRIGHTNESS_ADDVALUE (0.1) #define BRIGHTNESS_MINVALUE (0.0) #define BRIGHTNESS_MAXVALUE (1.0) // Properties //io io; /*S---------------------------------------------------------------*/ //io io(P0_15, P0_13); // HX711's CLK & DAT exio io; /*E---------------------------------------------------------------*/ //io(P0_5, P0_4); // HX711's CLK & DAT for BLEnano debug uint32_t weight_data; float32_t weight = 0.0; uint32_t scale = 0; int update_counter = 0; #if defined(PCB_VER1) || defined(PCB_VER2) float sw_data[SW_SAMPLECOUNT]; uint8_t sw_count = 0; #endif int led_mode = MODE_OFF; float led_brightness = BRIGHTNESS_MINVALUE; #ifdef UART_DEBUG #if defined(PCB_VER1) || defined(PCB_VER2) Serial pc(P0_9, P0_8);// TX=P0_9 #else Serial pc(P0_9, P0_11);// TX=P0_9 #endif #define UART_BAUD_RATE (9600UL) #define DEBUG(...) { pc.printf(__VA_ARGS__); } #else #define DEBUG(...) {} #endif Timer t; // BLE BLE ble; Gap::ConnectionParams_t connectionParams; /* Complete list of 16-bit Service IDs */ uint16_t uuid16_list[] = {GattService::UUID_DEVICE_INFORMATION_SERVICE}; /* Weight Scale Service */ static const uint8_t UUID_HACARUS_WEIGHT_CHAR[] = {0x00, 0x00, 0x2A, 0x9D, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'}; GattCharacteristic WeightMeasurement (UUID(UUID_HACARUS_WEIGHT_CHAR), (uint8_t *)&weight_data, sizeof(weight_data), sizeof(weight_data), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); static const uint8_t UUID_HACARUS_SCALE_CHAR[] = {0x00, 0x00, 0x2A, 0x9E, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'}; GattCharacteristic WeightScale (UUID(UUID_HACARUS_SCALE_CHAR), (uint8_t *)&scale, sizeof(scale), sizeof(scale), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); GattCharacteristic *Chars[] = {&WeightMeasurement,&WeightScale}; static const uint8_t UUID_HACARUS_WEIGHT_SERVICE[] = {0x00, 0x00, 0x18, 0x1D, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'}; GattService HWS = GattService(UUID(UUID_HACARUS_WEIGHT_SERVICE), Chars, sizeof(Chars) / sizeof(GattCharacteristic *)); /* Device Information Service */ GattCharacteristic ManuName(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR, (uint8_t *)&MANUFACTURER_NAME_STRING, sizeof(MANUFACTURER_NAME_STRING) - 1, sizeof(MANUFACTURER_NAME_STRING) - 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic ModelNum(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR, (uint8_t *)&MODEL_NUMBER_STRING, sizeof(MODEL_NUMBER_STRING) - 1, sizeof(MODEL_NUMBER_STRING) - 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic SerialNum(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR, (uint8_t *)&SERIAL_NUMBER_STRING, sizeof(SERIAL_NUMBER_STRING) - 1, sizeof(SERIAL_NUMBER_STRING) - 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic FWVersion(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)&FIRMWARE_REVISION_STRING, sizeof(FIRMWARE_REVISION_STRING) - 1, sizeof(FIRMWARE_REVISION_STRING) - 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic *DISChars[] = {&ManuName, &ModelNum, &SerialNum, &FWVersion}; GattService DIS(GattService::UUID_DEVICE_INFORMATION_SERVICE , DISChars, sizeof(DISChars) / sizeof(GattCharacteristic *)); /*S--------------------------------------------------------------------*/ CurrentTimeService *p_CurrentTimeService; // Current Time Service MMA845x *p_MMA845x; // 加速度センサー(本体) I2C i2c(P0_17, P0_18); // 加速度センサー(I2C) /*E--------------------------------------------------------------------*/ #ifdef PCB_VER1 bool check_joystick() { float sum_data = 0; sw_data[sw_count] = io.get_x(); if(++sw_count >= SW_SAMPLECOUNT) { sw_count = 0; } for(int count = 0; count < SW_SAMPLECOUNT; count++) { sum_data += sw_data[count]; } return ((sum_data / SW_SAMPLECOUNT) >= SW_THRESHOLD); } #endif uint32_t quick_ieee11073_from_float(float data) { uint8_t exponent = 0xFE; //exponent is -2 uint32_t mantissa = (uint32_t)(data*100); return ( ((uint32_t)exponent) << 24) | mantissa; } #if defined(PCB_VER1) || defined(PCB_VER2) void SWInit(void) { // SW Initialize for(int count = 0; count < SW_SAMPLECOUNT; count++) { sw_data[count] = 0; } } #endif void AppInit(void) { #if defined(PCB_VER1) || defined(PCB_VER2) SWInit(); #endif io.analog_pow(1); #ifdef PCB_VER3 // check XTALFREQ for TaiyoYuden module in PCB_VER3 /* if(NRF_UICR->XTALFREQ == 0xFFFFFF00){ io.display_value = 3232; }else if(NRF_UICR->XTALFREQ == 0xFFFFFFFF){ io.display_value = 1616; } */ #endif } /* * BLE CallBacks */ void BLEConnectionCallback(const Gap::ConnectionCallbackParams_t *params) { ble.updateConnectionParams(params->handle, params->connectionParams); } void BLEDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { if(led_mode == MODE_ON) { ble.startAdvertising(); } } void BLERadioNotificationCallback(bool radio_active) { if (radio_active == false) { if(led_mode == MODE_ON) { } } } void BleInitialize(void) { uint8_t advertiseServiceID[16]; // Initialize ble.init(); // Event Set ble.onConnection(&BLEConnectionCallback); ble.onDisconnection(&BLEDisconnectionCallback); ble.onRadioNotification(&BLERadioNotificationCallback); ble.getPreferredConnectionParams(&connectionParams); connectionParams.maxConnectionInterval = INTERVAL_500MSEC; connectionParams.minConnectionInterval = INTERVAL_500MSEC; connectionParams.connectionSupervisionTimeout = CONNTIMEOUT_3000MSEC; connectionParams.slaveLatency = 2; ble.setPreferredConnectionParams(&connectionParams); ble.setTxPower(BLE_TXPOWER_4DBM); for(int i=0; i<16; i++) { advertiseServiceID[i] = UUID_HACARUS_WEIGHT_SERVICE[16 - 1 - i]; } ble.accumulateAdvertisingPayload((GapAdvertisingData::Flags)(GapAdvertisingData::LE_GENERAL_DISCOVERABLE | GapAdvertisingData::BREDR_NOT_SUPPORTED)); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME)); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)advertiseServiceID, sizeof(advertiseServiceID)); ble.setAdvertisingInterval(INTERVAL_500MSEC); ble.setAdvertisingTimeout(ADV_TIMEOUT); /* 0 is disable the advertising timeout. */ /*S-----------------------------------------------------------------------*/ /*CurrentTimeServiceの初期化とサービス追加*/ ble_date_time_t dt; // 1970/1/1 00:00:00 以降の初期値 dt.year = 2016; dt.month = 7; dt.day = 31; dt.hours = 23; dt.minutes = 45; dt.seconds = 0; p_CurrentTimeService = new CurrentTimeService(ble, dt); /*E-----------------------------------------------------------------------*/ ble.addService(HWS); ble.addService(DIS); //DFUService dfu(ble); // これがライトできない原因。ひとまずコメント } /*S---------------------------------------------------------------------*/ //void zTap(void) //{ //} void AccelInit(void) { /*加速度センサー初期化*/ p_MMA845x = new MMA845x(i2c, MMA845x::SA0_VSS); //p_MMA845x->attachZAxisPulse(&zTap); const int ADR = 0x3A; char data[2], cmd = 0x0D; i2c.write(ADR, &cmd, 1, true); i2c.read(ADR, &data[0], 1); // data[0]: Who am I? //p_MMA845x->enableMotionMode(); //p_MMA845x->registerDump(); p_MMA845x->enableDataReadyMode(); } /*モード決定*/ void GetMode(void) { // 横置きなら時計タイマーモード、縦置きなら計量モード //int x = p_MMA845x->getX(); //int y = p_MMA845x->getY(); //int z = p_MMA845x->getZ(); float xx = p_MMA845x->getXX(); _mode = (xx < 0.3) ? M_SCALE : M_WATCHTIMER; #ifdef UART_DEBUG pc.printf("KATAMUKI xx=%f, mode=%s\r\n", xx, (_mode == M_SCALE) ? "SCALE" : "WATCHTIMER"); #endif } /*STATE決定*/ void GetState(int sw) { ble_date_time_t dt; // スイッチ長押しでタイマー、通常押しで時間表示 if(sw == exio::LongPressed) { p_CurrentTimeService->setCounter(0); // タイマーカウンタリセット io.displaySeconds(0); _state = S_TIMER; #ifdef UART_DEBUG pc.printf("S_TIMER START\r\n"); #endif } else if(sw == exio::Pressed){ p_CurrentTimeService->setTm(60/*sec*/); /*表示タイムアウト*/ p_CurrentTimeService->readDateTime(dt); // 時計取得 io.displayHHMM(dt); _state = S_WATCH; #ifdef UART_DEBUG pc.printf("S_WATCH START\r\n"); #endif } } int TMain(int sw) { /*下記は時計/タイマーモード*/ ble_date_time_t dt; int t; switch(_state){ case S_TIMER: /*タイマー表示の場合*/ t = p_CurrentTimeService->getCounter(); io.displaySeconds(t); // タイマー表示 // スイッチ押された場合終了 if(sw != exio::None){ #ifdef UART_DEBUG pc.printf("S_TIMER EXIT\r\n"); #endif return 1; // モード終了 } break; case S_WATCH: /*時計表示の場合*/ p_CurrentTimeService->readDateTime(dt); // 時計取得 io.displayHHMM(dt); // 時計表示 // 表示タイムアウトもしくはスイッチ押しの場合終了 if(/*p_CurrentTimeService->getTm() <= 0 ||*/ sw != exio::None){ // タイムアウトorスイッチ押し #ifdef UART_DEBUG pc.printf("S_WATCH EXIT\r\n"); #endif return 1; // モード終了 } break; default: break; } return 0; // モード継続 } /*E-----------------------------------------------------------------------*/ //DigitalOut _reg_ps(P0_1, 1); // 1=normal, 0=power_save //DigitalOut _adc_rate(P0_6, 1); // 0=10Hz, 1=80Hz (HX711's RATE pin) int main() { /*S----------------------------------------------------*/ int sw; /*E----------------------------------------------------*/ float weight_s; int Navg = 5; int sample = 0; #ifdef UART_DEBUG pc.baud(UART_BAUD_RATE); pc.printf("%s(%d): Program Start\r\n", __FILE__, __LINE__); // for checking SPI configuration (SPI1 is used_) // pc.printf("SPI->PSELSCK = %x\r\n", NRF_SPI0->PSELSCK); // will be 15 (P0_15) // pc.printf("SPI->PSELMISO = %x\r\n", NRF_SPI0->PSELMISO); // will be 13 (P0_13) // pc.printf("SPI->PSELMOSI = %x\r\n", NRF_SPI0->PSELMOSI); // will be 14 (P0_14): dummy // pc.printf("SPI->PSELSCK = %x\r\n", NRF_SPI1->PSELSCK); // will be 15 (P0_15) // pc.printf("SPI->PSELMISO = %x\r\n", NRF_SPI1->PSELMISO); // will be 13 (P0_13) // pc.printf("SPI->PSELMOSI = %x\r\n", NRF_SPI1->PSELMOSI); // will be 14 (P0_14): dummy #endif #ifdef PCB_VER3 // set XTAL=32MHz for TaiyoYuden's module // is moved to mbed-src/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/system_nrf51.c DEBUG("UICR->XTALFREQ=%x\r\n", NRF_UICR->XTALFREQ); // this should be 0xffffff00, not 0xffffffff #endif BleInitialize(); /*S-----------------------------------------------*/ AccelInit(); /*E-----------------------------------------------*/ AppInit(); led_mode = MODE_OFF; #ifdef DISPLAY_DEMO uint16_t d = 0; uint8_t demo_count = 0; led_mode = MODE_START; // for debug mode #endif for (;; ) { // 100msec waitForEvent t.reset(); while(t.read_ms() < LED_INTERVAL_MSEC) { t.start(); ble.waitForEvent(); t.stop(); } switch(led_mode) { case MODE_OFF: io.analog_pow(0); io.display(0); /*S--------------------------------------------------------------------*/ sw = io.get_switch(); io.switch_reset(); if(sw != exio::None) {/*通常押しもしくは長押し*/ GetMode(); /*傾きからモード決定*/ if(_mode == M_WATCHTIMER){ GetState(sw); //WATCH or TIMER ? } #ifdef UART_DEBUG pc.printf("GO MODE_START\r\n"); #endif /*E--------------------------------------------------------------------*/ led_mode = MODE_START; } break; case MODE_START: io.analog_pow(1); io.power_save_mode(0); /*S----------------------------------------------------------------*/ // タイマー時はここで毎回更新 if(_mode == M_WATCHTIMER && _state == S_TIMER){ p_CurrentTimeService->setCounter(0); // タイマーカウンタリセット io.displaySeconds(0); } else if(_mode == M_SCALE){ io.display_value = 0; } /*E----------------------------------------------------------------*/ led_brightness += BRIGHTNESS_ADDVALUE; io.display(led_brightness); if(led_brightness >= BRIGHTNESS_MAXVALUE) { /*S-----------------------------------------------------------------------*/ if(_mode == M_WATCHTIMER){ ble.startAdvertising(); led_mode = MODE_ON; break; /*時間/タイマーモードはここで終了*/ } /*E-----------------------------------------------------------------------*/ /*計量モードの初期処理*/ update_counter = 0; io.calibrate_weight(); /*ここがゼロ補正*/ #if defined(PCB_VER1) || defined(PCB_VER2) SWInit(); #endif ble.startAdvertising(); led_mode = MODE_ON; weight_s = 0.0; sample = 0; } break; case MODE_ON: #ifdef UART_DEBUG //pc.printf("%d %d %.2f\r\n", io.get_switch(), io.get_weight_raw(), io.get_weight()); #endif io.analog_pow(1); #ifdef DISPLAY_DEMO demo_count++; if (demo_count == 10) { demo_count = 0; io.display_value = d++; // increment display value for every 1s in demo mode weight_data = quick_ieee11073_from_float(d); ble.updateCharacteristicValue(WeightMeasurement.getValueAttribute().getHandle(), (uint8_t *)&weight_data, sizeof(weight_data)); } #else /*S-------------------------------------------------------------------------*/ sw = io.get_switch(); io.switch_reset(); if(_mode == M_WATCHTIMER){ int ret = TMain(sw); // 時間/タイマー処理へ if(ret == 1){ // モード終了 goto L010; } break; // 時間/タイマーモードはここで終了 } /*下記は計量モード*/ if(sw == exio::Pressed) { L010: #ifdef UART_DEBUG pc.printf("GO MODE_END\r\n"); #endif /*E-------------------------------------------------------------------------*/ led_mode = MODE_END; if(ble.getGapState().connected) { ble.disconnect(Gap::REMOTE_USER_TERMINATED_CONNECTION); } else { ble.stopAdvertising(); } } else { scale++; ble.updateCharacteristicValue(WeightScale.getValueAttribute().getHandle(), (uint8_t *)&scale, sizeof(scale)); weight_s += io.get_weight(); sample++; if (sample == Navg) { weight = weight_s / (float)Navg; io.display_value = (uint16_t)weight; weight_s = 0.0; sample = 0; #ifdef UART_DEBUG pc.printf("weight=%.1f\r\n", weight); #endif } // pc.printf("weight=%.1f\r\n", weight); // io.display_value = 8888; // for LED soldering check #ifdef UART_DEBUG // pc.printf("%d\r\n", io._get_adc_raw(0)); // pc.printf("weight=%f %d / %d\r\n", weight, io.display_value, io._adc0); #endif if(++update_counter >= 5) { weight_data = quick_ieee11073_from_float(weight); ble.updateCharacteristicValue(WeightMeasurement.getValueAttribute().getHandle(), (uint8_t *)&weight_data, sizeof(weight_data)); update_counter = 0; } } #endif break; case MODE_END: led_brightness -= BRIGHTNESS_ADDVALUE; io.display(led_brightness); if(led_brightness <= BRIGHTNESS_MINVALUE) { #if defined(PCB_VER1) || defined(PCB_VER2) SWInit(); #endif led_mode = MODE_OFF; io.power_save_mode(1); } break; } } }