【STA25】BaseにBNO085x2個分データをSDログ追加<Teensy超高速SD書き込み>

Baseの衛星補足データとRTK測位データのSDログが出来上がったので、次はBNO085x2個分のデータログをやりました。
Baseの1Kbyteデータログと同時にBNOの100Hzログも余裕できているのはTeensyのSDカードのIFがSDIOのおかげです。
マイコンのSPIだったら、10MBPSなんて超高速書き込みできませんから。

●ログデータ量は、1分間に1MByte発生する
BNo085のRVCモードは、10msec周期でyaw,pitch,roll,Accx,AccY,AccZを19バイトのバイナリで送ってきます。
Baseは、120msecと遅いので、SDログは、独立して行います。
ADS122U04は、2.4msec周期でデータを出力してきますが、10msecまで間引いてログします。ADSの場合ピン割り込みが入るので
これから、全体のシステムと割り込みの関係をプログラムしていきます、下手をすると今までのプログラム全部改造しなければいけななくなるので、そういうことにならないようにADSのプログラムを作成していきます。
全データを計算すると下表になりました。10分で10MBですので、1分で1MBになります。
だいたいスキー1本で20-30分測定するので、1回で20-30MBのデータログができます。
ファイル数は、Base,Rover,BNO+ADSの3ファイルにする予定です。
リアルタイム同期はタイムパルスとマイコン時刻を同時ログすることで、各センサとの同期合わせは、測定後のデータ処理で行います。
マイコン上で同期合わせすると、プログラムが複雑になってしまうので、STA25では、マイコンでの同期処理を避けました。

●BNO受信プログラムの備忘録
ポイント1:1つの関数に2個の受信部をいれること
=>当初2個の関数でLOOP内で2個並べてログしていたのですが、同期が全然とれませんでした、そこで、同じ関数内で受信処理しました。何しろ、Teensyのハードウェアシリアルのバッファからの読み込み時間は、数十から数百μsecしかかりませんので、2個分読んでも1msecもかかりませんので。周期が10msecで入ってくるデータに対して余裕でログ処理できます。
一応受信関数int bnoread31(uint8_t *dBuf3,uint8_t *dBuf1,int n,int bncnt0)を記録しておきます。
この関数の引数は、出力データとしてSerial3のデータdBuf3[19]とSerrial1のデータdBuf1[19]とn=19,bncnt0は、データカウンタで
RETURNでインクリメントしたbncnt0として返します。

//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
//———–Serial3 Serial1同時READ———————————————————–
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
int bnoread31(uint8_t *dBuf3,uint8_t *dBuf1,int n,int bncnt0){//1shotを受信して変換してdBuf1生データで返す
//returnは、時刻 配列 d[]のポインタを渡されるので、*dがd番地の実数 nは、バイト数String bnostr3;
int bn85=0;//
int t,t_1;
int period[12];
int cnt3=0;//Byte counter
int cnt1=0;//Byte Counter// uint8_t dBuf3[19],dB3[16];;
//Serial,printf(“bnoread:Serail3=%d\n\r”,Serial3.available());
//Serial,printf(“bnoread:Serail1=%d\n\r”,Serial1.available());
if(Serial3.available()>18){ //19byte x12回でdBuf5満杯
//[0]0xaa,[1]0xaa,[2]index,[3]yawL,[4]yawM,[5]pitchL,[6]pitchM,[7]rollL,[8]roolM,[9]axL,[10]axM,[11]ayL,[12]ayM,[13]azL,[14]azM,[15]MI,[16]MR,[17]Rsv,[18]Chcksum
uint8_t b30=Serial3.read();
uint8_t b31=Serial3.read();
uint8_t b32=Serial3.read();

t=micros();
if(b30==0xaa && b31==0xaa )
{
dBuf3[0]=b30;
dBuf3[1]=b31;
dBuf3[2]=b32;
//Serial.printf(“Serial3:%x,%x,%x,”,b30,b31,b32);
//while(Serial3.available()>0){
while(cnt3<16){
if(Serial3.available()){
dBuf3[cnt3+3]=Serial3.read();
//Serial.print(dBuf3[cnt3+3],HEX);
cnt3++;
//Serial.printf(“cnt3=%d,[%x],millis=%d\n\r”,cnt3,dBuf3[cnt3+3],millis());
}
}
//Serial.println();
bncnt0++;
}//0xaa && 0xaa end
}//END if serial3 available

if(Serial1.available()>18){ //19byte x12回でdBuf5満杯
//[0]0xaa,[1]0xaa,[2]index,[3]yawL,[4]yawM,[5]pitchL,[6]pitchM,[7]rollL,[8]roolM,[9]axL,[10]axM,[11]ayL,[12]ayM,[13]azL,[14]azM,[15]MI,[16]MR,[17]Rsv,[18]Chcksum
uint8_t b10=Serial1.read();
uint8_t b11=Serial1.read();
uint8_t b12=Serial1.read();

t=micros();
if(b10==0xaa && b11==0xaa )
{
dBuf1[0]=b10;
dBuf1[1]=b11;
dBuf1[2]=b12;
//Serial.printf(“Serial1:%x,%x,%x,”,b10,b11,b12);
//while(Serial1.available()>0){
while(cnt1<16){
if(Serial1.available()){
dBuf1[cnt1+3]=Serial1.read();
//Serial.print(dBuf1[cnt1+3],HEX);
cnt1++;
//Serial.printf(“cnt1=%d,[%x],millis=%d\n\r”,cnt1,dBuf1[cnt1+3],millis());
}
}
//Serial.println();

}//0xaa && 0xaa end
}//if serial available
t=micros();

return bncnt0;//累計EPOCH数
}//bnoread31 END
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

