reduced message bytes for BLE
Dependencies: BLE_API mbed nRF51822
Fork of Inp_Fiber_Logo_FOTA by
main.cpp
- Committer:
- jojisdogakane
- Date:
- 2017-05-16
- Revision:
- 4:a0150e0f285b
- Parent:
- 3:ab649240543c
- Child:
- 5:b3fe9050a777
File content as of revision 4:a0150e0f285b:
#include "mbed.h" #include "neopixel.h" #include "nrf_soc.h" #include "common.h" #include "ble/BLE.h" #include "ble/services/HeartRateService.h" #include "ble/services/BatteryService.h" #include "ble/services/DeviceInformationService.h" #include "UARTService.h" #include "ble_gap.h" #include "ble/services/DFUService.h" // ★OTA用 #define RAINBOW_RATIO 1 #define RCFILTER 0.9 #define RCFILTER2 0.9 #define NEOPIXEL_COUNT 6 #define MIN_LIGHT 0 #define PNNX_FACTOR 0.1 // 0.06 #define MAXARRAY 15 //15 // 心拍平均値計算用の配列サイズ //20 #define MAXHRVARRAY 10 //30 // 脈間ゆらぎ平均値計算用の配列サイズ #define MIN_INTERVAL 200 #define INTERVAL 10 // Loopの間隔 通常時推奨1 通信時推奨20 #define MAXCOLORARRAY 1 //(MIN_INTERVAL / INTERVAL) // 色平均値計算用の配列サイズ (MIN_INTERVAL / 7) #define MAXCONARRAY 10 #define MAXSTRESSARRAY 3 #define DIM_LED 0.2 //0.2 //#define DIM_LED 1.0 // 心拍数の最低値、最高値 // 人間の場合は60~150、標準80 // 犬の場合は40~200、標準60 #define HR_MIN 40 #define HR_MAX 150 #define RELAX_RATIO_MIN 0.6 // ラジアンを度に変換する. #define RadianToDegree(radian) ((180 / 3.14159) * (radian)) // 度をラジアンに変換する. #define DegreeToRadian(degree) ((3.14159 / 180) * (degree)) // 色の識別値設定(ピンではない) #define RED 0 #define BLUE 1 #define GREEN 2 #define SHOW_EXCITE 1 #define SHOW_HAPPY 2 #define SHOW_CONCENTRATION 4 int displayFlag = 0; BLE ble; DFUService *dfuService; // ★OTA用 AnalogIn HRSigIn(P0_4); //const static char DEVICE_NAME[] = "InupLogo"; static char DEVICE_NAME[16] = "IND"; static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE, GattService::UUID_DEVICE_INFORMATION_SERVICE}; static volatile bool triggerSensorPolling = true; short ColorArrayR[NEOPIXEL_COUNT]; short ColorArrayG[NEOPIXEL_COUNT]; short ColorArrayB[NEOPIXEL_COUNT]; short TargetColorArrayR[NEOPIXEL_COUNT]; short TargetColorArrayG[NEOPIXEL_COUNT]; short TargetColorArrayB[NEOPIXEL_COUNT]; #define NEOPIXEL_COMMANDLEN ((NEOPIXEL_COUNT * 3) + 1 + 1) unsigned long pixelStartCounter; int mainCurrentPixel = 0; int mainPrevPixel = 0; int mainPixelLightCount; int mainPixelStep = 0; int mainStepsRemain = 0; unsigned long currentmillis = 0; unsigned long prevmillis = 0; unsigned long intervalmillis = 0; unsigned long prevIntervalmillis = 0; unsigned long intervalmillisArray[MAXARRAY] = {1000}; unsigned long intervalmillisHRVArray[MAXHRVARRAY] = {1000}; float conArray[MAXCONARRAY] = {0.5}; //float stressArray[MAXSTRESSARRAY] = {0.5}; float prevFilteredAngle = 0.5; float happyRatio = 0.0; float happyRatioNow = 0.0; float prevRelaxRatio = 1.0; float prevFilteredDistRatio = 0.0; #define HR_THRESHOLD 2 int HRThreshold[] = {120, 1000}; // 気分判定フラグ #define IS_RELAX 0 #define IS_EXCITED 1 #define IS_HAPPY 2 #define IS_INTERESTED 3 #define IS_STRESSED 4 // IS_STRESSEDはMOODの個数としても扱うので最後の番号にすること #define MOOD_COUNT IS_STRESSED + 1 // 気分判定係数 #define CONMARGIN 0.85 #define RELAXMARGIN 0.2 #define HAPPYMARGIN 0.225 // 気分判定フラグを索引にする int MoodColorR[NEOPIXEL_COUNT][MOOD_COUNT]; int MoodColorG[NEOPIXEL_COUNT][MOOD_COUNT]; int MoodColorB[NEOPIXEL_COUNT][MOOD_COUNT]; unsigned char RainbowR[] = { 50, 50, 50, 127, 200, 255}; unsigned char RainbowG[] = { 50, 127, 255, 127, 100, 50}; unsigned char RainbowB[] = {255, 127, 50, 50, 50, 50}; /* unsigned char HappyR[] = {255, 100, 100, 255, 100, 100}; unsigned char HappyG[] = {100, 255, 100, 100, 255, 100}; unsigned char HappyB[] = {100, 100, 255, 100, 100, 255}; */ unsigned char HappyR[] = {255, 200, 100, 255, 200, 100}; unsigned char HappyG[] = {100, 255, 200, 100, 255, 200}; unsigned char HappyB[] = {100, 100, 255, 100, 100, 255}; unsigned char RelaxR[] = { 0, 100, 255, 0, 100, 255}; unsigned char RelaxG[] = {255, 255, 255, 255, 255, 255}; unsigned char RelaxB[] = { 0, 100, 255, 0, 100, 255}; unsigned char ExciteR[] = {255, 255, 255, 255, 255, 255}; unsigned char ExciteG[] = {100, 100, 100, 100, 100, 100}; unsigned char ExciteB[] = { 75, 50, 25, 25, 50, 75}; /* unsigned char StressR[] = {255, 255, 255, 255, 100, 100}; unsigned char StressG[] = { 0, 0, 0, 0, 0, 0}; unsigned char StressB[] = { 0, 0, 100, 100, 255, 255}; */ unsigned char StressR[] = {100, 100, 255, 255, 100, 100}; unsigned char StressG[] = { 0, 0, 0, 0, 0, 0}; unsigned char StressB[] = {255, 255, 100, 100, 255, 255}; unsigned char InterestR[] = {255, 255, 255, 255, 255, 255}; unsigned char InterestG[] = {255, 255, 255, 255, 255, 255}; unsigned char InterestB[] = {255, 100, 0, 0, 100, 255}; float rainbowOffset = 0.0; bool bConcentration; unsigned long loopCounter = 0; int lightPos = 1; int prevLightPos = 1; double relaxRatio = 0.0; float conRatio = 0.5; float conRatioNow = 0.5; double HR_ratio = 0.0; unsigned long IBI; int x3, y3; int mainPixelCounter; int prevInterval; int prevprevInterval; void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.gap().startAdvertising(); // restart advertising } /* void ConnectTimeoutCallback(Gap::EventCallback_t timeoutCallback) { ble.gap().startAdvertising(); // restart advertising } */ uint8_t BPM = 0; float sensorValue = 0; Timer t; Timer tRand; float redVal = 0; float blueVal = 255; float greenVal = 0; Ticker neopixelTick; UARTService *uartServicePtr; void neopixelTick_Handler() { return; } void SetMoodColor() { int i = 0; for(i = 0; i < NEOPIXEL_COUNT; i++) { MoodColorR[i][IS_RELAX] = RelaxR[i]; MoodColorG[i][IS_RELAX] = RelaxG[i]; MoodColorB[i][IS_RELAX] = RelaxB[i]; } for(i = 0; i < NEOPIXEL_COUNT; i++) { MoodColorR[i][IS_EXCITED] = ExciteR[i]; MoodColorG[i][IS_EXCITED] = ExciteG[i]; MoodColorB[i][IS_EXCITED] = ExciteB[i]; } for(i = 0; i < NEOPIXEL_COUNT; i++) { MoodColorR[i][IS_HAPPY] = HappyR[i]; MoodColorG[i][IS_HAPPY] = HappyG[i]; MoodColorB[i][IS_HAPPY] = HappyB[i]; } for(i = 0; i < NEOPIXEL_COUNT; i++) { MoodColorR[i][IS_INTERESTED] = InterestR[i]; MoodColorG[i][IS_INTERESTED] = InterestG[i]; MoodColorB[i][IS_INTERESTED] = InterestB[i]; } for(i = 0; i < NEOPIXEL_COUNT; i++) { MoodColorR[i][IS_STRESSED] = StressR[i]; MoodColorG[i][IS_STRESSED] = StressG[i]; MoodColorB[i][IS_STRESSED] = StressB[i]; } } // 現在の気分の判定 int getMood(int bpm, double relaxRatio, double happyRatio, double conRatio) { // 第一優先:集中 // 集中係数が0.95以上なら集中と判定 if(conRatio >= CONMARGIN) { return IS_INTERESTED; } // 第二優先:Stress // リラックス係数が0.2以下 if(relaxRatio <= RELAXMARGIN) { return IS_STRESSED; } // 第三優先:Happy // Happy係数が0.2以上 if(happyRatio >= HAPPYMARGIN && relaxRatio > 0.5) { return IS_HAPPY; } // それ以外は興奮度合い // 心拍数の閾値判定 int i = 0; for(i = 0; i < HR_THRESHOLD; i++) { if (BPM <= HRThreshold[i]) { break; } } switch(i) { // 第1領域:NORMAL case 0: return IS_RELAX; // 第2領域:EXCITED1 case 1: return IS_EXCITED; } return IS_RELAX; } //Serial mySerial(USBTX, USBRX); //Serial mySerial(P0_9, P0_11); // MACアドレスを取得してBLEのデバイス名に組み込む void setBleDeviceName(char *deviceName) { int i; //BLEProtocol::AddressType_t type; //< The type of the BLE address. //BLEProtocol::AddressBytes_t mac_address; //< The BLE address. // typedef uint8_t AddressBytes_t[ADDR_LEN] ble_gap_addr_t mac_address; if(sd_ble_gap_address_get(&mac_address) != NRF_SUCCESS){ return; } // ADDR_LENは6 for(i=BLE_GAP_ADDR_LEN-1; i>=0; i--){ sprintf(deviceName, "%s%02x", deviceName, (mac_address.addr)[i]); } sprintf(deviceName, "%s%s", deviceName, "\0"); /* if(ble.getAddress(&type, mac_address) == BLE_ERROR_NONE){ // ADDR_LENは6 for(i=BLEProtocol::ADDR_LEN-1; i>=0; i--){ sprintf(deviceName, "%s%02x", deviceName, mac_address[i]); } sprintf(deviceName, "%s%s", deviceName, "\0"); } */ } int main(void) { char msgIBI[100]; int nMsgIBILen = 0; char msgHappy[10]; int nMsgHappyLen = 0; char msgConcentration[10]; int nMsgConcentrationLen = 0; char msgRelax[10]; int nMsgRelaxLen = 0; char msg[256]; int nMsgLen = 0; float Brightness = 1.0; bool brighten = true; float brightenSpeedMs = 1000.0; float colorSpeedMs = 1000.0; float conRatioShow = 0.5; int i; unsigned long lightPrevMillis = 0; int currentBPM; float fBeatIndex = 0.0; // displayFlag = SHOW_EXCITE; displayFlag = SHOW_EXCITE | SHOW_HAPPY | SHOW_CONCENTRATION; //displayFlag = SHOW_HAPPY ; // mySerial.baud(9600); // mySerial.format(8, Serial::None, 1); // PwrPin = 1; static uint8_t rrIntervalH = 0; static uint8_t rrIntervalL = 1; // static uint8_t bpm[8] = {0x10, hrmCounter, 0, 0, 0, 0, rrIntervalH, rrIntervalL}; neopixel_strip_t neopixel1; neopixel_init(&neopixel1, P0_7, 1); neopixel_clear(&neopixel1); neopixel_strip_t neopixel2; neopixel_init(&neopixel2, P0_8, 1); neopixel_clear(&neopixel2); neopixel_strip_t neopixel3; neopixel_init(&neopixel3, P0_10, 1); neopixel_clear(&neopixel3); neopixel_strip_t neopixel4; neopixel_init(&neopixel4, P0_9, 1); neopixel_clear(&neopixel4); neopixel_strip_t neopixel5; neopixel_init(&neopixel5, P0_15, 1); neopixel_clear(&neopixel5); neopixel_strip_t neopixel6; neopixel_init(&neopixel6, P0_11, 1); neopixel_clear(&neopixel6); neopixel_strip_t *pixels[6]; pixels[0] = &neopixel1; pixels[1] = &neopixel2; pixels[2] = &neopixel3; pixels[3] = &neopixel4; pixels[4] = &neopixel5; pixels[5] = &neopixel6; int pixelIndex = 0; SetMoodColor(); // my_analogin_init(); ble.init(); ble.gap().onDisconnection(disconnectionCallback); // ble.gap().onTimeout(ConnectTimeoutCallback); UARTService uartService(ble); uartServicePtr = &uartService; // ★OTA用 dfuService = new DFUService(ble, NULL); /* Setup primary service. */ HeartRateService hrServiceBPM(ble, BPM, HeartRateService::LOCATION_CHEST); // HeartRateService hrServiceIBI(ble, IBI, HeartRateService::LOCATION_FINGER); // BatteryService batteryService(ble, 100); /* Setup auxiliary service. */ //DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); // ★ DeviceInformationService deviceInfo(ble, "INUPATHY01", "0.0.1", "SN1", "0.0.1", "0.0.1", "0.0.1"); // MACアドレスをDEVICE_NAMEに組み込む setBleDeviceName(DEVICE_NAME); /* Setup advertising. */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(800); /* 1000ms */ ble.gap().startAdvertising(); for( i = 0; i < NEOPIXEL_COUNT; i++) { // ColorArrayR[i] = RainbowR[i]; // ColorArrayG[i] = RainbowG[i]; // ColorArrayB[i] = RainbowB[i]; ColorArrayR[i] = StressR[i]; ColorArrayG[i] = StressG[i]; ColorArrayB[i] = StressB[i]; TargetColorArrayR[i] = ColorArrayR[i]; TargetColorArrayG[i] = ColorArrayG[i]; TargetColorArrayB[i] = ColorArrayB[i]; neopixel_set_color( pixels[i], 0, short(float(ColorArrayR[i] * DIM_LED)), short(float(ColorArrayG[i] * DIM_LED)), short(float(ColorArrayB[i] * DIM_LED))); neopixel_show(pixels[i]); } t.start(); prevmillis = t.read_ms(); bool bPulseEvent = false; float degPoint = 0; float degRatio = 0; bool bSwingR = false; float swingIndex = 0.0; float midPoint = 0.5; // neopixelTick.attach(neopixelTick_Handler, 0.005); while (1) { // batteryService.updateBatteryLevel( (uint8_t)read_battery_level()); float currentValue = HRSigIn; bPulseEvent = false; if ((currentValue <= 0.3) && (sensorValue > 0.3)) { bPulseEvent = true; } int sens = 1023 * currentValue; // printf("S%d", sens); // printf("S%d\n", sens); sensorValue = currentValue; if(bPulseEvent) { fBeatIndex = 0.0; // batteryService.updateBatteryLevel( (uint8_t)read_battery_level()); // 現在の時刻を取得 // t.stop(); // stop, startは時間計測の結果を有意に短くしてしまうので使わない currentmillis = t.read_ms(); // t.start(); // 現在時刻から過去時刻を引き、間隔を求める intervalmillis = currentmillis - prevmillis; // 心拍の間の間隔 IBI = intervalmillis; // 現在の時刻を過去時刻として記録 prevmillis = currentmillis; // 平均値算出用配列に値を詰める double averageIntervalMillis; for(i = 0; i < MAXARRAY ; i++) { // 最後尾以外の場合 if(i != MAXARRAY - 1) { // 次の要素の値をコピーする intervalmillisArray[i] = intervalmillisArray[i + 1]; } // 最後尾の場合 else { // 最新値を詰める intervalmillisArray[i] = intervalmillis; } } // 先頭が0の間は何もしない unsigned long sumIntervalMillis = 0; unsigned long sumIntervalMillisV = 0; if (intervalmillisArray[0] != 0) { // 平均値算出 averageIntervalMillis = 0; for(i = 0; i < MAXARRAY ; i++) { sumIntervalMillis += intervalmillisArray[i]; sumIntervalMillisV += intervalmillisArray[i] * intervalmillisArray[i]; } double squ; double var; double stdDev; averageIntervalMillis = (double)sumIntervalMillis / (double)MAXARRAY; squ = sumIntervalMillisV - (double)(sumIntervalMillis * sumIntervalMillis) / (double)MAXARRAY; var = squ / (double)(MAXARRAY - 1); stdDev = sqrt(var); BPM = min32_of(60000 / averageIntervalMillis, 255); // if(intervalmillis < averageIntervalMillis - stdDev) { // || intervalmillis > averageIntervalMillis + stdDev) { currentBPM = min32_of(60000 / intervalmillis, 255); /* } else { currentBPM = BPM; } */ } /* int IBI1024 = IBI * (1024/1000); bpm[1] = BPM; bpm[6] = (IBI1024 & 0xFF00) >> 8; bpm[7] = (IBI1024 & 0xFF); */ // update bpm if(ble.gap().getState().connected == 1) { hrServiceBPM.updateHeartRate(BPM); // hrServiceIBI.updateHeartRate(IBI); } // printf("B%d\n", BPM); // printf("Q%d\n", IBI); // nMsgLen = sprintf(msg,"B%d\0", BPM); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen); nMsgIBILen = sprintf(msgIBI,"Q%d\0", IBI); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen); // 平均値算出用配列に値を詰める for(i = 0; i < MAXHRVARRAY ; i++) { // 最後尾以外の場合 if(i != MAXHRVARRAY - 1) { // 次の要素の値をコピーする intervalmillisHRVArray[i] = intervalmillisHRVArray[i + 1]; } // 最後尾の場合 else { // 最新値を詰める intervalmillisHRVArray[i] = intervalmillis; } } // 平均値算出 int nNNInterval; unsigned long ulIntervalSum = 0; int nSampleCount = 0; for(i = 0; i < MAXHRVARRAY ; i++) { if(intervalmillisHRVArray[i] > 0) { ulIntervalSum += intervalmillisHRVArray[i]; nSampleCount++; } } float IntervalAverage = 0.0; if(nSampleCount > 0){ IntervalAverage = (float)ulIntervalSum / (float)nSampleCount; } nNNInterval = (int)((float)IntervalAverage * PNNX_FACTOR); bool bContinue = false; int nNNxCount = 0; for(i = 0; i < MAXHRVARRAY ; i++) { // if not end if(i < MAXHRVARRAY - 1) { if(abs((int)(intervalmillisHRVArray[i] - intervalmillisHRVArray[i + 1])) >= nNNInterval) { if(bContinue == false) { nNNxCount++; } nNNxCount++; bContinue = true; } else { bContinue = false; } } } float diffRatio = (float)nNNxCount / (float)nSampleCount; if(diffRatio > 1) { diffRatio = 1; } // リラックスの係数を算出する relaxRatio = diffRatio; nMsgRelaxLen = sprintf(msgRelax,"R%0.2f\0", relaxRatio); // nMsgLen = sprintf(msg,"R%0.2f\0", relaxRatio); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen); // 現在値から最低値を引く // relaxRatio = relaxRatio - RELAX_RATIO_MIN; // 1.0 / 最低値 × 現在値 // relaxRatio = relaxRatio * (1.0 / (1.0 - RELAX_RATIO_MIN)); int x1, y1, x2, y2; int tempx1, tempy1, tempx2, tempy2, tempx3, tempy3; int longx, shortx, longy, shorty; long xx1, xx2, yy1, yy2; int movex, movey; double dist1, dist2; double conRatioRatio; /* // 最後尾の3データから二つのx, y地点を作る。 x1 = intervalmillisArray[nSampleCount - 1]; y1 = intervalmillisArray[nSampleCount - 2]; x2 = intervalmillisArray[nSampleCount - 2]; y2 = intervalmillisArray[nSampleCount - 3]; */ x1 = intervalmillis; y1 = prevInterval; x2 = prevInterval; y2 = prevprevInterval; // 2地点を結ぶ直線の長さを算出する。 if(x1 > x2) { longx = x1; shortx = x2; } else { longx = x2; shortx = x1; } if(y1 > y2) { longy = y1; shorty = y2; } else { longy = y2; shorty = y1; } xx1 = longx - shortx; yy1 = longy - shorty; dist1 = sqrt((double)((xx1 * xx1) + (yy1 * yy1))); dist2 = longx + longy; float distRatio = dist1 / dist2; conRatioNow = 1 - distRatio; // 平均値算出用配列に値を詰める float averageConRatio = 0.5; for(i = 0; i < MAXCONARRAY ; i++) { // 最後尾以外の場合 if(i != MAXCONARRAY - 1) { // 次の要素の値をコピーする conArray[i] = conArray[i + 1]; } // 最後尾の場合 else { // 最新値を詰める conArray[i] = distRatio; } } // 先頭が0の間は何もしない if (conArray[0] != 0) { // 平均値算出 averageConRatio = 0; for(i = 0; i < MAXCONARRAY ; i++) { averageConRatio += conArray[i]; } averageConRatio = averageConRatio / (double)MAXCONARRAY; } /* float averageStressRatio = 0.5; for(i = 0; i < MAXSTRESSARRAY ; i++) { // 最後尾以外の場合 if(i != MAXSTRESSARRAY - 1) { // 次の要素の値をコピーする stressArray[i] = stressArray[i + 1]; } // 最後尾の場合 else { // 最新値を詰める if(x1 > y1) { stressArray[i] = y1 / x1; } else { stressArray[i] = x1 / y1; } } } // 先頭が0の間は何もしない if (stressArray[0] != 0) { // 平均値算出 averageStressRatio = 0; for(i = 0; i < MAXSTRESSARRAY ; i++) { averageStressRatio += stressArray[i]; } averageStressRatio = averageStressRatio / (double)MAXSTRESSARRAY; } */ /* float rcFilter = RCFILTER2; float filteredDistRatio = 0.0; float a; if(prevFilteredDistRatio != 0) { a = rcFilter * prevFilteredDistRatio; filteredDistRatio = a + (1 - rcFilter) * distRatio; } else { filteredDistRatio = (1 - rcFilter) * distRatio; } prevFilteredDistRatio = filteredDistRatio ; conRatio = filteredDistRatio ; */ conRatio = averageConRatio; conRatio = 1 - conRatio; nMsgConcentrationLen = sprintf(msgConcentration,"C%0.2f\0", conRatio); // nMsgLen = sprintf(msg,"C%0.2f\0", conRatio); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen); prevprevInterval = prevInterval; prevInterval = intervalmillis; // (x2, y2)が原点となるように座標を変換する movex = x2 * -1; movey = y2 * -1; tempx1 = x1 - movex; tempy1 = y1 - movey; tempx2 = x2 - movex; tempy2 = y2 - movey; tempx3 = x3 - movex; tempy3 = y3 - movey; // (x2, y2)を中心とした円を考える。 // (x3, y3)を(x2, y2)を中心に180°回転する。→(rotx3, roty3) double theta = DegreeToRadian(180); double rotx3 = (tempx3) * cos(theta) - (tempy3) * sin(theta); double roty3 = (tempx3) * sin(theta) + (tempy3) * cos(theta); // ベクトル1とベクトル3の内積を求める double vecInt = tempx1 * rotx3 + tempy1 * roty3; // ベクトル1とベクトル3の外積を求める double vecExt = tempx1 * roty3 - tempy1 * rotx3; // ベクトル1とベクトル3の角度を求める theta = atan2(vecExt, vecInt); double deg = RadianToDegree(theta); midPoint = degRatio; if( deg <= 11.25 && deg >= -11.25) { degPoint = 0.5; } else if(deg >= 11.25 && deg <= 33.75) { degPoint = 0.375; } else if(deg >= 33.75 && deg <= 56.25) { degPoint = 0.25; } else if(deg >= 56.25 && deg <= 78.75) { degPoint = 0.125; } else if(deg >= 78.75 && deg <= 101.25) { degPoint = 0; } else if(deg >= 101.25 && deg <= 123.75) { degPoint = 0.125; } else if(deg >= 123.75 && deg <= 146.25) { degPoint = 0.25; } else if(deg >= 146.25 && deg <= 168.75) { degPoint = 0.375; } else if(deg >= 168.75 && deg <= 180 || deg <= 0 && deg >= -11.25) { degPoint = 0.5; } else if(deg <= -11.25 && deg >= -33.75) { degPoint = 0.625; } else if(deg <= -33.75 && deg >= -56.25) { degPoint = 0.75; } else if(deg <= -56.25 && deg >= -78.75) { degPoint = 0.875; } else if(deg <= -78.75 && deg >= -101.25) { degPoint = 1; } else if(deg <= -101.25 && deg >= -123.75) { degPoint = 0.875; } else if(deg <= -123.75 && deg >= -146.25) { degPoint = 0.75; } else if(deg <= -146.25 && deg >= -168.75) { degPoint = 0.625; } else { degPoint = 0; } happyRatioNow = degPoint; degRatio = (deg + 180.0) / 360.0; float rcFilter = RCFILTER; float filteredAngle = rcFilter * prevFilteredAngle + (1 - rcFilter) * degPoint; prevFilteredAngle = filteredAngle ; happyRatio = filteredAngle - 0.5; if(happyRatio <= 0){ happyRatio = abs(happyRatio); } else { happyRatio = 0; } // happyRatio = averageStressRatio ;// @@@ nMsgHappyLen = sprintf(msgHappy,"H%0.2f\0", happyRatio); // nMsgLen = sprintf(msg,"H%0.2f\0", happyRatio); // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen); // happyRatio = happyRatio * happyRatio * happyRatio; // happyRatio *= 10; x3 = x2; y3 = y2; int HR_range = 0; int HR_tempval = currentBPM; // 心拍の係数を算出する // 最大心拍数以上→最大心拍数に if( HR_MAX < HR_tempval) { HR_tempval = HR_MAX; } // 最少心拍数以下→最少心拍数に if( HR_MIN > HR_tempval) { HR_tempval = HR_MIN; } // 心拍の幅を計算 HR_range = HR_MAX - HR_MIN; // 現在値-最少心拍数 HR_tempval = HR_tempval - HR_MIN; // 心拍の係数を算出。0 ~ 1.0 HR_ratio = (double)HR_tempval / (double)HR_range; if(conRatioNow >= 0.95 /* && averageAngle >= 0.7*/) { bConcentration = true; } else { bConcentration = false; } prevRelaxRatio = relaxRatio; int hval = 1023 * happyRatio; int rval = 1023 * relaxRatio; int cval = 1023 * conRatio; // printf("H%d\n", hval); // printf("R%d\n", rval); // printf("C%d\n", cval); sprintf(msg,"%s%s%s%s\0", msgIBI, msgHappy, msgRelax, msgConcentration); ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgIBILen + nMsgHappyLen + nMsgRelaxLen + nMsgConcentrationLen); // (uint8_t*)msg, nMsgIBILen + 1 + nMsgHappyLen + 1 + nMsgRelaxLen + 1 + nMsgConcentrationLen); // determine color range conRatio = conRatio - 0.5; if(conRatio < 0) { conRatio = 0; } conRatio = conRatio * 2; // happyRatio = happyRatio * 2; // happyRatio = happyRatio * 2; if(happyRatio > 1) { happyRatio = 1; } /* if(BPM >= HR_MIN) { happyRatio /= ((float)(BPM * 2) / 255.0) ; } */ } if(BPM > 0 && bPulseEvent) { int NewMood = getMood(BPM, relaxRatio, happyRatio, conRatio) ; for(i = 0 ; i < NEOPIXEL_COUNT; i++) { TargetColorArrayR[i] = MoodColorR[i][NewMood]; TargetColorArrayG[i] = MoodColorG[i][NewMood]; TargetColorArrayB[i] = MoodColorB[i][NewMood]; } } // for(i = NEOPIXEL_COUNT - 1; i >= 0; i--) { if(ColorArrayR[pixelIndex] < TargetColorArrayR[pixelIndex]) { ColorArrayR[pixelIndex]++; } else if(ColorArrayR[pixelIndex] > TargetColorArrayR[pixelIndex]) { ColorArrayR[pixelIndex]--; } /* if(ColorArrayR[pixelIndex] < 200) { ColorArrayR[pixelIndex]++; } else if(ColorArrayR[pixelIndex] > 200) { ColorArrayR[pixelIndex]--; }*/ if(ColorArrayG[pixelIndex] < TargetColorArrayG[pixelIndex]) { ColorArrayG[pixelIndex]++; } else if(ColorArrayG[pixelIndex] > TargetColorArrayG[pixelIndex]) { ColorArrayG[pixelIndex]--; } if(ColorArrayB[pixelIndex] < TargetColorArrayB[pixelIndex]) { ColorArrayB[pixelIndex]++; } else if(ColorArrayB[pixelIndex] > TargetColorArrayB[pixelIndex]) { ColorArrayB[pixelIndex]--; } neopixel_set_color( pixels[pixelIndex], 0, short(float(ColorArrayR[pixelIndex]) * DIM_LED), short(float(ColorArrayG[pixelIndex]) * DIM_LED), short(float(ColorArrayB[pixelIndex]) * DIM_LED)); neopixel_show(pixels[pixelIndex]); // } pixelIndex++; if(pixelIndex >= NEOPIXEL_COUNT) { pixelIndex = 0; } //wait_ms(1); wait_us(500); } }