●クワエルマウスWS1は機能評価試作機
重くてでかいので、手で支えることにしました。
クワエル機能開発をするための評価機と割り切って完成させました。センサ側は、Promicroでなくmbed NUCLEO L432KCにしました。
理由1:センサが多いのでArduinoではピン数不足
理由2:3.3vセンサと5vセンサのトレラブル対応できない点
理由3:プログラム容量が大きくなった場合Arduinoでなくmbedで処理するため
mbedをセンサ用CPUにしました。Arduino Pro microは、Xbeeで受信したデータをHIDマウス機能でPCへ転送する機能をさせます。Xbeeは、MFT会場でBlueToothなど使うと混信リスクがある点で無線はXbeeということにしました。
●マウス側基板
3個のHX711と微差圧センサ1個のデータを取集してXbeeでPro microに送信します。基板面積に乗らないので、HX711の上空にXbee基板とI2Cターミナルブロックを載せました。
電池は、単四2本直接NUCLEO L432KCに入れられます。
L432KCの電源仕様が1.7~3.6Vで丁度電池2本でOKですが
Xbeeが数百mA食うので、1時間程度しか持ちません。
Pro microの受信波形とmbedの送信波形を比較してみました。
当然どんぴしゃりです。
mbedプログラムは、これです。
//実装接続プログラム2016/10/16 rev.1.0 //単一プログラムでライブラリー化せず // ********************WBite Mouse***************************** // Target NUCLEO L432KC // // OMRON D6F-PH5050 I2C diff pressure meter i2C(PB_7.PB_6) SDA,SCL // HX711 //************************************************************* //————————————Header ———————————–#include “mbed.h” #define D6F_ADDR 0xD8 //I2Cアドレス定義 #include “HX711.h” //For L432KC 3CH board HX711 scale1(PB_5,PB_4);//(DATA,CLOCK) HX711 scale2(PA_1,PA_0);//(DATA,CLOCK) HX711 scale3(PA_3,PA_4);//(DATA,CLOCK) I2C i2c1(PB_7,PB_6);//SDA SCL DigitalOut led1(LED1); DigitalOut led2(LED2); Serial pc(USBTX, USBRX);//USB serial Serial xbee(PA_9,PA_10);//Tx Rx //————————–HX711—————————————-// float w1,w2,w3; float sum_w1,sum_w2,sum_w3; float ave_w1,ave_w2,ave_w3; //————————-D6FPH 定義————————————// float tmpr=20; float Cof=0.9; int wtime=50; static const char d6f_config[5]={0x00,0xD0,0x40,0x18,0x06}; static const char d6f_comp_read[4]={0x00,0xD0,0x51,0x2c};//差圧データx51hを指定 static const char d6f_temp_read[4]={0x00,0xD0,0x61,0x2c};//温度テータx61hを指定 static const char d6f_mem_read[1]={0x07};//リードレジスタx07hから読む static const char d6f_init[2]={0x0B,0x00};//初期化レジスタx0Bhをx00でリセット //—————————————————————————– //初期化関数//uint8_t d6fph_strt(void) { uint8_t error;//D6F-PHのレジスタ通信データを宣言・初期化するerror=i2c1.write(D6F_ADDR,d6f_init,2);return(error); }//差圧読み込み関数// float read_pressure(void) { char error; char rdata[2]; uint16_t raw_diff_pa; float diff_pa; error=i2c1.write(D6F_ADDR,d6f_config,5); wait_us(33000); error=i2c1.write(D6F_ADDR,d6f_comp_read,4); error=i2c1.write(D6F_ADDR,d6f_mem_read,1,true); error=i2c1.read(0xD9,rdata,2); if (error){ return(error); } raw_diff_pa=(rdata[0]<<8)+rdata[1]; diff_pa=((float)raw_diff_pa-1024)/60-500; return(diff_pa); } //温度読み取り関数// float read_d6f_temp(void) { char error; char rdata[2]; uint16_t raw_ref_temp; float ref_temp;i2c1.write(D6F_ADDR,d6f_config,5); wait_us(33000); error=i2c1.write(D6F_ADDR,d6f_temp_read,4); error=i2c1.write(D6F_ADDR,d6f_mem_read,1,true); error=i2c1.read(0xD9,rdata,2); if(error){ return(error); } raw_ref_temp=(rdata[0]<<8)+rdata[1]; ref_temp=((float)raw_ref_temp-10214)/37.39; return(ref_temp); } //cout関数 //関数定義終わり—————————// //————————-main————————— int main() { while(1){ } |
●Promicro基板
PC側受信側です。
Arduino Pro microは、シリアルが1個しかないので、Xbeeはソフトシリアルをつかいます。しかし、ソフトシリアルが使えるピンが限られているので、それを知らないで半日苦労しました。
ソフトシリアルに関しては、ここのサイトで詳しく解説されてます。
https://garretlab.web.fc2.com/arduino_reference/libraries/standard_libraries/SoftwareSerial/index.html
ArduinoのCは、独自のフォーマットなので、C++に慣れていると手間取ってしまいます。特に、文字列処理と文字出力が非常に低機能なので、シリアル受信プログラムがmbedだと数十分で作れるものがArduinoだと1日がかりとなってしまって、Arduinoは、将来的には無くなったほうがいいと思います。入門者の方は、mbedから入門して、必要に応じてarduinoを使うほうがベターです。
苦労して作ったXbee受信プログラムです。
Pro_micro_Mouse_Xbee_Cordinate_stringchar_rev06
//================================================== // BiteMouse (カムマウス)WS1プログラム rev06 // Arduino Pro micro互換 中華Pro Micro ATmega32U4 5V/16MHz // 使い方は、下記リンクを参考にさせていただきました。 //https://ht-deko.com/arduino/promicro.html // 原理:3軸センサでFxがカーソルの左右 Fzで上下移動座標ですが、 // 1:FzとFyの組み合わせで上下方向していしてます。 // 2:FxとFzで閾値以上で加速します // D6FPHをLPC1678からソフトシリアルで鼻息 口息圧力を転送しえCLICKとPRESSの2Ch//====================================================#include <Mouse.h> #include <SoftwareSerial.h> //===========xbee_Recive===================== int i,j,k; int buflen=0; char c; char buff[100]={}; String strBuff; String strPara[20]={}; float Para[5]={}; //=========================================== int Fx; int Fy; int Fz; int Fx_1; int Fy_1; int Fz_1; int Fxs; int Fys; int Fzs; int gainxN=1; int gainzN=1; char xbeeDatac[30]; String xbeeDatas; float Press; int in_Press; double vector;double vector_1; SoftwareSerial mySerial(10, 16); // RX, TX //Variables double gainx=1; double gainz=1; int Fxr; int Fyr; int Fzr; //=================SET UP================= void setup() { Serial.begin(57600); // initialize mouse control: Mouse.begin(); //—–mbed Serial D6FPH data—— mySerial.begin(9600); Serial.println(“Set Up”); } //<<<<<<<<<<<<<<<<<<<<<<<<<LOOP>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void loop() { if(mySerial.available()>0){ Fx_1=Fx; Fz_1=Fz; //====================Xbee Recieve===================== xbee_Recive(); //===================================================== //===========vector値で加速係数変化=================== vector_1=vector; vector=sqrt(pow(Fx,2)+pow(Fz,2));//Serial.print(vector); // Serial.print(“——–“); // Serial.println(gainxN); if (abs(Fx)>=20){ gainxN=1; } if (abs(Fx)<20){ gainxN=1; } if (abs(Fz)>=20){ gainzN=1; } if (abs(Fz)<20){ gainzN=1; } // ===Fy値が前押し(マイナス)ならFzの方向を逆転======= if (Fy<0){ gainz=-1; } if (Fy>=0){ gainz=1; } //=============================================== //Serial.print(“Main:”); Serial.print(Fx); Serial.print(“,”); Serial.print(Fz); Serial.print(“,”); Serial.print(Fy); Serial.print(“,”); Serial.print(Fz*gainz*gainzN); Serial.print(“,”); Serial.print(Fx*gainx*gainxN); Serial.print(“,”); Serial.println(Press);//if (abs(Fx-Fx_1)>1 || abs(Fz-Fz_1)>1) { //***************静止状態のオフセットゼロ************** if (abs(vector-vector_1)<2){ Fx=Fx_1; Fz=Fz_1; } /* //<<<<<<<<<<<<<<<<<CLICK & PRESS>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //Serial.println(Press); if (Press>5){// Click Mouse.click(); delay(0.1); Serial.println(“MouseClick=1”); } if (Press<-5 && in_Press==0){//Press Mouse.press(); in_Press=1; Serial.println(“MousePress=1”); } if (Press<-5 && in_Press==1){//Release Mouse.release(); in_Press=0; Serial.println(“MouseRelease=1”); } */ //<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //test Fz=1; Mouse.move(Fx*gainx*gainxN,Fz*gainz*gainzN,0);} } //========================================================================================= void xbee_Recive(){ /*Serial.print(“buff[“); strBuff=buff; /*Serial.print(“strPara[0]=”); }//Availableなら |
●最重要:歯とセンサの接触構造と処理Pgm
Fx(左右移動:歯ぎしり力)、Fz(上下移動:噛む圧縮力)Fy(前後移動:あごの前後力)と3つの力をセンサに伝えられるような歯とセンサの接触構造が最重要課題となてます。複雑な歯の形状なので、樹脂粘土でかたどって試行錯誤してみようと思います。形状によって、力の大きさとスピードとクロストークが違ってきますので、接触構造ができてから処理プログラムを作るという順になります。
5月7日までにどこまでできるか判りませんので、WS2は、3D CAD形状と骨組試作までとなりそうです。
ご無沙汰しております。
NucleoもPro microと同様にHID機能が付いているようなので、下記の記事のようにNucleo自体をUSBデバイス化ができるそうです。
WBite Mouseのソースコードをみる限りではPA11とPA12は空いていそうですし、いかがでしょうか?
https://qiita.com/eggman/items/9e7dad30e4d2833af17f
また、よほどのことがない限り大丈夫だと思いますが、XBee(ZigBee)はBluetooth/BLE/Wi-Fiと同じ2.4GHz帯だったと思うので、混信リスクはゼロではない気がします 。
お忙しいことは重々承知していますが、余力がありましたらご検討ください。
teruki.kirihata様
返信遅れまして、申し訳ございません。
2019年から所用で忙しくなって更新間隔が1-2週間まったくない場合が発生してます。
昨年MFT2018で、アドバイスいただいたおかげでMFT2019のネタにさせていただいてます。感謝しております。
NUCLEOでもHIDデバイスになれるとの情報誠に有難うございます。
NUCLEOに慣れているので、助かります。
MFT会場では、毎年必ずトラブルが発生してますので、万一を考えて無線がだめだったら有線で
PCへHID接続できるように対策を取らせていただきます。
開発状況は、歯のかみ合わせとセンサ接触部の形状が大きな課題となってます。
上下左右と前後の力をリニアにくわえられないとマウス操作ができないので肝となります。
クワエルマウスというより、歯列全体でマウスを固定する構造になりつつあります。
5月7日までに一号機仕上げますので、アドバイス宜しくお願いいたします。
ご支援誠に有難うございます。