hanyazou / BMI160-Arduino

76 stars 35 forks source link

Not issue but Question #1

Closed mjs513 closed 7 years ago

mjs513 commented 7 years ago

Do you have an examples of using FIFO. In the sensortec support.c file I found this code:

    case STANDARD_UI_IMU_FIFO:
        com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
                /* bmi160_delay_ms in ms*/
        s_bmi160.delay_msec(BMI160_MODE_SWITCHING_DELAY);

        /*Set the gyro mode as Normal write in the register 0x7E*/
        com_rslt += bmi160_set_command_register(GYRO_MODE_NORMAL);
                /* bmi160_delay_ms in ms*/
        s_bmi160.delay_msec(BMI160_MODE_SWITCHING_DELAY);

        /* Set the accel bandwidth as Normal */
        com_rslt += bmi160_set_accel_bw(BMI160_ACCEL_NORMAL_AVG4);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Set the gryo bandwidth as Normal */
        com_rslt += bmi160_set_gyro_bw(BMI160_GYRO_NORMAL_MODE);
        s_bmi160.delay_msec(BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* set gyro data rate as 100Hz*/
        com_rslt += bmi160_set_gyro_output_data_rate(
            BMI160_GYRO_OUTPUT_DATA_RATE_100HZ);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* set accel data rate as 100Hz*/
        com_rslt += bmi160_set_accel_output_data_rate(
            BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ,
            BMI160_ACCEL_OSR4_AVG1);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /***** read FIFO data based on interrupt*****/
        com_rslt += bmi160_interrupt_configuration();

        /* Enable the FIFO header*/
        com_rslt += bmi160_set_fifo_header_enable(FIFO_HEADER_ENABLE);
        s_bmi160.delay_msec(BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Enable the FIFO accel*/
        com_rslt += bmi160_set_fifo_accel_enable(FIFO_ACCEL_ENABLE);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Enable the FIFO gyro*/
        com_rslt += bmi160_set_fifo_gyro_enable(FIFO_GYRO_ENABLE);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Enable the FIFO time*/
        com_rslt += bmi160_set_fifo_time_enable(FIFO_TIME_ENABLE);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Enable FIFO water mark interrupts in INT_EN[1] */
        com_rslt += bmi160_set_intr_enable_1(BMI160_FIFO_WM_ENABLE,BMI160_ENABLE);

        /* Enable the FIFO water mark interrupt1*/
        com_rslt += bmi160_set_intr_fifo_wm(BMI160_INIT_VALUE,BMI160_ENABLE);
        s_bmi160.delay_msec(BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* Enable the FIFO water mark interrupt2*/
        com_rslt += bmi160_set_intr_fifo_wm(BMI160_ENABLE,  BMI160_ENABLE);
        s_bmi160.delay_msec(
        BMI160_GEN_READ_WRITE_DELAY);/* bmi160_delay_ms in ms*/

        /* set the fifo water mark as 10*/
        com_rslt += bmi160_set_fifo_wm(BMI160_ENABLE_FIFO_WM);

        /* read the FIFO data*/
        com_rslt +=  bmi160_read_fifo_header_data(BMI160_SEC_IF_BMM150, &header_data);

    break;

I can translate most of the changing the gyro and accel settings no problem but not sure about the interrupt watermarks and the read fifo header data translation. Any help would be appreciated.

Thanks Mike

hanyazou commented 7 years ago

Do you have an examples of using FIFO.

Here it is:

CurieIMU.setFIFOHeaderModeEnabled(true); CurieIMU.setAccelFIFOEnabled(false); CurieIMU.setGyroFIFOEnabled(true); CurieIMU.setGyroRate(100);

define BMI160_FIFO_TIME_EN_BIT 1

CurieIMU.reg_write_bits(BMI160_RA_FIFO_CONFIG_1, 0x1, BMI160_FIFO_TIME_EN_BIT, 1); CurieIMU.resetFIFO(); CurieIMU.attachInterrupt(bmi160_intr); CurieIMU.reg_write(BMI160_RA_FIFO_CONFIG_0, 0x1); // set FIFO water mark level

define BMI160_FWM_INT_BIT 6

CurieIMU.reg_write_bits(BMI160_RA_INT_EN_1, 0x1, BMI160_FWM_INT_BIT, 1);

NOTE: You must alter the BMI160.h to access reg_write() and reg_write_bits().

not sure about the interrupt watermarks and the read fifo header data translation.

Did you read the data sheet? (http://www.mouser.com/ds/2/783/BST-BMI160-DS000-07-786474.pdf) "2.6.12FIFOInterrupts" describes the watermark and "2.5.1FIFO Frames" explains how you can translate the header.

mjs513 commented 7 years ago

Thank you for getting back to me so quickly. I have been going the BMI api from bostec and datasheet in detail since last night. The biggest challengs seems to be reading the frames. In the process now of incorporating the code. I didn't see a burst read function specifically in the bmi160.cpp file, I did see a fifo read bytes function though - have to check to see if that is the same thing.

By the way, nice approach on the writing the library, using the same approach as Jeff Rowberg did for his MPU6050 library. Been using that myself for years in my version of the FreeIMU library. Will keep you posted on it goes if you are interested.

hanyazou commented 7 years ago

Will keep you posted on it goes if you are interested.

https://github.com/mjs513/FreeIMU-Updates looks nice. I will check a bit later!

The biggest challengs seems to be reading the frames.

This did work:

void bmi160_intr(void) { int fifo_cnt; uint8_t data[1024];

fifo_cnt = CurieIMU.getFIFOCount(); fifo_cnt += 4; CurieIMU.getFIFOBytes(data, fifo_cnt); // show_fifo_frames(data, fifo_cnt); }

void setup() { // initialize device CurieIMU.begin(); CurieIMU.setFIFOHeaderModeEnabled(true); CurieIMU.setAccelFIFOEnabled(false); CurieIMU.setGyroFIFOEnabled(true); //CurieIMU.setGyroRate(25); CurieIMU.setGyroRate(1600);

define BMI160_FIFO_TIME_EN_BIT 1

CurieIMU.reg_write_bits(BMI160_RA_FIFO_CONFIG_1, 0x1, BMI160_FIFO_TIME_EN_BIT, 1); CurieIMU.resetFIFO(); CurieIMU.attachInterrupt(bmi160_intr); CurieIMU.reg_write(BMI160_RA_FIFO_CONFIG_0, 0x1); // set FIFO water mark level

define BMI160_FWM_INT_BIT 6

CurieIMU.reg_write_bits(BMI160_RA_INT_EN_1, 0x1, BMI160_FWM_INT_BIT, 1); }

void loop() { delay(1000); }

mjs513 commented 7 years ago

Thanks for the compliment - seems to be never ending maintaining it. Just got it to work with wifi - which was fun.

Just tried the code and it compiled fine on the Arduino 101 board but nothing seems to be coming out: this is what I changed the code to (not sure if its my showfifo routine that is off or something else

#include "CurieIMU.h"
  int fifo_cnt;
  uint8_t data[1024];

void bmi160_intr(void)
{
  fifo_cnt = CurieIMU.getFIFOCount();
  fifo_cnt += 4;
  CurieIMU.getFIFOBytes(data, fifo_cnt);
  show_fifo_frames();
}

void show_fifo_frames(){
  Serial.println(fifo_cnt);
  for(int i = 0; i < fifo_cnt; i++){
    Serial.println(data[i], HEX);
  }

}

void setup() {
  // initialize device
  Serial.begin(9600);
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  CurieIMU.begin();

  // verify connection
  Serial.println("Testing device connections...");
  if (CurieIMU.begin()) {
    Serial.println("CurieIMU connection successful");
  } else {
    Serial.println("CurieIMU connection failed");
  }

  CurieIMU.setFIFOHeaderModeEnabled(true);
  CurieIMU.setAccelFIFOEnabled(false);
  CurieIMU.setGyroFIFOEnabled(true);
  //CurieIMU.setGyroRate(25);
  CurieIMU.setGyroRate(1600);
  #define BMI160_FIFO_TIME_EN_BIT 1
  CurieIMU.reg_write_bits(BMI160_RA_FIFO_CONFIG_1, 0x1, BMI160_FIFO_TIME_EN_BIT, 1);
  CurieIMU.resetFIFO();
  CurieIMU.attachInterrupt(bmi160_intr);
  CurieIMU.reg_write(BMI160_RA_FIFO_CONFIG_0, 0x1); // set FIFO water mark level
  #define BMI160_FWM_INT_BIT 6
  CurieIMU.reg_write_bits(BMI160_RA_INT_EN_1, 0x1, BMI160_FWM_INT_BIT, 1);
}

void loop() {
  delay(1000);
}
mjs513 commented 7 years ago

Been playing around with the code and registers and it does not seem like a interrupt is being generated. Going to keep playing.

Update: ok. I used Serial.println(CurieIMU.reg_read(0x1D), HEX); to see if the interrupt is tripped or not. Starts out as 0 the goes to 1. So I think that part works.

hanyazou commented 7 years ago

Did you check this fix? https://github.com/hanyazou/BMI160-Arduino/commit/ebf4924c8a5594ec4fd3cbbcc6ed0d44eaa4004f

mjs513 commented 7 years ago

No. Didn't see it. Going to check the fix. Not sure if this is going to work. I am using the Arduiono 101 board while the library is geared to a separate board. The interrupts my be handled differently. Just ordered a BMI160 breakout board. Won't be here for a week or so to test.

mjs513 commented 7 years ago

Oh. One more question if you don't mind. When we enable the fifo is that headerless or with header (control frames too)?

hanyazou commented 7 years ago

No. Didn't see it.

UPDATE: My log says that the interrupt handling worked without the mod on my 101 board. So you don't need that.

the fifo is that headerless or with header (control frames too)?

You can chose that calling "CurieIMU.setFIFOHeaderModeEnabled(true);".

mjs513 commented 7 years ago

Success at last (99%). Changed one line and did a few thing to code base and got the fifo data. Interesting thing though is with the gx and gy values, ever other dump is -32768, see below:

a/g: -87 49 16345 -1 -2 2 a/g: -87 49 16345 -32768 -32768 2 a/g: 152 52 16466 4 2 0 a/g: 152 52 16466 -32768 -32768 0 a/g: 64 26 16326 2 -3 -2 a/g: 64 26 16326 -32768 -32768 -2 a/g: 55 -48 16282 2 1 -1 a/g: 55 -48 16282 -32768 -32768 -1 a/g: 71 -23 16443 6 1 2

If I do a show data it works (guess its the added delay):

a/g: 11 39 16402 -3 0 -1 253, 255, 0, 0, 255, 255, 11, 0, 39, 0, 18, 64, 252, 255, 252, 255, .................. a/g: -26 96 16300 -2 -5 -2 254, 255, 251, 255, 254, 255, 230, 255, 96, 0, 172, 63, 251, 255, ................... a/g: 108 -11 16370 -1 3 0 255, 255, 3, 0, 0, 0, 108, 0, 245, 255, 242, 63, 253, 255, 254, ....................... a/g: -30 -5 16339 -3 -6 3 253, 255, 250, 255, 3, 0, 226, 255, 251, 255, 211, 63, 1, 0, 255, 255, ................

Here is a copy of the code I put together:

#include "CurieIMU.h"
#include "BMI160.h"

  int fifo_cnt;
  uint8_t data[1024];
  int16_t ax, ay, az;         // accelerometer values
  int16_t gx, gy, gz;         // gyrometer values

void bmi160_intr(void)
{
  fifo_cnt = CurieIMU.getFIFOCount();
  fifo_cnt += 4;
  CurieIMU.getFIFOBytes(data, fifo_cnt);
  gx = (((int16_t)data[1])  << 8) | data[0];
  ax = (((int16_t)data[7])  << 8) | data[6];

  gy = (((int16_t)data[3])  << 8) | data[2];
  ay = (((int16_t)data[9])  << 8) | data[8];

  gz = (((int16_t)data[5])  << 8) | data[4];
  az = (((int16_t)data[11])  << 8) | data[10];
  // display tab-separated accel/gyro x/y/z values
  Serial.print("a/g:\t");
  Serial.print(ax);
  Serial.print("\t");
  Serial.print(ay);
  Serial.print("\t");
  Serial.print(az);
  Serial.print("\t");
  Serial.print(gx);
  Serial.print("\t");
  Serial.print(gy);
  Serial.print("\t");
  Serial.println(gz);
  show_fifo_frames();
}

void show_fifo_frames(){
  //Serial.println(fifo_cnt);
  for(int i = 0; i < fifo_cnt; i++){
    Serial.print(data[i]); Serial.print(", ");
  }
  Serial.println("----------------------");
}

void setup() {
// initialize device
  Serial.begin(9600); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  CurieIMU.begin();

  // verify connection
  Serial.println("Testing device connections...");
  if (CurieIMU.begin()) {
    Serial.println("CurieIMU connection successful");
  } else {
    Serial.println("CurieIMU connection failed");
  }

  //CurieIMU.setGyroRate(25);
  CurieIMU.setAccelerometerRange(2);
  CurieIMU.setAccelRate(BMI160_ACCEL_RATE_1600HZ);
  CurieIMU.setGyroRange(250);
  CurieIMU.setGyroRate(BMI160_GYRO_RATE_1600HZ);

    Serial.println("About to calibrate. Make sure your board is stable and upright");
    delay(5000);

    // The board must be resting in a horizontal position for
    // the following calibration procedure to work correctly!
    Serial.print("Starting Gyroscope calibration and enabling offset compensation...");
    CurieIMU.autoCalibrateGyroOffset();
    Serial.println(" Done");

    Serial.print("Starting Acceleration calibration and enabling offset compensation...");
    CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0);
    CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
    CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);
    Serial.println(" Done");

    Serial.println("Internal sensor offsets AFTER calibration...");
    Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS));
    Serial.print("\t"); // -76
    Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS));
    Serial.print("\t"); // -2359
    Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS));
    Serial.print("\t"); // 1688
    Serial.print(CurieIMU.getGyroOffset(X_AXIS));
    Serial.print("\t"); // 0
    Serial.print(CurieIMU.getGyroOffset(Y_AXIS));
    Serial.print("\t"); // 0
    Serial.println(CurieIMU.getGyroOffset(Z_AXIS));

  CurieIMU.setFIFOHeaderModeEnabled(false);
  CurieIMU.setAccelFIFOEnabled(true);
  CurieIMU.setGyroFIFOEnabled(true);

  #define BMI160_FIFO_TIME_EN_BIT 1
  CurieIMU.reg_write_bits(BMI160_RA_FIFO_CONFIG_1, 0x1, BMI160_FIFO_TIME_EN_BIT, 1);
  CurieIMU.resetFIFO();
  CurieIMU.attachInterrupt(bmi160_intr);
  CurieIMU.reg_write(BMI160_RA_FIFO_CONFIG_0, 0b00000101); // set FIFO water mark level
  #define BMI160_FWM_INT_BIT 6
  CurieIMU.reg_write_bits(BMI160_RA_INT_EN_1, 0x1, BMI160_FWM_INT_BIT, 1);

  CurieIMU.resetFIFO();

  Serial.println(CurieIMU.reg_read(BMI160_RA_FIFO_CONFIG_0), BIN);
  Serial.println(CurieIMU.reg_read(BMI160_RA_FIFO_CONFIG_1), BIN);
  Serial.println(CurieIMU.reg_read(BMI160_RA_INT_EN_1),BIN);

}

void loop() {

  delay(1);
}
mjs513 commented 7 years ago

Just an update. got everything working by using the second set of data. Believe this is the only line changed: CurieIMU.reg_write(BMI160_RA_FIFO_CONFIG_0, 0b00001010); // set FIFO water mark level

By the way do you mind me posting this to the arduino101 board forum or would you prefer to do it. It might help someone else.

update: Incorporated the routine into the CurieIMU MadwickAHRS and I am celebrating. It worked. But the visualizer is off.

hanyazou commented 7 years ago

Congratulations.

By the way do you mind me posting this to the arduino101 board forum or would you prefer to do it. It might help someone else.

I don't mind. Go ahead.

mjs513 commented 7 years ago

Thanks again taking the time to work on this. Here's the post on the forum page. https://forum.arduino.cc/index.php?topic=462729.0