右クランクのトルク成分をXbee経由で4msec周期で母艦マイコンに取り込むことができたので
ローラ台に設置してペダリング波形をみてみました。
●過去2年間の経緯
MFT2017出展時に、SeatTube型のひずみとクランクのひずみ波形の測定システムを制作しました。当時は,出展目的であまり詳細な解析と考察をしなかったままで2年間放置状態となってました。改めて、2017年7月の記事をみてみると、いろいろなことを短期間にやっていて、現在より開発速度は3倍くらいの勢いでやってました。
速く走りすぎて、落ち着いてデータを解析できてなかった点が判りました。
http://shinshu-makers.net/shinshu_makers/2017/07/
●パワーメーター2019での解析
今までは、まず静的キャリブレーションしてから実際のペダリング波形を測定していましたが、キャリブレーションのやり方自体が検証されてない状態なので、まずは、現象を先入観なしに見てから、キャリブレーションや解析方法を決めていくやり方をとってみます。
「SeatTubeの波形とクランクの波形の関係を比較演算できるプログラムを作って、各種条件での両者の関係を比較してみます。」
●プログラム備忘録
①CrankのArduino ATMEGA328P 8MHz3.3Vの
プログラム備忘録
送信タイミングを4msec周期に固定しました。
int analogPin = 0; int torque = 0; int Time=0; int Time_1=0; int Time_2=0; void setup() { Serial.begin(115200); //シリアルの設定 }void loop() { Time=millis(); if(Time-Time_1>3){ Time_2=Time-Time_1; Time_1=Time; torque = analogRead(analogPin); //入力ピンの読み取り delayMicroseconds(500); Serial.println(torque); /* delayMicroseconds(500); Serial.println(‘,’); delayMicroseconds(500); Serial.println(Time_2); */ }} |
②母艦mbed NUCLEO F446REのプログラム備忘録
4msec周期でXbeeから送ってくるデータを受信割り込みを走らせてint配列Torque[]に収納してますが、味噌は、pc.printfで表示に使っているTorque[jr-2]と現在割り込みが測定しているデータの2個手前のデータを使ってます。割り込みでデータ作成中のものにアクセスすると断片的な数値しか取得できませんので、取得済みで安定している2個手前のデータを使ってます。その分、タイミングの同期が4-8msec遅れている可能性があります。数十回に一回読み間違いが発生するので、文字数が不足しているデータを省く受信割り込み関数にしてあります。
// AD7193 EVAL Board mbed NUCLEO 432KC SPIIF Program // Differential 1Ch AIN1(+) AIN2(-) //2019/07/22 Shinshu-Makers #include “mbed.h” #include <math.h> SPI ad7193 (PB_15,PB_14,PB_13); //NUCLEO L432KC MOSI, MISO, SCLK DigitalOut CS(PB_12); // Chip select //DigitalOut ADReset(p15); // Pin 15 is reset line for AD9850 Serial pc(USBTX, USBRX); // tx, rx for debug terminal Serial xbee1(PA_9,PA_10);//Xbee Right Crank Ticker ticker; Timer t; int c; char kazu[1000]; int xdata[3]; int data,data0,data1,data2 ; int sdata,sdata0,sdata1,mdata0,mdata1,mdata2,sdata_1; int condata0,condata1,condata2; int cReg0,cReg1; double mV[6],mV_Ave[6],mV_Sum[6]; int Nave; double dmV=0.196695;//μV換算 double mV0arry[500]; double mV1arry[500]; //double mV2arry[100]; //double mV3arry[100]; double mV0sum,mV1sum,mV2sum,mV3sum; double mV0ave,mV1ave,mV2ave,mV3ave; double mV0,mV1,mV2,mV3; double vector,vector_1;; double mV0Per,mV1Per; int vGo,vGo_1; //——————————– char rcv[30]={}; int Torque[100]; int ir=0,jr=0; char rcvc; int TorqueN=0; //########################################################################## int AD7193_init(){ pc.printf(“AD7193_init\n\r”); //**************************AD7193 Set******************************************************* CS=0;//Chip Selct Low設定 //while(1){ wait(1); //set_AD7193(); //MODEレジスタへモード設定データ書き込み ad7193.write(0x08);//MODEレジスタ書き込み指定 ad7193.write(0x08) ;//MODEレジスタ23-16bit書き込み=連続変換モード+InternalClock4.8MHz ad7193.write(0x00) ;//MODEレジスタ15-8bit書き込み=デフォルトのまま ad7193.write(0x01) ;//MODEレジスタ7-0bit書き込み=4800Hz設定 //mode書き込み確認 ad7193.write(0x48);//MODEレジスタ書き込み指定 mdata0=ad7193.write(0x00) ;//MODEレジスタ23-16bit書き込み=連続変換モード+InternalClock4.8MHz mdata1=ad7193.write(0x00) ;//MODEレジスタ15-8bit書き込み=デフォルトのまま mdata2=ad7193.write(0x00) ;//MODEレジスタ7-0bit書き込み=4800Hz設定 //pc.printf(“MAIN:mdata:%x,%x,%x\n\r”,mdata0,mdata1,mdata2); //設定レジスタへ設定データ書き込み ad7193.write(0x10);//設定レジスタ書き込み指定 ad7193.write(0x00) ;//設定レジスタ23-16bit書き込み=デフォルトのまま ad7193.write(0x0f) ;//設定レジスタ15-8bit書き込み=1ch-4ch自動スキャン設定 AIN1+ AIN2- ad7193.write(0x17) ;//設定レジスタ7-0bit書き込み=BUF Gain128 //Config書き込み確認 ad7193.write(0x50);//Configレジスタ書き込み指定 condata0=ad7193.write(0x00) ;//MODEレジスタ23-16bit書き込み=連続変換モード+InternalClock4.8MHz condata1=ad7193.write(0x00) ;//MODEレジスタ15-8bit書き込み=デフォルトのまま condata2=ad7193.write(0x00) ;//MODEレジスタ7-0bit書き込み=4800Hz設定 //pc.printf(“MAIN:mdata:%x,%x,%x,condata:%x,%x,%x\n\r”,mdata0,mdata1,mdata2,condata0,condata1,condata2); //***************************************************************************************************************** } int AD7193_Averaging(){ int i=0; int j=0; mV0sum=0; mV1sum=0; //************************************Averaging ********************************************************** Nave=100; data0=0; data1=0; data2=0; for (i=0;i<Nave;i++){ //MODEレジスタへモード設定データ書き込み ad7193.write(0x08);//MODEレジスタ書き込み指定 ad7193.write(0x08) ;//MODEレジスタ23-16bit書き込み=連続変換モード+InternalClock4.8MHz ad7193.write(0x00) ;//MODEレジスタ15-8bit書き込み=デフォルトのまま ad7193.write(0x01) ;//MODEレジスタ7-0bit書き込み=4800Hz設定 //設定レジスタへ設定データ書き込み ad7193.write(0x10);//設定レジスタ書き込み指定 ad7193.write(0x00) ;//設定レジスタ23-16bit書き込み=デフォルトのまま ad7193.write(0x03) ;//設定レジスタ15-8bit書き込み=1ch3ch 自動スキャン設定 AIN1+ AIN2- ad7193.write(0x17) ;//設定レジスタ7-0bit書き込み=BUF Gain128 wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //=====================0ch Averaging================================== ad7193.write(0x58); data0=ad7193.write(0x0); data1=ad7193.write(0x0); data2=ad7193.write(0x0); mV0arry[i]=((double)data0*65536+(double)data1*256+(double)data2)*dmV; mV0sum=mV0sum+mV0arry[i]; //pc.printf(“%d:mV0:data0=,%d,data1=,%d,data2=,%d,mV0arry=,%10.5f,mV0sum=,%10.5f\n\r”,i,data0,data1,data2,mV0arry[i],mV0sum);wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //==================1ch Averaging===================================== ad7193.write(0x58); data0=ad7193.write(0x0); data1=ad7193.write(0x0); data2=ad7193.write(0x0); mV1arry[i]=((double)data0*65536+(double)data1*256+(double)data2)*dmV; mV1sum=mV1sum+mV1arry[i]; wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //pc.printf(“%d:mV1:data0=,%d,data1=,%d,data2=,%d,mV1arry=,%10.5f,mV1sum=,%10.5f\n\r”,i,data0,data1,data2,mV1arry[i],mV1sum); //pc.printf(“%d:mV[0]=,%6.0f,mV[1]=,%6.0f,mV0sum=,%6.0f,mV1sum=,%6.0f\n\r”,i,mV0arry[i],mV1arry[i],mV0sum,mV1sum); }//for loopmV0ave=mV0sum/Nave; mV1ave=mV1sum/Nave;//pc.printf(“Averaging:mV0ave=%10.5f,mV1ave=%10.5f\n\r”,mV0ave,mV1ave);} //*********************************************************************************************************** int AD7193_MA(int i,int MA){ //pc.printf(“AD719MA:%d,%d\n\r”,i,MA); int j; //MODEレジスタへモード設定データ書き込み ad7193.write(0x08);//MODEレジスタ書き込み指定 ad7193.write(0x08) ;//MODEレジスタ23-16bit書き込み=連続変換モード+InternalClock4.8MHz ad7193.write(0x00) ;//MODEレジスタ15-8bit書き込み=デフォルトのまま ad7193.write(0x01) ;//MODEレジスタ7-0bit書き込み=4800Hz設定 //設定レジスタへ設定データ書き込み ad7193.write(0x10);//設定レジスタ書き込み指定 ad7193.write(0x00) ;//設定レジスタ23-16bit書き込み=デフォルトのまま ad7193.write(0x03) ;//設定レジスタ15-8bit書き込み=1ch3ch 自動スキャン設定 AIN1+ AIN2- ad7193.write(0x17) ;//設定レジスタ7-0bit書き込み=BUF Gain128 wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //=====================0ch================================== ad7193.write(0x58); data0=ad7193.write(0x0); data1=ad7193.write(0x0); data2=ad7193.write(0x0); mV0arry[i%MA]=((double)data0*65536+(double)data1*256+(double)data2)*dmV; wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //==================1ch===================================== ad7193.write(0x58); data0=ad7193.write(0x0); data1=ad7193.write(0x0); data2=ad7193.write(0x0); mV1arry[i%MA]=((double)data0*65536+(double)data1*256+(double)data2)*dmV; wait_ms(1);//1msec以上WaitいれないとCH切り替えできない //pc.printf(“data0x=%x,data1x=%x,data2x=%x,V[%d]=%d\n\r”,data0,data1,data2,i,mV[i]); if (i>MA){ mV0sum=0; mV1sum=0; for (j=0;j<MA;j++){ mV0sum=mV0sum+mV0arry[i%MA]; mV1sum=mV1sum+mV1arry[i%MA]; } mV0=mV0sum/MA/1000; mV1=mV1sum/MA/1000; }} //================================Serial Function====================================== void xbee1_Rcv(){ if(xbee1.readable()){ rcvc=xbee1.getc(); //pc.putc(rcvc); rcv[ir]=rcvc; ir++; if (rcvc==0x0d && strlen(rcv)>4){ Torque[jr%100]=atoi(rcv);jr++; ir=0; } }} //********************************************************************************************************************************** int main() { pc.baud(115200); xbee1.baud(115200); int i,j,n,n_1; //pc.printf(“AD7193_init=>\n\r”); i=0; pc.printf(“%4.0f,%4.0f,%d,%d\n\r”,mV0,mV1,Torque[(jr-2)%100],t.read_ms()); } |
●試しに踏んだグラフ
黄緑がクランクのトルク、黒がSeatTube曲げ、踏むと下方向へマイナスピークが発生します。
ピークの深さの変化が線形関係が見れそうなので、統計処理してどの程度の線形性があるかみてみます。
拡大してみるとクランクは右のみので谷状の波形ですが、
シートチューブは、左右踏みの出力が1CHにでてくるのでSINカーブに近い形状がでてます。クランクも左右を合成するとSINカーブに近いものがでるはずです。
●以後
波形を統計処理するVBAプログラム作ります。
左クランクも同様な波形が必要なので、Xbeeで作ります。
TWELITEがXbeeほど、転送速度がでそうもないので、TWELITEは、ペンディングにします。
Xbeeの欠点である電流値を食う点は、小型で高性能バッテリーで左クランクに収める検討をします。