Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Stream Accelerometer and Gyroscope date to the Arduino Serial terminal
#include "Arduino.h"
#include "SPI.h"
#include "Wire.h"
#include "bmi270.h"
#define BMI270_CS SS
#define BMI270_INT1 6
/* Callback function prototypes for the BMI270 Sensor API */
int8_t bmi2_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
int8_t bmi2_spi_write(uint8_t dev_id, uint8_t reg_addr, const uint8_t *data, uint16_t len);
int8_t bmi2_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
int8_t bmi2_i2c_write(uint8_t dev_id, uint8_t reg_addr, const uint8_t *data, uint16_t len);
void bmi2_delay_us(uint32_t period);
/* Other functions */
void panic_led_trap(void);
int8_t configure_sensor(struct bmi2_dev *dev);
void bmi2_intr1_callback(void);
void print_rslt(int8_t rslt);
/* Static variables */
static struct bmi2_dev bmi2;
static volatile bool bmi2_intr_recvd = false;
static volatile uint32_t last_time_us = 0;
void setup(void)
{
int8_t rslt;
Serial.begin(115200);
while (!Serial.available()); // Wait for an input to proceed
pinMode(LED_BUILTIN, OUTPUT);
/* Use either the SPI or I2C configuration */
// /* Start of SPI configuration */
// SPI.begin();
// pinMode(BMI270_CS, OUTPUT);
// digitalWrite(BMI270_CS, LOW);
// delay(1);
// digitalWrite(BMI270_CS, HIGH); // Toggle the chip select to switch into SPI mode
// delay(10);
//
// bmi2.dev_id = BMI270_CS;
// bmi2.read = bmi2_spi_read;
// bmi2.write = bmi2_spi_write;
// bmi2.delay_us = bmi2_delay_us;
// bmi2.intf = BMI2_SPI_INTERFACE;
// bmi2.read_write_len = 8192;
// bmi2.config_file_ptr = NULL; // Use the default BMI270 config file
// /* End of SPI configuration */
/* Start of I2C configuration */
// pinMode(PIN_SPI_MISO, OUTPUT);
// digitalWrite(PIN_SPI_MISO, LOW); // Expected state of the SDO line
// pinMode(BMI270_CS, OUTPUT);
// digitalWrite(BMI270_CS, HIGH); // Expected state of the CS line
Wire.begin();
bmi2.dev_id = BMI2_I2C_PRIM_ADDR;
bmi2.read = bmi2_i2c_read;
bmi2.write = bmi2_i2c_write;
bmi2.delay_us = bmi2_delay_us;
bmi2.intf = BMI2_I2C_INTERFACE;
bmi2.read_write_len = 30; // Limitation of the Wire library
bmi2.config_file_ptr = NULL; // Use the default BMI270 config file
/* End of I2C configuration */
rslt = bmi270_init(&bmi2);
print_rslt(rslt);
attachInterrupt(BMI270_INT1, bmi2_intr1_callback, RISING);
rslt = configure_sensor(&bmi2);
print_rslt(rslt);
}
void loop(void)
{
if (bmi2_intr_recvd)
{
bmi2_intr_recvd = false;
digitalWrite(LED_BUILTIN, LOW); // Flash the LED to show activity
struct bmi2_sensor_data sensor_data[2] = { { .type = BMI2_ACCEL }, { .type = BMI2_GYRO } };
int8_t rslt = bmi2_get_sensor_data(sensor_data, 2, &bmi2);
print_rslt(rslt);
Serial.print(last_time_us); // Comment out this line if using the Serial plotter
Serial.print(","); // Comment out this line if using the Serial plotter
Serial.print(sensor_data[0].sens_data.acc.x);
Serial.print(",");
Serial.print(sensor_data[0].sens_data.acc.y);
Serial.print(",");
Serial.print(sensor_data[0].sens_data.acc.z);
Serial.print(",");
Serial.print(sensor_data[1].sens_data.gyr.x);
Serial.print(",");
Serial.print(sensor_data[1].sens_data.gyr.y);
Serial.print(",");
Serial.print(sensor_data[1].sens_data.gyr.z);
Serial.println();
digitalWrite(LED_BUILTIN, HIGH);
}
}
int8_t configure_sensor(struct bmi2_dev *dev)
{
int8_t rslt;
uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_GYRO };
struct bmi2_int_pin_config int_pin_cfg;
int_pin_cfg.pin_type = BMI2_INT1;
int_pin_cfg.int_latch = BMI2_INT_NON_LATCH;
int_pin_cfg.pin_cfg[0].lvl = BMI2_INT_ACTIVE_HIGH;
int_pin_cfg.pin_cfg[0].od = BMI2_INT_PUSH_PULL;
int_pin_cfg.pin_cfg[0].output_en = BMI2_INT_OUTPUT_ENABLE;
int_pin_cfg.pin_cfg[0].input_en = BMI2_INT_INPUT_DISABLE;
struct bmi2_sens_config sens_cfg[2];
sens_cfg[0].type = BMI2_ACCEL;
sens_cfg[0].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2;
sens_cfg[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ;
sens_cfg[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE,
sens_cfg[0].cfg.acc.range = BMI2_ACC_RANGE_4G;
sens_cfg[1].type = BMI2_GYRO;
sens_cfg[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE;
sens_cfg[1].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE;
sens_cfg[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
sens_cfg[1].cfg.gyr.range = BMI2_GYR_RANGE_2000;
sens_cfg[1].cfg.gyr.ois_range = BMI2_GYR_OIS_2000;
rslt = bmi2_set_int_pin_config(&int_pin_cfg, dev);
if (rslt != BMI2_OK)
return rslt;
rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, dev);
if (rslt != BMI2_OK)
return rslt;
rslt = bmi2_set_sensor_config(sens_cfg, 2, dev);
if (rslt != BMI2_OK)
return rslt;
rslt = bmi2_sensor_enable(sens_list, 2, dev);
if (rslt != BMI2_OK)
return rslt;
return rslt;
}
int8_t bmi2_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if ((data == NULL) || (len == 0))
return -1;
digitalWrite(dev_id, LOW);
SPI.transfer(reg_addr);
for (uint16_t i = 0; i < len; i++)
{
data[i] = SPI.transfer(0xff);
}
digitalWrite(dev_id, HIGH);
return 0;
}
int8_t bmi2_spi_write(uint8_t dev_id, uint8_t reg_addr, const uint8_t *data, uint16_t len)
{
if ((data == NULL) || (len == 0))
return -1;
digitalWrite(dev_id, LOW);
SPI.transfer(reg_addr);
for (uint16_t i = 0; i < len; i++)
SPI.transfer(data[i]);
digitalWrite(dev_id, HIGH);
return 0;
}
int8_t bmi2_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if ((data == NULL) || (len == 0) || (len > 32)) {
return -1;
}
uint8_t bytes_received;
Wire.beginTransmission(dev_id);
Wire.write(reg_addr);
if (Wire.endTransmission() == 0) {
bytes_received = Wire.requestFrom(dev_id, len);
// Optionally, throw an error if bytes_received != len
for (uint16_t i = 0; i < bytes_received; i++)
{
data[i] = Wire.read();
}
} else {
return -1;
}
return 0;
}
int8_t bmi2_i2c_write(uint8_t dev_id, uint8_t reg_addr, const uint8_t *data, uint16_t len)
{
if ((data == NULL) || (len == 0) || (len > 32)) {
return -1;
}
Wire.beginTransmission(dev_id);
Wire.write(reg_addr);
for (uint16_t i = 0; i < len; i++)
{
Wire.write(data[i]);
}
if (Wire.endTransmission() != 0) {
return -1;
}
return 0;
}
void bmi2_delay_us(uint32_t period)
{
delayMicroseconds(period);
}
void bmi2_intr1_callback(void)
{
bmi2_intr_recvd = true;
last_time_us = micros();
}
void panic_led_trap(void)
{
while (1)
{
digitalWrite(LED_BUILTIN, LOW);
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
}
}
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK: return; /* Do nothing */ break;
case BMI2_E_NULL_PTR:
Serial.println("Error [" + String(rslt) + "] : Null pointer");
panic_led_trap();
break;
case BMI2_E_COM_FAIL:
Serial.println("Error [" + String(rslt) + "] : Communication failure");
panic_led_trap();
break;
case BMI2_E_DEV_NOT_FOUND:
Serial.println("Error [" + String(rslt) + "] : Device not found");
panic_led_trap();
break;
case BMI2_E_OUT_OF_RANGE:
Serial.println("Error [" + String(rslt) + "] : Out of range");
panic_led_trap();
break;
case BMI2_E_ACC_INVALID_CFG:
Serial.println("Error [" + String(rslt) + "] : Invalid accel configuration");
panic_led_trap();
break;
case BMI2_E_GYRO_INVALID_CFG:
Serial.println("Error [" + String(rslt) + "] : Invalid gyro configuration");
panic_led_trap();
break;
case BMI2_E_ACC_GYR_INVALID_CFG:
Serial.println("Error [" + String(rslt) + "] : Invalid accel/gyro configuration");
panic_led_trap();
break;
case BMI2_E_INVALID_SENSOR:
Serial.println("Error [" + String(rslt) + "] : Invalid sensor");
panic_led_trap();
break;
case BMI2_E_CONFIG_LOAD:
Serial.println("Error [" + String(rslt) + "] : Configuration loading error");
panic_led_trap();
break;
case BMI2_E_INVALID_PAGE:
Serial.println("Error [" + String(rslt) + "] : Invalid page ");
panic_led_trap();
break;
case BMI2_E_INVALID_FEAT_BIT:
Serial.println("Error [" + String(rslt) + "] : Invalid feature bit");
panic_led_trap();
break;
case BMI2_E_INVALID_INT_PIN:
Serial.println("Error [" + String(rslt) + "] : Invalid interrupt pin");
panic_led_trap();
break;
case BMI2_E_SET_APS_FAIL:
Serial.println("Error [" + String(rslt) + "] : Setting advanced power mode failed");
panic_led_trap();
break;
case BMI2_E_AUX_INVALID_CFG:
Serial.println("Error [" + String(rslt) + "] : Invalid auxilliary configuration");
panic_led_trap();
break;
case BMI2_E_AUX_BUSY:
Serial.println("Error [" + String(rslt) + "] : Auxilliary busy");
panic_led_trap();
break;
case BMI2_E_SELF_TEST_FAIL:
Serial.println("Error [" + String(rslt) + "] : Self test failed");
panic_led_trap();
break;
case BMI2_E_REMAP_ERROR:
Serial.println("Error [" + String(rslt) + "] : Remapping error");
panic_led_trap();
break;
case BMI2_E_GYR_USER_GAIN_UPD_FAIL:
Serial.println("Error [" + String(rslt) + "] : Gyro user gain update failed");
panic_led_trap();
break;
case BMI2_E_SELF_TEST_NOT_DONE:
Serial.println("Error [" + String(rslt) + "] : Self test not done");
panic_led_trap();
break;
case BMI2_E_INVALID_INPUT:
Serial.println("Error [" + String(rslt) + "] : Invalid input");
panic_led_trap();
break;
case BMI2_E_INVALID_STATUS:
Serial.println("Error [" + String(rslt) + "] : Invalid status");
panic_led_trap();
break;
case BMI2_E_CRT_ERROR:
Serial.println("Error [" + String(rslt) + "] : CRT error");
panic_led_trap();
break;
case BMI2_E_ST_ALREADY_RUNNING:
Serial.println("Error [" + String(rslt) + "] : Self test already running");
panic_led_trap();
break;
case BMI2_E_CRT_READY_FOR_DL_FAIL_ABORT:
Serial.println("Error [" + String(rslt) + "] : CRT ready for DL fail abort");
panic_led_trap();
break;
case BMI2_E_DL_ERROR:
Serial.println("Error [" + String(rslt) + "] : DL error");
panic_led_trap();
break;
case BMI2_E_PRECON_ERROR:
Serial.println("Error [" + String(rslt) + "] : PRECON error");
panic_led_trap();
break;
case BMI2_E_ABORT_ERROR:
Serial.println("Error [" + String(rslt) + "] : Abort error");
panic_led_trap();
break;
case BMI2_E_GYRO_SELF_TEST_ERROR:
Serial.println("Error [" + String(rslt) + "] : Gyro self test error");
panic_led_trap();
break;
case BMI2_E_GYRO_SELF_TEST_TIMEOUT:
Serial.println("Error [" + String(rslt) + "] : Gyro self test timeout");
panic_led_trap();
break;
case BMI2_E_WRITE_CYCLE_ONGOING:
Serial.println("Error [" + String(rslt) + "] : Write cycle ongoing");
panic_led_trap();
break;
case BMI2_E_WRITE_CYCLE_TIMEOUT:
Serial.println("Error [" + String(rslt) + "] : Write cycle timeout");
panic_led_trap();
break;
case BMI2_E_ST_NOT_RUNING:
Serial.println("Error [" + String(rslt) + "] : Self test not running");
panic_led_trap();
break;
case BMI2_E_DATA_RDY_INT_FAILED:
Serial.println("Error [" + String(rslt) + "] : Data ready interrupt failed");
panic_led_trap();
break;
case BMI2_E_INVALID_FOC_POSITION:
Serial.println("Error [" + String(rslt) + "] : Invalid FOC position");
panic_led_trap();
break;
default:
Serial.println("Error [" + String(rslt) + "] : Unknown error code");
panic_led_trap();
break;
}
}
@Cam973

This comment has been minimized.

Copy link

@Cam973 Cam973 commented Feb 26, 2020

Hi,
So I am trying to run this code with the BMI270 shuttle board and upon compiling there is an error saying that the global variables are taking up 427% of dynamic memory. I was wondering if there was any way to fix this, I am writing onto an arduino uno with ATmega328p.

Any help would be much appreciated
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment