syouwa-taro が 2023年11月26日17時43分18秒 に編集
注意
本文の変更
# 概要 昔から扇風機の首振りの動作・停止は背中のノブを上下させる方式が変わらない。模型のサーボで扇風機の首振りノブを上下させ、人体センサーと組み合わせ自動追尾扇風機アダプターを製作。取り付けは工具不要で容易。直接風がくるので弱でも涼しい、AutoShutOff機能もありエコ扇風機にもなる。濡れた洗濯物を追尾することを利用し、洗濯物乾燥機にも応用が期待できる。 # 動作 人の体温を、赤外フレネルレンズで指向性を鋭く(視野角5°)した赤外線センサ(Thermopile)で検出し、人がいないとき扇風機の首振りノブをPUSHし、人を検知するとノブをPULLする。ノブを上下させる方法としてプランジャーなどが考えられるが、扱いやすい模型のサーボモーターを使用した。 ##### 難しかったところ メカのノブを上下させる仕組みは、メカど素人でありトルクもなにもかもわからず ただひたすら現物に合わせ試行錯誤の連続でした。サーボで動くようになってもサーボをがっちり固定すると無理が生じ遊びをいれる必要がありました。サーボを本体に固定し、本体の扇風機への固定をゴムで遊びを作る事によりうまくいきました。3Dも使いながら次第に動くようになり、作る楽しさを味わいながらとうとう完成でした。 次に難関は電源でした。同じ電源から大電力サーボと高感度アンプを共有しているので影響が及ばないよう大容量コンデンサ(8700μ)や5Vレギュレーター前にサーボ電圧降下に影響されないように整流回路を挿入してなんとか落ち着きました。 最後の難関は意外でした。ほぼ完成したころ突然PICのCコンパイラがうごかなくなり(何も悪いことした覚えはなく(>_<))、1週間専任してもダメで諦めかけた時、アセンブラは動くのでアセンブラで作り直すことにしました。約半月かけ完成(暇人)。 # 主な材料 | 部品 | 部品名 | |:---:|:---:|:---:| |マイコン| PIC16F88 | |サーモパイル|OTP537F2| |サーボモーター| TowerPro MG995| |赤外線フレネルレンズ|[AK-FL1 ( 秋月焦電型赤外線センサキットに同梱)](https://akizukidenshi.com/download/kairo/%E3%83%87%E3%83%BC%E3%82%BF/%E3%82%BB%E3%83%B3%E3%82%B5%EF%BC%88%E4%BA%BA%E6%84%9F%EF%BC%89%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81/K001_%E7%84%A6%E9%9B%BB%E5%9E%8B%E8%B5%A4%E5%A4%96%E7%B7%9A.pdf)| |OPアンプ | LM538|
| ACアダプター(DC10V)基板 | (手持ちACアダプターを分解して基板入手)| |5VDCリレー| 使用する扇風機のACをON/OFF出来る接点容量 |
|電源用電解コンデンサ| 8700μ 1個 1000μ 2個| |5V 3端子レギュレーター| L7805 | |5V ボルテージレギュレーター| S812 813シリーズ 1個| ##### センサBOXと電源サーボBOX ![キャプションを入力できます](https://camo.elchika.com/67e67af86ea7270e2c0a6bddcc22ed3f7d7bf140/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f38616238646538612d326237302d343064622d616531332d373532316361366266383865/) ##### センサBOX(磁石で扇風機上部に張り付ける) ![キャプションを入力できます](https://camo.elchika.com/15554c457e3788eb436eccbb916b26e847faf2c7/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f63303235326264322d373735662d343933362d616331652d633039333362383435666537/) ##### サーボモーターとノブ押し上げ下げ機構(苦労してたどり着いた形状 白い樹脂は3Dで制作) ![キャプションを入力できます](https://camo.elchika.com/613d852aedbe66dbb0f64bf0c5240317d521b4bb/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f35653135626563632d663334622d343064622d383935622d356665336462363433363566/) # 回路 ![センサBOXと電源サーボBOX](https://camo.elchika.com/4b8397b222d2f62d2bd13421909a47085b19c3db/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f37653239366361342d363439632d343434642d383735392d373439636563663434663339/) # ソフトソース ソフトのあるPCのOSがピクリとも動かず(>_<) OSと心中です。<m(__)m> (おまけでリモコン首振り用のsimple工作例をつけたので、興味のある方はそちらを参照ください)
# 重要なご注意 AC100Vを扱っている本工作は個人のホビーであり真似して作ることは出来ません。真似して起きたいかなる事故も当方は責任を一切負いません。
# 参考文献 [サーモパイルの応用](http://ssc-inc.jp/products/images/ST-OUYOU.pdf) @[youtube](https://www.youtube.com/watch?v=677MNdzzosg) # 感想 メカ首振り扇風機の背中のノブをカチャカチャ音を立てながら自動追尾する光景はたまりませんヽ(^o^)丿。 最近は首振りもリモコンで操作するので、このような代物は後にも先にもこれぽっちりかもしれません。。。。 ##### おまけ と・・・・首振りがリモコン式のものはかなり簡単にできそう・・・実際リモコン送信赤外LEDとサーモグラフだけで完成(>_<)。上下左右に自動追尾します。回路図と実際の映像 ソース ご参考です。(当初ジャイロを積んで姿勢制御に使おうとしましたが、うまくいかず未使用です) ![リモコン首振り用自動追尾アダプター](https://camo.elchika.com/21e4fffe99d8257b8438fa7e33deda5ff31f2a0b/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38376461636366622d643365352d343236642d386436312d3538383537333535363238662f38663964613465632d636564382d343130382d626332372d326438363265633231366531/) @[youtube](https://www.youtube.com/watch?v=eX69Bygq2ZA&feature=emb_logo) ##### リモコン首振り用 自動追尾サーキュレーターarduinoスケッチ(ジャイロは未使用) ```arduino:リモコン対応サーモレーダー #include <Wire.h> #define PCTL 0x00 #define RST 0x01 #define FPSC 0x02 #define INTC 0x03 #define STAT 0x04 #define SCLR 0x05 #define AVE 0x07 #define INTHL 0x08 #define TTHL 0x0E #define INT0 0x10 #define T01L 0x80 #define AMG88_ADDR 0x69 // in 7bit gyroMPU6050 IIC68h //temporaryData to buffer sumtotal IIC ADlow68h ADhigh69h int TMPDAT0[64], TMPDAT1[64], TMPDAT2[64], TMPDAT3[64], TMPDATS[64]; //**object scan ** int INITSTcnt = 0; //初期設定から打ち4LOOP int TMPmax = 0, TMPmin = 400, TMPair = 0,TMPmaxmin=500,TMPminmax=0; int lmax = 0, lmin = 0, imax = 0, imin = 0; int TMPHIS[350], TMPHISmax; //TMPHIS[0]~[250] TMPDATS:250~350 TMPHIS[TMPDATS-200] よりTMPHIS[50]~[150]となるint TMPHIS[150];TMPHISmax; int MANflg, WASHflg; int OBJ10P = 0, OBJ10M = 0; //**system** int POWflg = 0, LRflg = 0, UDflg = 0, objflg = 0;//-10 on chatter protection //int LOCKflg=0; //0:解除 1以上:LOCK objectLOCKでチャッター防止 int SB = 0, PN = 0, L = 0; int t; //*UDflg int AX[20]; int AXMAX,AXMIN; int m; int FLGcnt=0; //programとGyro判断違うとき時間をあけてGyroに変える //**IR Remote** #include <IRremote.h> IRsend irsend; //***GY521 Gyro:MPU6050*** //#include <Wire.h> int accelX, accelY, accelZ, accelX1, accelZ1; int gyroX, gyroY, gyroZ, gyroX1, gyroY1, gyroZ1; int gyroZA[25]; //int DGXT,DGYT,DGZT,DGXYZT,DAXT,DAZT, AXT,AZXT;//gyro accel data変化を合計 //int DGX[7],DGY[7],DGZ[7],DAX[7],DAZ[7],AX[7],AZX[7];//gyro accel data変化行列7回分 void setup() { Serial.begin(115200); Wire.begin(); pinMode(3, OUTPUT); //赤外LED OUT pinMode(2, OUTPUT);digitalWrite(2,LOW);//赤外LED PORTをGNDとして使用 //IIC SCL:A5 //SCA:A5 SDA:A4 AMG8833 MPU6050 int fpsc = B00000000;// 1fps datasend(AMG88_ADDR, FPSC, &fpsc, 1); int intc = 0x00; // diff interrpt mode, INT output reactive datasend(AMG88_ADDR, INTC, &intc, 1); // moving average output mode active int tmp = 0x50; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x45; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x57; datasend(AMG88_ADDR, 0x1F, &tmp, 1); tmp = 0x20; datasend(AMG88_ADDR, AVE, &tmp, 1); tmp = 0x00; datasend(AMG88_ADDR, 0x1F, &tmp, 1); int sensorTemp[2]; dataread(AMG88_ADDR, TTHL, sensorTemp, 2); // Serial.print("sensor temperature:"); // Serial.println( (sensorTemp[1]*256 + sensorTemp[0])*0.0625); //***GY521 Gyro:MPU6050 *** //{Serial.begin(9600); //Wire.begin(); // setupMPU6050(); //SCL=A5 SDA=A4 Adress=AD0:LOW0x68(default) HIGH0X69 } //setup END void loop() { INITSTcnt++; if (INITSTcnt >=20) INITSTcnt = 20; //初期設定から打ち5回以上 TMPmax = 0; TMPmin = 400; TMPHISmax = 0; //max min RESET //TMPHISCLR(); //時間をかけてrefresh 安定基準 Serial.println("["); // Wire library cannnot contain more than 32 bytes in bufffer // 2byte per one data // 2 byte * 16 data * 4 times = 2byte*64point int sensorData[32]; for (int i = 0; i < 4; i++) { // read each 32 bytes dataread(AMG88_ADDR, T01L + i * 0x20, sensorData, 32); for (int l = 0 ; l < 16 ; l++) { int16_t temporaryData = (sensorData[l * 2 + 1] * 256 ) + sensorData[l * 2]; //TMPHIS[temporaryData] += 1; //TMPHISMAXの計算の時あらためてHISTGRAM作成 温度ヒストグラム+1 //*** TMPDATSUM();*** 温度Data sum3回で安定化 TMPDATS[i * 16 + l] = 0; //TMPDATS[i*16+1]=0; TMPDAT0[i * 16 + l] = temporaryData; TMPDAT1[i * 16 + l] = TMPDAT0[i * 16 + l]; //TMPDAT1[i*16+l]=TMPDAT0[i*16+l]; TMPDATS[i * 16 + l] = TMPDATS[i * 16 + l] + TMPDAT1[i * 16 + l]; //TMPDATS[i*16+l]=TMPDATS[i*16+1]+TMPDAT1[i*16+1]; TMPDAT2[i * 16 + l] = TMPDAT1[i * 16 + l]; //TMPDAT2[i*16+1]=TMPDAT1[i*16+l]; TMPDATS[i * 16 + l] = TMPDATS[i * 16 + l] + TMPDAT2[i * 16 + l]; //TMPDATS[i*16+l]=TMPDATS[i*16+1]+TMPDAT2[i*16+1]; TMPDAT3[i * 16 + l] = TMPDAT2[i * 16 + l]; //TMPDAT3[i*16+1]=TMPDAT2[i*16+l]; TMPDATS[i * 16 + l] = TMPDATS[i * 16 + l] + TMPDAT3[i * 16 + l]; //TMPDATS[i*16+l]=TMPDATS[i*16+1]+TMPDAT3[i*16+1]; //*TMPDATSUMmaxmin* if (TMPmax < TMPDATS[i * 16 + l]) { TMPmax = TMPDATS[i * 16 + l]; imax = i; lmax = l; } //if (TMPmax<TMPDATS[i*16+1]) {TMPmax=TMPDATS[i*6+1];imax=i;lmax=l;} if (TMPmin>TMPDATS[i * 16 + l]) { //if (TMPmin > TMPDATS[i * 16 + 1]) { TMPmin = TMPDATS[i * 16 + l]; imin = i; lmin = l; } Serial.print(TMPDATS[i * 16 + l]); //Serial.print(temporaryData);//Serial.print(temperature); if ( (l + i * 16) < 63 ) Serial.print(","); if (l == 7) Serial.println(); } //for:I16 END Serial.println(); //every 16data } //for:i4 END Serial.println("]"); //every 64data //********1frame Data complete********* airtemperature(); //air temperature histgraghmaxで決定 objectscan() ; //object Scanで探す Serial.print(TMPmax);Serial.print("ads"); Serial.println(imax * 16 + lmax + 1); //Serial.println(lmax); Serial.print(TMPmin);Serial.print("ads");Serial.println(imin * 16 + lmin + 1); Serial.print(TMPair);Serial.print("Mami");Serial.print(TMPmaxmin);Serial.print("Mima");Serial.println(TMPminmax); Serial.print(POWflg);Serial.print("LR"); Serial.print(LRflg);Serial.print("UD"); Serial.print(UDflg);Serial.print("OJP");Serial.println(OBJ10P);Serial.print(OBJ10M); delay(200); //delay200でLR UD flg100で一往復 //***MPU6050*** iic low:68h(defult) high:69h //recordAccelRegisters(); //recordGyroRegisters(); // POWLRUDFLG(); // printData(); } //loop END //**************************************************************************************************** void datasend(int id, int reg, int *data, int datasize) { Wire.beginTransmission(id); Wire.write(reg); for (int i = 0; i < datasize; i++) { Wire.write(data[i]); } Wire.endTransmission(); } void dataread(int id, int reg, int *data, int datasize) { Wire.beginTransmission(id); Wire.write(reg); Wire.endTransmission(false); Wire.requestFrom(id, datasize, false); for (int i = 0; i < datasize; i++) { data[i] = Wire.read(); } Wire.endTransmission(true); } void airtemperature() //温度別ヒストグラム:最大sample数=Air温度 { TMPHISmax=0;TMPHISCLR();// //init 64dataであらためてヒストグラム作成 for (int air=63;air>=0;air--) { TMPHIS[TMPDATS[air]]++; if (TMPHIS[TMPDATS[air]]>TMPHISmax) {TMPHISmax=TMPHIS[TMPDATS[air]]; TMPair=TMPDATS[air]; } } //{ for (int tmp = 149; tmp > 50; tmp--) // { if (TMPHIS[tmp] > TMPHISmax) { // TMPHISmax = TMPHIS[tmp]; // TMPair = tmp; // } // } //} if (TMPmax<TMPmaxmin) TMPmaxmin=TMPmax; //TMPair TMPmaxmin どちらかをman検出の基準温度とする if (TMPmin>TMPminmax) TMPminmax=TMPmin; //TMPair TMPminmax どちらかをwash検出の基本温度とする //****TMPair+10 以上のcell個数 TEMair-10以下のcell個数 OBJ10P=0; OBJ10M=0; //init for (int air=63;air>=0;air--) { if (TMPDATS[air]>=TMPmaxmin+40) OBJ10P++; //airより+10以上のセル個数 if (TMPDATS[air]<=TMPminmax-40) OBJ10M++; //airよりー10以下のセル個数 } } //END void objectscan() { if (INITSTcnt >= 10) { if (POWflg==0) {if (TMPDATS[imax * 16 + lmax] > TMPair + 60 ) pn(); } else {if (TMPDATS[imax * 16 + lmax] > TMPair + 30 ) //if (TMPDATS[imin * 16 + lmin] < TMPair - 15) //temp? 首振りcheck || { switch (imax * 16 + lmax + 1) //switch (imax * 16 + lmax + 1) //switch (imin*16 + lmin +1) = WASHSCAN 洗濯の時はこちらminでScan // = MANSCAN 人の時はこちらmaxでScan { case 1:nf();break; case 2:nf();break; case 3:nf();break; case 4:fn();break; case 5:fn();break; case 6:nf();break; case 7:nf();break; case 8:nf();break; case 9:nf();break; case 10:nf();break; case 11:nf();break; case 12:fn();break; case 13:fn();break; case 14:nf();break; case 15:nf();break; case 16:nf();break; case 17:nf();break; case 18:nf();break; case 19:nf();break; case 20:fn();break; case 21:fn();break; case 22:nf();break; case 23:nf();break; case 24:nf();break; case 25:nf();break; case 26:nf();break; case 27:nf();break; case 28:ff1();break; case 29:ff1();break; case 30:nf();break; case 31:nf();break; case 32:nf();break; case 33:nf();break; case 34:nf();break; case 35:nf();break; case 36:ff1();break; case 37:ff1();break; case 38:nf();break; case 39:nf();break; case 40:nf();break; case 41:nf();break; case 42:nf();break; case 43:nf();break; case 44:fn();break; case 45:fn();break; case 46:nf();break; case 47:nf();break; case 48:nf();break; case 49:nf();break; case 50:nf();break; case 51:nf();break; case 52:fn();break; case 53:fn();break; case 54:nf();break; case 55:nf();break; case 56:nf();break; case 57:nf();break; case 58:nf();break; case 59:nf();break; case 60:fn();break; case 61:fn();break; case 62:nf();break; case 63:nf();break; case 64:nf();break; default: break; //switch(i) default } //switch END } else //object なし**************** { if (POWflg >= 1) noobj(); //object無し then LRON UDON } //temp check END } //POWflg END } //INITSTEND } //END void pn() { if (POWflg==0) {irsend.sendNEC(0X17B00FF, 32); POWflg = 1;delay(1000);LRflg=-10;UDflg=-10;} //NANO digitalWrite(LED_BUILTIN, HIGH);} //gyro判定違うとき時間をおいてGyro同期 } void pf() { if (POWflg>=1) { if (LRflg>0) irsend.sendNEC(0X17BA857,32);LRflg=-20;delay(500); if (UDflg>0) irsend.sendNEC(0X17B6897,32);UDflg=-20;delay(500); irsend.sendNEC(0X17B00FF,32);POWflg=0;delay(500); } } void nn() //LRON UDON LRflg++ UDflg++ { if (LRflg == 0) {irsend.sendNEC(0X17BA857, 32);LRflg=1;delay(500);}// LRstart slowly(after chatter count) else LRflg++; // LRflg:-10~-1 LRstop slowlystat(chatter protection) 0:LRstart 1~:LRmoving if (UDflg==0) {irsend.sendNEC(0X17B6897,32);UDflg=1;delay(500);} // UDstart else UDflg++; // } void ff() //LROFF UDOFF LOCKON ONChatter=-10 { if (LRflg >= 1) {irsend.sendNEC(0X17BA857, 32);LRflg=-10;delay(500);}// LRstop rapidly else LRflg = -10; //objectありstop中 then on chatter 更新 if (UDflg>=1) {irsend.sendNEC(0X17B6897,32);UDflg=-10;delay(500);} // UDSTOP else UDflg=-10; } void ff1() //void ffl() //LROFF UDOFF heavyLOCKON ONChatter=-10 { if (LRflg >= 1) {irsend.sendNEC(0X17BA857, 32);LRflg=-20;delay(500);}// LRstop strongly flg=-20 else LRflg = -20; //objectありstop中 then on chatter 更新 if (UDflg>=1) {irsend.sendNEC(0X17B6897,32);UDflg=-20;delay(500);} // UDSTOP strongly flg=-20 else UDflg=-20; } void fn() //LROFF:ONChatter=-10 UDON:UDflg++ { if (LRflg>=1) {irsend.sendNEC(0X17BA857, 32);LRflg=-10;delay(1000);} // LRstop rapidly else LRflg=-20; //object有 stop中 then on chatter 更新 if (UDflg==0) {irsend.sendNEC(0X17B6897,32);UDflg=1;delay(500);} // UDStart slowly else {UDflg++; if (UDflg>100) UDflg=0; // 信号ありでflgが100以上ならば停止しているらしい flgを停止に変更 } } void nf() //LRON:LRflg++ UDOFF:ONChatter=-10 { if (LRflg == 0) { irsend.sendNEC(0X17BA857, 32); LRflg=1;delay(1000);}// LRstart slowly(after chatter count) else {LRflg++; if (LRflg>100) LRflg=0; // 信号ありでflgが100以上ならば停止しているらしい flgを停止に変更 } if (UDflg>=1) {irsend.sendNEC(0X17B6897,32);UDflg=-10;delay(500);} // UDSTOP rapidly (start slowly) else UDflg=-20; //更新 } void noobj() //objectなし { //objflg=0; //objectなし if ((LRflg <0 )&&(UDflg <=0)) LRflg++; //objectなし まずLRを動かす LR chatter処理中 if ((LRflg == 0)&&(UDflg <= 0)) { irsend.sendNEC(0X17BA857, 32); LRflg=1;delay(500);}//LR chatter 終了 LRstart if ((LRflg >= 1)&&(LRflg < 100)&&(UDflg <=0)) LRflg++; //LRでobject scanning中 if ((LRflg>=100)&&(UDflg<=0)) {irsend.sendNEC(0X17BA857,32);LRflg=-10;delay(1000);irsend.sendNEC(0X17B00FF,32); POWflg=0;} //LR chatter終了でobjectないのでPOWOFF // if ((LRflg <= 0)&&(UDflg >0 )&&(UDflg<100)) UDflg++; //100ないと途中で止まる UDはLRの半分100/2=50UDでobject scanning中 0<UD<100はscan // if ((LRflg <= 0)&&(UDflg>=100)) {irsend.sendNEC(0X17B6897,32);UDflg=-10;delay(1000); irsend.sendNEC(0X17BA857, 32); LRflg=1;delay(500); //UD>=100 はLRと交代 UDは少しずつ進める<=30 5 // } // UDでobject見つからずUDSTOP 交替でLRstart //if ((LRflg >= 100)&&(UDflg <= 0)) {irsend.sendNEC(0X17BA857, 32); LRflg=-10; delay(1000); irsend.sendNEC(0X17B6897,32); UDflg=1; delay(500); //} //LRでobject見つからずLRSTOP 交替でUDstart //----------------------Illegal condition-------------------------------UDOirsend.sendNEC(0X17B6897,32);UDflg=-10;} // if ((LRflg>0)&&(LRflg<100)&&(UDflg>0)) { LRflg++; irsend.sendNEC(0X17B6897,32); UDflg=-10;} //flgエラーかscan誤動作 LR++ UD#STOP:17B6897 // if ((LRflg>=100)&&(UDflg>0)&&(UDflg<100)) {UDflg++; irsend.sendNEC(0X17BA857,32); LRflg=-10;} //flgエラーかscan誤動作 UD++ LR#STOP:17BA857 // if ((LRflg>100)&&(UDflg>100)) {irsend.sendNEC(0X17BA857,31);LRflg=-10; UDflg=1;} //試しにLRだけリモコン反転してみる irsend.sendNEC(0X17B6897,32);UDflg=-10;} } //END void TMPHISCLR() { //TMPHIS[300] for ( int m = 349; m >= 0; m--) { TMPHIS[m] = 0; } } //END //***6軸Gyiro GY521:MPU6050¥300*** void setupMPU6050() { //MPU6050との通信を開始し、ジャイロと加速度の最大範囲を指定 Wire.beginTransmission(0b1101000); //I2C address of the MPU Wire.write(0x6B); //Accessing the register 6B Wire.write(0b00000000); //SLEEP register to 0 Wire.endTransmission(); Wire.beginTransmission(0b1101000); Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration Wire.write(0x00000000); //gyro to full scale ± 250deg./s Wire.endTransmission(); Wire.beginTransmission(0b1101000); Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration Wire.write(0b00000000); //accel to +/- 2g Wire.endTransmission(); } void recordAccelRegisters() { //***加速度読み取り*** Wire.beginTransmission(0b1101000); Wire.write(0x3B); // Accel Readings Wire.endTransmission(); Wire.requestFrom(0b1101000, 6); //Request Accel Registers (3B - 40) while (Wire.available() < 6); accelX = Wire.read() << 8 | Wire.read(); //Store first two bytes into accelX accelY = Wire.read() << 8 | Wire.read(); //Store middle two bytes into accelY accelZ = Wire.read() << 8 | Wire.read(); //Store last two bytes into accelZ } void recordGyroRegisters() { //***ジャイロの値を読み取る*** Wire.beginTransmission(0b1101000); //I2C address of the MPU Wire.write(0x43); //Starting register for Gyro Readings Wire.endTransmission(); Wire.requestFrom(0b1101000, 6); //Request Gyro Registers (43 - 48) while (Wire.available() < 6); gyroX = Wire.read() << 8 | Wire.read(); //Store first two bytes into accelX gyroY = Wire.read() << 8 | Wire.read(); //Store middle two bytes into accelY gyroZ = Wire.read() << 8 | Wire.read(); //Store last two bytes into accelZ } //***gyroZ 山 谷の値をSTBY(0~70) POWON(-170~150) LR(以外) の領域で個数をカウント 25sampleをshiftしながら3点で山 谷を決める void POWLRUDFLG() { //Serial.println(LRflg); //Serial.println(POWflg); //Serial.println(POWflg); gyroZA[0] = gyroZ; L=0; //gyroZ array20 leftshift for ( t = 24; t > 0; t--) { gyroZA[t] = gyroZA[t - 1]; if ((gyroZA[t]>150)||(gyroZA[t]<-170)) L++; //Lだけは領域すべてカウント } SB = 0; PN = 0; for ( t = 24; t > 2; t--) { //gyroZ 山 谷 SB PN LRの領域で個数をカウント if ((gyroZA[t - 1] > gyroZA[t]) && (gyroZA[t - 2] <= gyroZA[t - 1])) { if ((gyroZA[t - 1] <= 0) && (gyroZA[t - 1] > -70)) SB++; else { if ((gyroZA[t - 1] <= 150) && (gyroZA[t - 1] > 50)) PN++; } } if ((gyroZA[t - 1] < gyroZA[t]) && (gyroZA[t - 2] > gyroZA[t - 1])) { if ((gyroZA[t - 1] >= -70) && (gyroZA[t - 1] < 0)) SB++; else { if ((gyroZA[t - 1] >= -170) && (gyroZA[t - 1] < -70)) PN++; } } } Serial.println(gyroZ); Serial.println(SB); Serial.println(PN); Serial.println(L); //delay(1000); //**flg判定** if (SB>=10) { if (POWflg<=0) { SB=SB;//NANO{digitalWrite(LED_BUILTIN, LOW);//STBY=SB:16~18 PN:0 LR:0 POWON=SB:0 PN:9~16 LR=0 LRSB:0~2 PN;0~6 LR:6~24 n=25 } else {FLGcnt++;if (FLGcnt>=50) {FLGcnt=50;POWflg=0;} } } if ((SB<3)||(PN>=5)) { if (POWflg>=1) { SB=SB;//NANO{digitalWrite(LED_BUILTIN, HIGH); } else {FLGcnt++;if (FLGcnt>=50) {FLGcnt=50;POWflg=1;} //ONなのにOFF=POWflg=0 FLGcnt=50で修正POWflg=1 } } if (L<=3) { if (LRflg>100) LRflg=-10; //gyro LR首振りstopであるのにLRflg>=1首振りのとき flgcountupの時間100をみてflgs修正 } //**UDflg** AX[0]=accelX; AXMAX=0; AXMIN=20000; for (m=19;m>0;m--) { //m=9NG AX[m]=AX[m-1]; if (AXMAX<AX[m]) AXMAX=AX[m]; if (AXMIN>AX[m]) AXMIN=AX[m]; } } //END void printData() { //***シリアルモニタに出力*** Serial.print("Gyro"); Serial.print(" X="); Serial.print(gyroX); Serial.print(" Y="); Serial.print(gyroY); Serial.print(" Z="); Serial.print(gyroZ); Serial.print(" Accel"); Serial.print(" X="); Serial.print(accelX); Serial.print(" Y="); Serial.print(accelY); Serial.print(" Z="); Serial.println(accelZ); } ```