reduced message bytes for BLE

Dependencies:   BLE_API mbed nRF51822

Fork of Inp_Fiber_Logo_FOTA by inupathy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // 20170703 BRIGHTNESS_MAXを100に変更
00002 //          シリアル通信のプロトコルを、文字列→バイト列に変更
00003 // 20170619 DeviceInformationのSerialNumberにIND+Macアドレスを適用し、DEVICENAMEはINUPATHYとした
00004 // 20170617 ストレス値を"R"(relax)から"S"(stress)に変更し、(1.0 - relaxRatio)を送るよう改変
00005 // 20170617 輝度調整の方法をrgbの合計値を基準にするように調整した。
00006 
00007 #include "mbed.h"
00008 #include "neopixel.h"
00009 #include "nrf_soc.h"
00010 #include "common.h"
00011 #include "ble/BLE.h"
00012 #include "ble/services/HeartRateService.h"
00013 #include "ble/services/BatteryService.h"
00014 #include "ble/services/DeviceInformationService.h"
00015 #include "UARTService.h"
00016 #include "ble_gap.h"
00017 #include "ble/services/DFUService.h" // ★OTA用
00018 
00019 #define RAINBOW_RATIO 1
00020 #define RCFILTER  0.9
00021 #define RCFILTER2  0.9
00022 #define NEOPIXEL_COUNT 6
00023 #define MIN_LIGHT 0
00024 #define PNNX_FACTOR 0.1 // 0.06
00025 #define MAXARRAY 15 //15  // 心拍平均値計算用の配列サイズ //20
00026 #define MAXHRVARRAY 10 //30 // 脈間ゆらぎ平均値計算用の配列サイズ
00027 #define MIN_INTERVAL 200
00028 #define INTERVAL 10  // Loopの間隔 通常時推奨1 通信時推奨20
00029 #define MAXCOLORARRAY 1 //(MIN_INTERVAL / INTERVAL) // 色平均値計算用の配列サイズ (MIN_INTERVAL / 7)
00030 #define MAXCONARRAY 10
00031 #define MAXSTRESSARRAY 3
00032 
00033 #define BRIGHTNESS_MAX 100 // RGBLED1セットのpwm合計値の上限 ws2812b型のneopixelが6個の場合、150を超えた値にするとセンサーが誤作動する
00034 
00035 #define DIM_LED ((float)(BRIGHTNESS_MAX) / (float)(255))   // R, G, Bそれぞれのpwm値がBRIGHTNESS_MAXを超えない様にする制限
00036 
00037 
00038 // 心拍数の最低値、最高値
00039 // 人間の場合は60~150、標準80
00040 // 犬の場合は40~200、標準60
00041 #define HR_MIN 40
00042 #define HR_MAX 150
00043 
00044 #define RELAX_RATIO_MIN 0.6
00045 
00046 // ラジアンを度に変換する.
00047 #define RadianToDegree(radian)    ((180 / 3.14159) * (radian))
00048 
00049 // 度をラジアンに変換する.
00050 #define DegreeToRadian(degree)    ((3.14159 / 180) * (degree))
00051 
00052 // 色の識別値設定(ピンではない)
00053 #define RED 0
00054 #define BLUE 1
00055 #define GREEN 2
00056 
00057 #define SHOW_EXCITE 1
00058 #define SHOW_HAPPY  2
00059 #define SHOW_CONCENTRATION    4
00060 
00061 
00062 BLE  ble;
00063 DFUService *dfuService; // ★OTA用
00064 
00065 AnalogIn HRSigIn(P0_4);
00066 
00067 
00068 const static char     DEVICE_NAME[]        = "INUPATHY";
00069 static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
00070                                               GattService::UUID_DEVICE_INFORMATION_SERVICE};
00071 static volatile bool  triggerSensorPolling = true;
00072 
00073 short ColorArrayR[NEOPIXEL_COUNT];
00074 short ColorArrayG[NEOPIXEL_COUNT];
00075 short ColorArrayB[NEOPIXEL_COUNT];
00076 
00077 short TargetColorArrayR[NEOPIXEL_COUNT];
00078 short TargetColorArrayG[NEOPIXEL_COUNT];
00079 short TargetColorArrayB[NEOPIXEL_COUNT];
00080 
00081 
00082 #define NEOPIXEL_COMMANDLEN ((NEOPIXEL_COUNT * 3) + 1 + 1)
00083 
00084 
00085 unsigned long pixelStartCounter;
00086 
00087 int mainCurrentPixel = 0;
00088 int mainPrevPixel = 0;
00089 int mainPixelLightCount;
00090 int mainPixelStep = 0;
00091 int mainStepsRemain = 0;
00092 
00093 unsigned long currentmillis = 0;
00094 unsigned long prevmillis = 0;
00095 unsigned long intervalmillis = 0;
00096 unsigned long prevIntervalmillis = 0;
00097 unsigned long intervalmillisArray[MAXARRAY] = {1000};
00098 unsigned long intervalmillisHRVArray[MAXHRVARRAY] = {1000};
00099 float conArray[MAXCONARRAY] = {0.5};
00100 
00101 //float stressArray[MAXSTRESSARRAY] = {0.5};
00102 
00103 float prevFilteredAngle = 0.5;
00104 float happyRatio = 0.0;
00105 float happyRatioNow = 0.0;
00106 float prevRelaxRatio = 1.0;
00107 float prevFilteredDistRatio = 0.0;
00108 
00109 #define HR_THRESHOLD 2
00110 int HRThreshold[] = {120, 1000}; 
00111 
00112 
00113 // 気分判定フラグ
00114 #define IS_RELAX 0     
00115 #define IS_EXCITED 1
00116 #define IS_HAPPY 2   
00117 #define IS_INTERESTED 3  
00118 #define IS_STRESSED 4   // IS_STRESSEDはMOODの個数としても扱うので最後の番号にすること
00119 #define MOOD_COUNT IS_STRESSED + 1
00120 
00121 // 気分判定係数
00122 // 気分判定係数
00123 #define CONMARGIN 0.9 // 0.85
00124 #define RELAXMARGIN 0.35
00125 #define HAPPYMARGIN 0.25 // 0.225
00126 #define EXCITEMARGIN 1.5 // 1.15
00127 
00128 #define HRM_AVERAGE_COUNT 100 // MAX 125
00129 short HRM_Average[HRM_AVERAGE_COUNT] = {70};
00130 
00131 // 気分判定フラグを索引にする
00132 int MoodColorR[NEOPIXEL_COUNT][MOOD_COUNT];
00133 int MoodColorG[NEOPIXEL_COUNT][MOOD_COUNT];
00134 int MoodColorB[NEOPIXEL_COUNT][MOOD_COUNT];
00135 
00136 
00137 unsigned char RainbowR[] = { 50,  50,  50, 127, 200, 255};
00138 unsigned char RainbowG[] = { 50, 127, 255, 127, 100,  50};
00139 unsigned char RainbowB[] = {255, 127,  50,  50,  50,  50};
00140 
00141 unsigned char HappyR[] = { 50,  50,  50, 127, 200, 255};
00142 unsigned char HappyG[] = { 50, 127, 255, 127, 100,  50};
00143 unsigned char HappyB[] = {255, 127,  50,  50,  50,  50};
00144 
00145 unsigned char RelaxR[] = {  0,   0,   0,   0,   0,   0};
00146 unsigned char RelaxG[] = {255, 255, 255, 255, 255, 255};
00147 unsigned char RelaxB[] = {  0,   0,   0,   0,   0,   0};
00148 
00149 unsigned char ExciteR[] = {255, 255, 255, 255, 255, 255};
00150 unsigned char ExciteG[] = {100, 100, 100, 100, 100, 100};
00151 unsigned char ExciteB[] = {  0,   0,   0,   0,   0,   0};
00152 
00153 unsigned char StressR[] = {100, 100, 100, 100, 100, 100};
00154 unsigned char StressG[] = {  0,   0,   0,   0,   0,   0};
00155 unsigned char StressB[] = {255, 255, 255, 255, 255, 255};
00156 
00157 unsigned char InterestR[] = {255, 255, 255, 255, 255, 255};
00158 unsigned char InterestG[] = {255, 255, 255, 255, 255, 255};
00159 unsigned char InterestB[] = {150, 150, 150, 150, 150, 150};
00160 
00161 float rainbowOffset = 0.0;
00162 
00163 bool bConcentration;
00164 unsigned long loopCounter = 0;
00165 int lightPos = 1;
00166 int prevLightPos = 1;
00167 
00168 double relaxRatio = 0.0;
00169 float conRatio = 0.5;
00170 float conRatioNow = 0.5;
00171 double HR_ratio = 0.0;
00172 
00173 unsigned long IBI;
00174 
00175 int x3, y3;
00176 
00177 int mainPixelCounter;
00178 
00179 int prevInterval;
00180 int prevprevInterval;
00181 
00182 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
00183 {
00184     ble.gap().startAdvertising(); // restart advertising
00185 }
00186 /*
00187 void ConnectTimeoutCallback(Gap::EventCallback_t timeoutCallback)
00188 {
00189     ble.gap().startAdvertising(); // restart advertising
00190 }
00191   */  
00192 
00193 uint8_t BPM = 0;
00194 float sensorValue = 0;
00195 Timer t;
00196 Timer tRand;
00197 
00198 float redVal = 0;
00199 float blueVal = 255;
00200 float greenVal = 0;
00201 
00202 Ticker neopixelTick;
00203     
00204 UARTService *uartServicePtr;
00205 
00206 void neopixelTick_Handler() {
00207     return;
00208 }
00209 
00210 void SetMoodColor() {
00211     int i = 0;
00212     
00213     for(i = 0; i < NEOPIXEL_COUNT; i++) {
00214         MoodColorR[i][IS_RELAX] = RelaxR[i];
00215         MoodColorG[i][IS_RELAX] = RelaxG[i];
00216         MoodColorB[i][IS_RELAX] = RelaxB[i];
00217     }
00218     for(i = 0; i < NEOPIXEL_COUNT; i++) {
00219         MoodColorR[i][IS_EXCITED] = ExciteR[i];
00220         MoodColorG[i][IS_EXCITED] = ExciteG[i];
00221         MoodColorB[i][IS_EXCITED] = ExciteB[i];
00222     }
00223     
00224     for(i = 0; i < NEOPIXEL_COUNT; i++) {
00225         MoodColorR[i][IS_HAPPY] = HappyR[i];
00226         MoodColorG[i][IS_HAPPY] = HappyG[i];
00227         MoodColorB[i][IS_HAPPY] = HappyB[i];
00228     }
00229     for(i = 0; i < NEOPIXEL_COUNT; i++) {
00230         MoodColorR[i][IS_INTERESTED] = InterestR[i];
00231         MoodColorG[i][IS_INTERESTED] = InterestG[i];
00232         MoodColorB[i][IS_INTERESTED] = InterestB[i];
00233     }
00234     for(i = 0; i < NEOPIXEL_COUNT; i++) {
00235         MoodColorR[i][IS_STRESSED] = StressR[i];
00236         MoodColorG[i][IS_STRESSED] = StressG[i];
00237         MoodColorB[i][IS_STRESSED] = StressB[i];
00238     }
00239 }
00240 
00241 
00242 float BPM_Average = 0.0;
00243 int currentBPM = 0;
00244 
00245 // 現在の気分の判定
00246 int getMood(int bpm, double relaxRatio, double happyRatio, double conRatio) {
00247     // 第一優先:集中
00248     // 集中係数が0.95以上なら集中と判定
00249     if(conRatio >= CONMARGIN)
00250     {
00251         return IS_INTERESTED;
00252     }
00253     
00254     // 第二優先:Stress
00255     // リラックス係数が0.2以下
00256     if(relaxRatio <= RELAXMARGIN) {
00257         return IS_STRESSED;
00258     }
00259     
00260     // 第三優先:Happy
00261     // Happy係数が0.2以上
00262     if(happyRatio >= HAPPYMARGIN && relaxRatio > 0.5) {
00263         return IS_HAPPY;
00264     }
00265 
00266     // 平均の心拍より1.2倍以上だと興奮
00267     // それ以外は安静
00268     if((float)currentBPM / BPM_Average >= EXCITEMARGIN) {
00269         return IS_EXCITED;
00270     }
00271     // もしくは一定以上の心拍数だと興奮
00272     else if(BPM >= HRThreshold[0]) {
00273         return IS_EXCITED;
00274     }
00275     else {
00276         return IS_RELAX;
00277     }
00278 }
00279 
00280 //Serial mySerial(USBTX, USBRX);
00281 //Serial mySerial(P0_9, P0_11);
00282 
00283 // MACアドレスを取得してBLEのSerialNumberに組み込む
00284 void setBleSerialNumber(char *serialNumber)
00285 {
00286     int i;
00287     
00288     ble_gap_addr_t mac_address;
00289     
00290     if(sd_ble_gap_address_get(&mac_address) != NRF_SUCCESS){
00291         return;
00292     }
00293     
00294     //  ADDR_LENは6
00295     for(i=BLE_GAP_ADDR_LEN-1; i>=0; i--){
00296         sprintf(serialNumber, "%s%02x", serialNumber, (mac_address.addr)[i]);
00297     }
00298     sprintf(serialNumber, "%s%s", serialNumber, "\0");    
00299             
00300 }
00301 
00302 int main(void)
00303 {
00304 /*
00305     char msgIBI[100];
00306     int nMsgIBILen = 0;
00307     char msgHappy[10];
00308     int nMsgHappyLen = 0;
00309     char msgConcentration[10];
00310     int nMsgConcentrationLen = 0;
00311     char msgRelax[10];
00312     int nMsgRelaxLen = 0;
00313 */
00314     byte_t msgHeader[3]  = {0x49,0x4e,0x50}; 
00315     
00316 //    byte_t msg[19];
00317     byte_t msg[10];
00318 //    int nMsgLen = 0;
00319 
00320     int i;
00321 
00322     int r = 0;
00323     int g = 0;
00324     int b = 0;
00325     int brightnessSum = 0;
00326 
00327     neopixel_strip_t neopixel1;
00328     neopixel_init(&neopixel1, P0_7, 1); 
00329     neopixel_clear(&neopixel1);
00330     
00331     neopixel_strip_t neopixel2;
00332     neopixel_init(&neopixel2, P0_8, 1);
00333     neopixel_clear(&neopixel2);
00334     
00335     neopixel_strip_t neopixel3;
00336     neopixel_init(&neopixel3, P0_10, 1);
00337     neopixel_clear(&neopixel3);
00338     
00339     neopixel_strip_t neopixel4;
00340     neopixel_init(&neopixel4, P0_9, 1);
00341     neopixel_clear(&neopixel4);
00342     
00343     neopixel_strip_t neopixel5;
00344     neopixel_init(&neopixel5, P0_15, 1);
00345     neopixel_clear(&neopixel5);
00346     
00347     neopixel_strip_t neopixel6;
00348     neopixel_init(&neopixel6, P0_11, 1);
00349     neopixel_clear(&neopixel6);
00350     
00351     neopixel_strip_t *pixels[6];
00352         
00353     pixels[0] = &neopixel1;
00354     pixels[1] = &neopixel2;
00355     pixels[2] = &neopixel3;
00356     pixels[3] = &neopixel4;
00357     pixels[4] = &neopixel5;
00358     pixels[5] = &neopixel6;
00359     
00360     
00361 
00362     SetMoodColor();
00363         
00364     ble.init();
00365     ble.gap().onDisconnection(disconnectionCallback);
00366 
00367     
00368     UARTService uartService(ble);
00369     uartServicePtr = &uartService;
00370 
00371     // ★OTA用
00372     dfuService = new DFUService(ble, NULL);
00373     
00374     /* Setup primary service. */
00375     HeartRateService hrServiceBPM(ble, BPM, HeartRateService::LOCATION_CHEST);
00376 //    HeartRateService hrServiceIBI(ble, IBI, HeartRateService::LOCATION_FINGER);
00377 
00378 //    BatteryService batteryService(ble, 100);
00379     
00380     /* Setup auxiliary service. */
00381     //DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
00382     
00383     char serialNumber[16] = "IND";    
00384     // SerialNumberStringにMACアドレスを組み込む
00385     setBleSerialNumber(serialNumber);  
00386     
00387     // ★
00388     DeviceInformationService deviceInfo(ble, "INUPATHY01", "0.0.1", serialNumber, "0.0.1", "0.0.1", "0.0.1");
00389 
00390     /* Setup advertising. */
00391     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00392     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00393     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
00394     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00395     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00396     ble.gap().setAdvertisingInterval(800); /* 1000ms */
00397     ble.gap().startAdvertising();
00398     
00399     for( i = 0; i < NEOPIXEL_COUNT; i++)
00400     {   
00401         // 起動時の色パターンを設定
00402         ColorArrayR[i] = RainbowR[i];
00403         ColorArrayG[i] = RainbowG[i];
00404         ColorArrayB[i] = RainbowB[i];
00405      
00406         TargetColorArrayR[i] = ColorArrayR[i];
00407         TargetColorArrayG[i] = ColorArrayG[i];
00408         TargetColorArrayB[i] = ColorArrayB[i];
00409         
00410         // 輝度調整
00411         r = ColorArrayR[i] * DIM_LED;
00412         g = ColorArrayG[i] * DIM_LED;
00413         b = ColorArrayB[i] * DIM_LED;
00414      
00415         brightnessSum = r + g + b;
00416         
00417         // 輝度の合計値が上限を超えた場合は補正する
00418         if(brightnessSum > BRIGHTNESS_MAX) {
00419             r = (int)(r * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
00420             g = (int)(g * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
00421             b = (int)(b * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
00422         }
00423         
00424         neopixel_set_color(
00425             pixels[i],
00426             0,
00427             short(r),
00428             short(g),
00429             short(b));
00430         neopixel_show(pixels[i]);
00431     }
00432  
00433     t.start();
00434     
00435     prevmillis = t.read_ms();
00436     
00437     bool bPulseEvent = false;
00438 
00439     float degPoint = 0;
00440 
00441 //    neopixelTick.attach(neopixelTick_Handler, 0.005);
00442 
00443     while (1) {
00444 
00445 //        batteryService.updateBatteryLevel( (uint8_t)read_battery_level());
00446             
00447         float currentValue = HRSigIn; 
00448 
00449         bPulseEvent = false;
00450         
00451         if ((currentValue <= 0.3) && (sensorValue > 0.3))
00452         {
00453             bPulseEvent = true;
00454         }
00455         
00456 //        printf("S%d", sens);
00457 //        printf("S%d\n", sens);
00458 
00459         sensorValue = currentValue;
00460         
00461         if(bPulseEvent) {
00462 //            batteryService.updateBatteryLevel( (uint8_t)read_battery_level());
00463 
00464             // 現在の時刻を取得
00465 //            t.stop();         // stop, startは時間計測の結果を有意に短くしてしまうので使わない
00466             currentmillis = t.read_ms();
00467 //            t.start();
00468             // 現在時刻から過去時刻を引き、間隔を求める
00469             intervalmillis = currentmillis - prevmillis;
00470     
00471             // 心拍の間の間隔
00472             IBI = intervalmillis;
00473             
00474             // 現在の時刻を過去時刻として記録
00475             prevmillis = currentmillis;
00476         
00477             // 平均値算出用配列に値を詰める
00478             double averageIntervalMillis;
00479             
00480             for(i = 0; i < MAXARRAY ; i++)
00481             {
00482                 // 最後尾以外の場合
00483                 if(i != MAXARRAY - 1)
00484                 {
00485                     // 次の要素の値をコピーする
00486                     intervalmillisArray[i] = intervalmillisArray[i + 1];
00487                 }
00488                 // 最後尾の場合
00489                 else {
00490                     // 最新値を詰める
00491                     intervalmillisArray[i] = intervalmillis;
00492                 }
00493             }
00494             // 先頭が0の間は何もしない
00495             unsigned long sumIntervalMillis = 0;
00496             unsigned long sumIntervalMillisV = 0;
00497             if (intervalmillisArray[0] != 0)
00498             {
00499                 // 平均値算出
00500                 averageIntervalMillis = 0;
00501                 for(i = 0; i < MAXARRAY ; i++)
00502                 {
00503                     sumIntervalMillis += intervalmillisArray[i];
00504                     sumIntervalMillisV += intervalmillisArray[i] * intervalmillisArray[i];
00505                 }
00506                 
00507                 averageIntervalMillis = (double)sumIntervalMillis / (double)MAXARRAY;
00508                                 
00509                 BPM = min32_of(60000 / averageIntervalMillis, 255);
00510 //                if(intervalmillis < averageIntervalMillis - stdDev) { // || intervalmillis > averageIntervalMillis + stdDev) {
00511                 
00512                 currentBPM = min32_of(60000 / intervalmillis, 255);      
00513 /*                }
00514                 else {
00515                     currentBPM = BPM;
00516                 } */
00517             }
00518             
00519             
00520             // BPMの平均値計算
00521             int BPM_sum = 0;
00522             for(i = 0; i < HRM_AVERAGE_COUNT ; i++)
00523             {
00524                 BPM_sum += HRM_Average[i];
00525             }
00526             BPM_Average = (float)BPM_sum/(float)HRM_AVERAGE_COUNT;
00527             
00528             
00529             if(currentBPM > 0) {
00530                 for(i = 0; i < HRM_AVERAGE_COUNT ; i++)
00531                 {
00532                     // 最後尾以外の場合
00533                     if(i != HRM_AVERAGE_COUNT - 1)
00534                     {
00535                         // 次の要素の値をコピーする
00536                         HRM_Average[i] = HRM_Average[i + 1];
00537                     }
00538                     // 最後尾の場合
00539                     else {
00540                         // 最新値を詰める
00541                         HRM_Average[i] = currentBPM;
00542                     }
00543                 }
00544             }
00545             
00546             /*
00547             int IBI1024 = IBI * (1024/1000);
00548             
00549             bpm[1] = BPM;
00550             bpm[6] = (IBI1024 & 0xFF00) >> 8;
00551             bpm[7] = (IBI1024 & 0xFF);
00552             */
00553             
00554 //            printf("B%d\n", BPM);
00555 //            printf("Q%d\n", IBI);
00556 
00557 //            nMsgLen = sprintf(msg,"B%d\0", BPM); 
00558 //            ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen);
00559             
00560 //            nMsgIBILen = sprintf(msgIBI,"Q%d\0", IBI); 
00561 //            ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen);
00562             
00563             // 平均値算出用配列に値を詰める
00564             for(i = 0; i < MAXHRVARRAY ; i++)
00565             {
00566                 // 最後尾以外の場合
00567                 if(i != MAXHRVARRAY - 1)
00568                 {
00569                     // 次の要素の値をコピーする
00570                     intervalmillisHRVArray[i] = intervalmillisHRVArray[i + 1];
00571                 }
00572                 // 最後尾の場合
00573                 else {
00574                     // 最新値を詰める
00575                     intervalmillisHRVArray[i] = intervalmillis;
00576                 }
00577             }
00578 
00579             // 平均値算出
00580             int nNNInterval;
00581             unsigned long ulIntervalSum = 0;
00582             int nSampleCount = 0;
00583             for(i = 0; i < MAXHRVARRAY ; i++)
00584             {
00585                 if(intervalmillisHRVArray[i] > 0)
00586                 {
00587                     ulIntervalSum += intervalmillisHRVArray[i];
00588                     nSampleCount++;
00589                 }
00590             }
00591             
00592             float IntervalAverage = 0.0;
00593             if(nSampleCount > 0){
00594                 IntervalAverage = (float)ulIntervalSum / (float)nSampleCount;
00595             }
00596             
00597             nNNInterval = (int)((float)IntervalAverage * PNNX_FACTOR);            
00598             
00599             
00600             bool bContinue = false;
00601             int nNNxCount = 0;
00602             for(i = 0; i < MAXHRVARRAY ; i++)
00603             {
00604                 // if not end
00605                 if(i < MAXHRVARRAY - 1) {
00606                     if(abs((int)(intervalmillisHRVArray[i] - intervalmillisHRVArray[i + 1])) >= nNNInterval)
00607                     {
00608                         if(bContinue == false)
00609                         {
00610                             nNNxCount++;
00611                         }
00612                         nNNxCount++;
00613                         bContinue = true;
00614                     }
00615                     else {
00616                         bContinue = false;
00617                     }
00618                 } 
00619             }
00620         
00621             float diffRatio = (float)nNNxCount / (float)nSampleCount;
00622         
00623             if(diffRatio > 1)
00624             {
00625                 diffRatio = 1;
00626             }
00627 
00628             // リラックスの係数を算出する
00629             relaxRatio = diffRatio;
00630 
00631 //            nMsgRelaxLen = sprintf(msgRelax,"S%0.2f\0", (1-relaxRatio)); 
00632             
00633 //            nMsgLen = sprintf(msg,"R%0.2f\0", relaxRatio); 
00634 //            ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen);
00635             
00636             // 現在値から最低値を引く
00637 //            relaxRatio = relaxRatio - RELAX_RATIO_MIN;
00638             
00639             // 1.0 / 最低値 × 現在値
00640 //            relaxRatio = relaxRatio * (1.0 / (1.0 - RELAX_RATIO_MIN));
00641 
00642             int x1, y1, x2, y2;
00643             int tempx1, tempy1, tempx3, tempy3;
00644             int longx, shortx, longy, shorty;
00645             long xx1, yy1;
00646             
00647             int movex, movey;
00648             
00649             double dist1, dist2;
00650             
00651             /*
00652             // 最後尾の3データから二つのx, y地点を作る。
00653             x1 = intervalmillisArray[nSampleCount - 1];
00654             y1 = intervalmillisArray[nSampleCount - 2];
00655             x2 = intervalmillisArray[nSampleCount - 2];
00656             y2 = intervalmillisArray[nSampleCount - 3];
00657             */
00658             
00659             x1 = intervalmillis;
00660             y1 = prevInterval;
00661             x2 = prevInterval;
00662             y2 = prevprevInterval;
00663             
00664             // 2地点を結ぶ直線の長さを算出する。
00665             if(x1 > x2)
00666             {
00667                 longx = x1;
00668                 shortx = x2;
00669             }
00670             else {
00671                 longx = x2;
00672                 shortx = x1;
00673             }
00674             
00675             if(y1 > y2)
00676             {
00677                 longy = y1;
00678                 shorty = y2;
00679             }
00680             else {
00681                 longy = y2;
00682                 shorty = y1;
00683             }
00684             
00685             xx1 = longx - shortx;
00686             yy1 = longy - shorty;
00687             
00688             dist1 = sqrt((double)((xx1 * xx1) + (yy1 * yy1)));
00689             
00690             dist2 = longx + longy;
00691             float distRatio = dist1 / dist2;
00692 
00693             conRatioNow = 1 - distRatio;
00694             
00695             // 平均値算出用配列に値を詰める
00696             float averageConRatio = 0.5;
00697             for(i = 0; i < MAXCONARRAY ; i++)
00698             {
00699                 // 最後尾以外の場合
00700                 if(i != MAXCONARRAY - 1)
00701                 {
00702                     // 次の要素の値をコピーする
00703                     conArray[i] = conArray[i + 1];
00704                 }
00705                 // 最後尾の場合
00706                 else {
00707                     // 最新値を詰める
00708                     conArray[i] = distRatio;
00709                 }
00710             }
00711             // 先頭が0の間は何もしない
00712             if (conArray[0] != 0)
00713             {
00714                 // 平均値算出
00715                 averageConRatio = 0;
00716                 for(i = 0; i < MAXCONARRAY ; i++)
00717                 {
00718                     averageConRatio += conArray[i];
00719                 }
00720                 averageConRatio = averageConRatio / (double)MAXCONARRAY;  
00721             }
00722 /*
00723             float averageStressRatio = 0.5;
00724             for(i = 0; i < MAXSTRESSARRAY ; i++)
00725             {
00726                 // 最後尾以外の場合
00727                 if(i != MAXSTRESSARRAY - 1)
00728                 {
00729                     // 次の要素の値をコピーする
00730                     stressArray[i] = stressArray[i + 1];
00731                 }
00732                 // 最後尾の場合
00733                 else {
00734                     // 最新値を詰める
00735                     if(x1 > y1) {
00736                         stressArray[i] = y1 / x1;
00737                     }
00738                     else {
00739                         stressArray[i] = x1 / y1;
00740                     }
00741                 }
00742             }
00743             // 先頭が0の間は何もしない
00744             if (stressArray[0] != 0)
00745             {
00746                 // 平均値算出
00747                 averageStressRatio = 0;
00748                 for(i = 0; i < MAXSTRESSARRAY ; i++)
00749                 {
00750                     averageStressRatio += stressArray[i];
00751                 }
00752                 averageStressRatio = averageStressRatio / (double)MAXSTRESSARRAY;  
00753             }
00754   */          
00755 
00756 /*            float rcFilter = RCFILTER2;
00757             float filteredDistRatio = 0.0;
00758             float a;
00759             if(prevFilteredDistRatio != 0) {
00760                 a = rcFilter * prevFilteredDistRatio;
00761                 filteredDistRatio = a + (1 - rcFilter) * distRatio;
00762             }
00763             else {
00764                 filteredDistRatio = (1 - rcFilter) * distRatio;
00765             }            
00766             prevFilteredDistRatio = filteredDistRatio ;
00767             
00768             conRatio = filteredDistRatio ;
00769  */                   
00770             conRatio = averageConRatio;
00771             conRatio = 1 - conRatio;
00772 
00773 //            nMsgConcentrationLen = sprintf(msgConcentration,"C%0.2f\0", conRatio); 
00774 
00775 //            nMsgLen = sprintf(msg,"C%0.2f\0", conRatio); 
00776 //            ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen);
00777             
00778             
00779             prevprevInterval = prevInterval;
00780             prevInterval = intervalmillis; 
00781             
00782             // (x2, y2)が原点となるように座標を変換する
00783             movex = x2 * -1;
00784             movey = y2 * -1;
00785             
00786             tempx1 = x1 - movex;
00787             tempy1 = y1 - movey;
00788             tempx3 = x3 - movex;
00789             tempy3 = y3 - movey;
00790             
00791             // (x2, y2)を中心とした円を考える。
00792                         
00793             // (x3, y3)を(x2, y2)を中心に180°回転する。→(rotx3, roty3)
00794             double theta = DegreeToRadian(180);
00795             
00796             double rotx3 = (tempx3) * cos(theta) - (tempy3) * sin(theta);
00797             double roty3 = (tempx3) * sin(theta) + (tempy3) * cos(theta);
00798             
00799             // ベクトル1とベクトル3の内積を求める
00800             double vecInt = tempx1 * rotx3 + tempy1 * roty3;
00801             
00802             // ベクトル1とベクトル3の外積を求める
00803             double vecExt = tempx1 * roty3 - tempy1 * rotx3;
00804             
00805             // ベクトル1とベクトル3の角度を求める
00806             theta = atan2(vecExt, vecInt);
00807             
00808             double deg = RadianToDegree(theta);
00809             
00810             if( deg <= 11.25 && deg >= -11.25) {
00811                 degPoint = 0.5;
00812             }
00813             else if(deg >= 11.25 && deg <= 33.75) {
00814                 degPoint = 0.375;
00815             }
00816             else if(deg >= 33.75 && deg <= 56.25) {
00817                 degPoint = 0.25;
00818             }
00819             else if(deg >= 56.25 && deg <= 78.75) {
00820                 degPoint = 0.125;
00821             }
00822             else if(deg >= 78.75 && deg <= 101.25) {
00823                degPoint = 0;
00824             }
00825             else if(deg >= 101.25 && deg <= 123.75) {
00826                 degPoint = 0.125;
00827             }
00828             else if(deg >= 123.75 && deg <= 146.25) {
00829                 degPoint = 0.25;
00830             }
00831             else if(deg >= 146.25 && deg <= 168.75) {
00832                 degPoint = 0.375;
00833             }
00834             else if(deg >= 168.75 && deg <= 180 || deg <= 0 && deg >= -11.25) {
00835                 degPoint = 0.5;
00836             }
00837             else if(deg <= -11.25 && deg >= -33.75) {
00838                 degPoint = 0.625;
00839             }
00840             else if(deg <= -33.75 && deg >= -56.25) {
00841                 degPoint = 0.75;
00842             }
00843             else if(deg <= -56.25 && deg >= -78.75) {
00844                 degPoint = 0.875;
00845             }
00846             else if(deg <= -78.75 && deg >= -101.25) {
00847                 degPoint = 1;
00848             }
00849             else if(deg <= -101.25 && deg >= -123.75) {
00850                 degPoint = 0.875;
00851             }
00852             else if(deg <= -123.75 && deg >= -146.25) {
00853                 degPoint = 0.75;
00854             }
00855             else if(deg <= -146.25 && deg >= -168.75) {
00856                 degPoint = 0.625;
00857             }
00858             else {
00859                 degPoint = 0;
00860             }
00861             
00862             happyRatioNow = degPoint;
00863             
00864             float rcFilter = RCFILTER;
00865             float filteredAngle = rcFilter * prevFilteredAngle + (1 - rcFilter) * degPoint;            
00866             prevFilteredAngle = filteredAngle ;
00867 
00868             happyRatio = filteredAngle - 0.5;
00869             
00870             if(happyRatio <= 0){
00871                 happyRatio = abs(happyRatio);
00872             }
00873             else {
00874                 happyRatio = 0;
00875             }
00876             
00877 //            happyRatio = averageStressRatio ;// @@@
00878 
00879 //            nMsgHappyLen = sprintf(msgHappy,"H%0.2f\0", happyRatio); 
00880 
00881 //            nMsgLen = sprintf(msg,"H%0.2f\0", happyRatio); 
00882 //            ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), (uint8_t*)msg, nMsgLen);
00883             
00884 //            happyRatio = happyRatio * happyRatio * happyRatio;
00885               
00886 //            happyRatio *= 10;
00887             
00888             x3 = x2;
00889             y3 = y2;
00890                 
00891             int HR_range = 0;
00892             
00893             int HR_tempval = currentBPM;
00894             
00895             
00896             // 心拍の係数を算出する
00897             
00898             // 最大心拍数以上→最大心拍数に
00899             if( HR_MAX < HR_tempval)
00900             {
00901                 HR_tempval = HR_MAX;
00902             }
00903             
00904             // 最少心拍数以下→最少心拍数に
00905             if( HR_MIN > HR_tempval)
00906             {
00907                 HR_tempval = HR_MIN;
00908             }
00909             
00910             // 心拍の幅を計算
00911             HR_range = HR_MAX - HR_MIN;
00912             
00913             // 現在値-最少心拍数
00914             HR_tempval = HR_tempval - HR_MIN;
00915             
00916             // 心拍の係数を算出。0 ~ 1.0
00917             HR_ratio = (double)HR_tempval / (double)HR_range;
00918             
00919             if(conRatioNow >= 0.95 /* && averageAngle >= 0.7*/)
00920             {
00921                 bConcentration = true;
00922             }
00923             else {
00924                 bConcentration = false;
00925             }  
00926             prevRelaxRatio = relaxRatio;
00927 
00928 //            printf("H%d\n", hval);
00929 //            printf("R%d\n", rval);
00930 //            printf("C%d\n", cval);
00931 
00932 //            sprintf(msg,"%s%s%s%s\0", msgIBI, msgHappy, msgRelax, msgConcentration); 
00933 
00934             unsigned char happyRatioChar = (unsigned char)(happyRatio * 100);
00935             unsigned char stressRatioChar = (unsigned char)((1 - relaxRatio) * 100);
00936             unsigned char conRatioChar = (unsigned char)(conRatio * 100);
00937 
00938             memcpy(msg, msgHeader, sizeof(msgHeader));
00939             memcpy(&(msg[3]), &IBI          , sizeof(IBI)       );
00940             memcpy(&(msg[7]), &happyRatioChar   , sizeof(happyRatioChar));
00941             memcpy(&(msg[8]), &stressRatioChar  , sizeof(stressRatioChar));
00942             memcpy(&(msg[9]), &conRatioChar     , sizeof(conRatioChar)  );
00943             ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(),
00944             (uint8_t*)msg, sizeof(msg));
00945 //             (uint8_t*)msg, nMsgIBILen + nMsgHappyLen  + nMsgRelaxLen + nMsgConcentrationLen);
00946 //             (uint8_t*)msg, nMsgIBILen + 1 + nMsgHappyLen + 1 + nMsgRelaxLen + 1 + nMsgConcentrationLen);
00947             // update bpm
00948 
00949             if(ble.gap().getState().connected == 1)
00950             {
00951                 hrServiceBPM.updateHeartRate(BPM);
00952 //                hrServiceIBI.updateHeartRate(IBI);
00953             }
00954 
00955             // determine color range
00956 
00957             conRatio = conRatio - 0.5;
00958             
00959             if(conRatio < 0) {
00960                 conRatio = 0;
00961             }
00962             
00963             conRatio = conRatio * 2;
00964 
00965 //            happyRatio = happyRatio * 2;
00966 //            happyRatio = happyRatio * 2;
00967             if(happyRatio > 1) {
00968                 happyRatio = 1;
00969             }
00970         /*    
00971             if(BPM >= HR_MIN) {
00972                 happyRatio /= ((float)(BPM * 2) / 255.0) ;
00973             }
00974           */          
00975         }
00976 
00977         if(BPM > 0 && bPulseEvent) {
00978             int NewMood = getMood(BPM, relaxRatio, happyRatio, conRatio) ;
00979             
00980             for(i = 0 ; i < NEOPIXEL_COUNT; i++) {
00981                 TargetColorArrayR[i] = MoodColorR[i][NewMood];
00982                 TargetColorArrayG[i] = MoodColorG[i][NewMood];
00983                 TargetColorArrayB[i] = MoodColorB[i][NewMood];
00984             }
00985         }
00986         
00987         int deltaVal = 2;
00988         for(i = NEOPIXEL_COUNT - 1; i >= 0; i--) {
00989             if(ColorArrayR[i] < TargetColorArrayR[i]) {
00990                 ColorArrayR[i]+=deltaVal;
00991                 if(ColorArrayR[i] > TargetColorArrayR[i]) {
00992                    ColorArrayR[i] = TargetColorArrayR[i];
00993                 }
00994             }
00995             else if(ColorArrayR[i] > TargetColorArrayR[i]) {
00996                 ColorArrayR[i]-=deltaVal;
00997                 if(ColorArrayR[i] < TargetColorArrayR[i]) {
00998                    ColorArrayR[i] = TargetColorArrayR[i];
00999                 }
01000             }
01001             if(ColorArrayG[i] < TargetColorArrayG[i]) {
01002                 ColorArrayG[i]+=deltaVal;
01003                 if(ColorArrayG[i] > TargetColorArrayG[i]) {
01004                    ColorArrayG[i] = TargetColorArrayG[i];
01005                 }
01006             }
01007             else if(ColorArrayG[i] > TargetColorArrayG[i]) {
01008                 ColorArrayG[i]-=deltaVal;
01009                 if(ColorArrayG[i] < TargetColorArrayG[i]) {
01010                    ColorArrayG[i] = TargetColorArrayG[i];
01011                 }
01012             }
01013             if(ColorArrayB[i] < TargetColorArrayB[i]) {
01014                 ColorArrayB[i]+=deltaVal;
01015                 if(ColorArrayB[i] > TargetColorArrayB[i]) {
01016                    ColorArrayB[i] = TargetColorArrayB[i];
01017                 }
01018             }
01019             else if(ColorArrayB[i] > TargetColorArrayB[i]) {
01020                 ColorArrayB[i]-=deltaVal;
01021                 if(ColorArrayB[i] < TargetColorArrayB[i]) {
01022                    ColorArrayB[i] = TargetColorArrayB[i];
01023                 }
01024             }
01025             
01026             // 輝度調整
01027             r = ColorArrayR[i] * DIM_LED;
01028             g = ColorArrayG[i] * DIM_LED;
01029             b = ColorArrayB[i] * DIM_LED;
01030          
01031             brightnessSum = r + g + b;
01032             
01033             // 輝度の合計値が上限を超えた場合は補正する
01034             if(brightnessSum > BRIGHTNESS_MAX) {
01035                 r = (int)(r * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
01036                 g = (int)(g * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
01037                 b = (int)(b * ((float)BRIGHTNESS_MAX / (float)brightnessSum));
01038             }
01039             
01040             neopixel_set_color(
01041                 pixels[i],
01042                 0,
01043                 short(r),
01044                 short(g),
01045                 short(b));
01046             neopixel_show(pixels[i]);
01047         }
01048         //wait_ms(1);
01049         wait_ms(10); // 500usまで下げてもセンサー共振は起こらないことを確認
01050     }
01051 }
01052