前提・実現したいこと
ADXL345加速度センサICで3軸方向の加速度を定期的に計測し、CPUのメモリに保存したい。
発生している問題・エラーメッセージ
FFT処理を行うために、1回に取るデータは256組または512組としたいが、ADXL345から連続的に読み出すデータの組数がある程度以上になると、読み出しにかかる時間が異常に長くなる。
下記ソースコード中のloop()関数中の
for (i = 0; i < 128; i++) { adxl345_get_axi(accData[i]); // 加速度データ3軸分を読み出す }
forループ回数が128以下の場合、読み出しにかかる時間は、約120μs×ループ回数程度ですが、回数を150回程度にすると、約1ms×ループ回数程度に増えます。回数を256回にすると、forループから帰ってこなくなります。
該当のソースコード
ソースコード(下記)
/* Name: ADXL345 Reading Sample for Wio LTE JP.ino Created: 2021/09/09 9:33:14 Author: */ #include <Wire.h> #include <WioLTEforArduino.h> WioLTE Wio; #define ADXL345_I2C_ADRESS 0x53 // I2C address of ADXL345 #define ADXL345_DATAX0 0x32 // Output data register #define ADXL345_SCALE_FACTOR 1 // LSB = 4m[G] #define ADXL345_DEVID 0x00 // Device ID register #define ADXL345_DEV_ID 0xe5 // Device's ID #define ADXL345_POWER_CTL 0x2d // Power control register #define ADXL345_INT_SOURCE 0x30 // Interrupt source register, bit 7 is data-ready #define ADXL345_BW_RATE 0x2c // Bandwidth register // The setup() function runs once each time the micro-controller starts void setup() { SerialUSB.begin(115200); delay(2000); SerialUSB.println("Read ADXL345"); SerialUSB.println("Initilize Wio LTE JP"); Wio.Init(); SerialUSB.println("Setup I2C"); Wire.begin(); Wire.setClock(1000000); // I2Cのクロックを1MHzに設定 SerialUSB.println("Initilize ADXL345"); //ArduinoとADXL345のI2C通信確認 uint8_t ucData; adxl345_get_data(ADXL345_DEVID, &ucData, 1); //デバイスID取得 if (ucData != ADXL345_DEV_ID) { SerialUSB.println(F("I2C connection fail.")); } //ADXL345の帯域を3.2kHzに設定 adxl345_set_data(ADXL345_BW_RATE, 0x0f); //ADXL345を測定モードへ変更 adxl345_set_data(ADXL345_POWER_CTL, 0x08); delay(100); SerialUSB.println("ADXL345 Initialized, Start measuring."); } // Add the main program code into the continuous loop() function void loop() { int i; unsigned long time1,time2,time3; float accData[512][3]; time1 = micros(); // 読み出し開始時刻(μs) for (i = 0; i < 128; i++) { adxl345_get_axi(accData[i]); // 加速度データ3軸分を読み出す } time2 = micros(); // 3軸×512データ 読み出し完了時刻 SerialUSB.print("Read time:"); SerialUSB.print(time2 - time1); // ADXL345の読出しにかかった時間を表示 // 読出し保存したデータの先頭を確認のために表示 for(i=0;i<2; i++){ SerialUSB.print(" X:"); SerialUSB.print(accData[i][0]); SerialUSB.print(" Y:"); SerialUSB.print(accData[i][1]); SerialUSB.print(" Z:"); SerialUSB.print(accData[i][2]); SerialUSB.println(); delay(100); } delay(10000); // 10秒間待ち } /*ADXL345のレジスタデータ書き込み関数*/ void adxl345_set_data(uint8_t ucReg, uint8_t ucData) { Wire.beginTransmission(ADXL345_I2C_ADRESS); Wire.write(ucReg); Wire.write(ucData); Wire.endTransmission(true); } /*ADXL345のレジスタデータ読み込み関数*/ void adxl345_get_data(uint8_t ucReg, uint8_t* ucData, uint8_t ucSize) { uint8_t cnt = 0; Wire.beginTransmission(ADXL345_I2C_ADRESS); Wire.write(ucReg); Wire.endTransmission(false); Wire.requestFrom(ADXL345_I2C_ADRESS, ucSize, true); while (Wire.available()) { ucData[cnt] = Wire.read(); cnt++; } } /*ADXL345 X,Y,Zデータ取得関数*/ void adxl345_get_axi(float* pfData) { uint8_t ucBuf[6]; int16_t acc[3]; adxl345_get_data(ADXL345_DATAX0, ucBuf, 6); acc[0] = ((int16_t)ucBuf[1] << 8) | ucBuf[0]; acc[1] = ((int16_t)ucBuf[3] << 8) | ucBuf[2]; acc[2] = ((int16_t)ucBuf[5] << 8) | ucBuf[4]; pfData[0] = acc[0] * ADXL345_SCALE_FACTOR; pfData[1] = acc[1] * ADXL345_SCALE_FACTOR; pfData[2] = acc[2] * ADXL345_SCALE_FACTOR; }
試したこと
1回に読み出すデータの組数を変化させて、一組のデータを読むのに必要な時間を計測した。
組数が少ないうちは、一組当たり120μs程度で安定しているが、組数を増やしていくと、一組当たりの読み出し時間が急激に長くなる。
補足情報(FW/ツールのバージョンなど)
使用している開発環境: Aruduino IDE (Ver. 1.8) (C言語)
使用しているボード: Seeed社 Wio LTE JP Version
加速度センサ: ACCEL ADXL345 (I2C接続、SwitchScience通販で購入)
ここにより詳細な情報を記載してください。