●BNOのSD書き込み部
デバッグしやすいように関数でなくLoop直下に直接いれました。
ポイント1:Loop内に処理をいれると命令間が数μsecと超高速で回るので、一回受信処理しても、次に周回でまた同じ受信処理がぐるぐる回ります。1msecで数回まわりので、10msecだと数十回回って無駄な処理をしますので、データの更新チェックをして1回だけSDログ処理に回すようにします。その場合のカウンタは、BNOのヘッダについているINDEXを使います。1バイトですが、一個前のINDEX値を記憶しておいて現在のINDEX値と違ったら、SDログに入るようになってます。

//●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
//+++++++++++++++++++LOOP LOOP LOOP LOOP LOOP++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void loop()
{//———-BNOREAD してSD ログ dN>500以降常時ログ————————————
bncnt0=bnoread31(dB3,dB1,19,bncnt0);//cnt dB1[19]戻り

//uint32_tでカウント
//Serial.printf(“bncnt=%d,bnstr3=%s\n\r”,bncnt,bnostr3);
uint8_t dno[4];//bnocntを4byteに変換
if(fnflag==1 && bncnt0>bncnt0_1){//dN>500で毎回カウンタ更新された場合にSD Write
//myFileI = sd.open(fnameI, FILE_WRITE);//タイマーでOPENするので初め500カウントまでエラー
if(!myFileI){//エラーなら記録しない
//Serial.printf(“BNOmyFileI open Error======fnameI=%c,bncnt=%d,,dcount=%d\n\r”,fnameI,bncnt,dcount);
//exit(0);
}
else//エラーでないならSD write
{
//Serial.println(“BNO==============myFileI Write Successed=========”);

i_to_char(bncnt0,dno, 0);//bncntを4バイトのdnoに分解
Serial.printf(“bncnt0=%d,dno[]=%x,%x,%x,%x\n\r”,bncnt0,dno[0],dno[1],dno[2],dno[3]);
myFileI.write(0x03);//Serial3のマーク
myFileI.write(dno[0]);//bnocntをヘッドに格納
myFileI.write(dno[1]);
myFileI.write(dno[2]);
myFileI.write(dno[3]);
Serial.print(“3:”);
for(i=0;i<19;i++){
myFileI.write(dB3[i]);//dB3 Center IMU
Serial.print(dB3[i],HEX);
}
Serial.println();
Serial.print(“1:”);
for(i=0;i<19;i++){
myFileI.write(dB1[i]);//dB1 Top IMU
Serial.print(dB1[i],HEX);
}
bncnt0_1=bncnt0;
}// myFIleI ELSE END

}//BNO 受信 ログ END

 

●動作チェック
シリアルモニターしたBNOデータとSDログされたデータをバイナリエディタで確認しました。

●デバッグ回路基板がごちゃごちゃになってきた
センサが増えて、基板も増えてくるので、デバッグ作業で事故が発生しやすくなってきたので、配線を整理します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です