Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    Sort by:
    100% helpful (1/1)
    ‎08-06-2019 10:43 AM
     FIFO description The BMI160 integrates a 1024-bytes data FIFO. The FIFO contains frames of data, and each frame contains only one sample per sensor. Each sensor element can be enabled for the FIFO individually. The data frames can be configured into different formats as shown in Figure 1. If each sensor is with different ODRs, then each frame contains samples from different subsets of sensors which are enabled for the FIFO. In that case, the size of frames is not constant.                                                                        Figure 1: FIFO frame configuration The maximum number of frames in the FIFO is determined by different configurations. Assuming that all the sensors are with the same ODR, the following table demonstrates the maximum frames of sensor data can be stored in the FIFO for different frame format modes:                                                                  Table 1: Maximum number of frames in FIFO  The FIFO operates in a mode that collects data constantly. When the FIFO buffer is full, the data collection continues and the oldest entry is discarded. For the example in Figure 2, at the moment Time0, FIFO buffer has room for 9 bytes. So the next frame that contains 13 bytes does not fit in the FIFO. Therefore, at Time1, the oldest frame Frame[0] in FIFO[0…6] is discarded, the remaining frames are shifted down and the new frame Frames[84] is pushed into FIFO[1008…1020]. At Time2, when the new frame is ready, the oldest frame continues to be discarded.                                            Figure 2: FIFO full representation, the Oldest Frames are discarded  When data is being read, data collection continues. An example is shown in Figure 3. At Time0, the new frame Frame[19] is pushed into FIFO and the watermark interrupt is triggered. Then after some delay, the interrupt is serviced and a burst read of FIFO begins. In order to read out all the valid data in FIFO and generate a timestamp in Header mode, the length of the burst read is set to the watermark level plus two maximum-sized frames plus four bytes. At Time2, as the burst read takes longer than the sensor data is generated, a new frame Frame[20] is added into FIFO. At Time3, all the valid data including Frame[20] is read out and a Sensortime frame is returned.   The example below describes the steps of FIFO setting and FIFO data retrieval. After sensor configuration, Accel and Gyro are set to Normal mode. Then FIFO is configured to store Accel and Gyro data in Header mode. By burst reading FIFO data Register 0x24, data is read from FIFO every 50ms.                                 Figure 4: Steps to enable FIFO and retrieve FIFO data every 50ms FIFO register In the following table, the most important registers for FIFO configuration and usage (as excerpt of the full register map in Datasheet Section 2.11) are shown.                                           Table 2: Important registers for FIFO usage FIFO configuration registers (0x46-0x47) FIFO configuration registers can be used to: read or set the current FIFO watermark level set different modes of operation of the FIFO, i.e. which data will be stored in it and which format will be used (header or headerless mode).  fifo_water_mark fifo_water_mark defines the FIFO watermark level. An interrupt will be generated when the number of entries in the FIFO exceeds fifo_water_mark. Note: The unit of fifo_water_mark is 4 bytes. fifo_acc_en,fifo_gyr_en,fifo_mag_en fifo_xxx(acc, gyr, mag)_en defines if the xxx data is stored in FIFO. If fifo_xxx_en = 0, no data is stored in FIFO; if fifo_xxx_en = 1, xxx data is stored in FIFO (for all three axes). When all fifo_xxx_en are ‘0’, the FIFO is disabled, no sensor data is stored in FIFO and no headers are written.  fifo_header_en fifo_header_en defines the FIFO frame mode as discussed in Chapter 4. If fifo_header_en = 1, FIFO is in Header mode, each frame contains a header and data; If fifo_header_en = 0, FIFO is in Headerless mode, each frame contains data only. For Header mode, the output data rates of all enabled sensors for the FIFO can be different. However, for Headerless mode, the output data rates of all enabled sensors for the FIFO should be identical. If the output data rates are different in Headerless mode, the FIFO waits until the data with the lowest output data rate is ready and then stores the frame as shown in Figure 5.                        Figure 5: FIFO frame modes behave differently with not identical ODR for sensors For example, when Accel is set to 100Hz and Gyro is set to 200Hz, the frame of data is generated at 200Hz in Header mode and at 100Hz in Headerless mode. For further discussion about FIFO frame modes, see Chapter 4. fifo_tag_int1_en, fifo_tag_int2_en fifo_tag_int1_en and fifo_tag_int2_en define if the FIFO tags the voltage on interrupt pin 1 or 2 in the FIFO header. To enable this function, int1_input_en and/or int2_input_en should be set to ‘1’ in Register (0x54) INT_LATCH. fifo_time_en fifo_time_en defines if sensortime frame in FIFO is enabled. When fifo_time_en = 0, no sensortime frame will be returned. When fifo_time_en = 1, a sensortime frame will be returned after the last valid frame when the number of data that are read is greater than that of valid frames in the FIFO. When reading from FIFO with burst read, the AP/MCU should read more than the bytes (FIFO byte counter + 4 bytes). These four bytes contain one frame header that indicates the Sensortime frame and 3 bytes for the real sensor time.    FIFO data register (0x24) When reading out data from FIFO, read burst access must be used. The address does not increment when the read burst reads at the address of FIFO_DATA. When a frame is only partially read out, it is retransmitted including the header at the next readout. The data format depends on the setting of FIFO Configuration Registers (0x46-0x47). The FIFO data is organized by frame, as described in Chapter 4. FIFO length registers (0x22-0x23) FIFO length registers contain a FIFO byte counter. It represents the current fill level of the FIFO buffer. This includes the Skip frame for a full FIFO. An empty FIFO corresponds to 0x000. The byte counter can be reset by reading out all frames from the FIFO buffer or when the FIFO is reset through the Register (0x7E) CMD. The byte counter is updated when a complete frame is read or written.  FIFO downsampling register (0x45) The register (0x45) FIFO_DOWN provides xxx_fifo_filt_data and xxx_fifo_downs. Using these bits, the data stored in FIFO is downsampled compared to the ODR settings. If xxx_fifo_filt_data = 0, unfiltered data will be selected as the data source for FIFO downsampling(1600Hz for Accel and 6400Hz for gyro). If xxx_fifo_filt_data = 1, filtered data will be used as the data source for FIFO downsampling. This is identical to the ODR setting. Then the data stored in FIFO is related to the ODR and xxx_fifo_downs. For example, xxx_fifo_downs = 2, then every 4 samples output from data registers (updated based on ODR settings) will be stored in FIFO.  FIFO interrupt The FIFO full interrupt and the watermark interrupt can be enabled/disabled through the Register (0x51) INT_EN_1 and can be mapped/unmapped to interrupt pin 1 or 2 through the Register (0x56) INT_MAP_1. Detailed information can be found in BMI160 Datasheet. When FIFO is full, the FIFO full interrupt is issued and the next full data sample will cause FIFO overflow, which may cause samples to be deleted. Technically, this means that the FIFO full interrupt is issued whenever the remaining space in the FIFO is less than two maximum-sized frames. The FIFO watermark interrupt is fired when the FIFO fill level in fifo_byte_counter in Register (0x22-0x23) FIFO_LENGTH is above the pre-configured watermark defined in fifo_watermark in Register (0x46-0x47) FIFO_CONFIG. FIFO flush function In order to empty the FIFO content, the user should write the command word 0xB0 into the command register 0x7E. Note: This action only clears the data content of FIFO and it does not change any FIFO configuration. FIFO related error code In the Error register, there are two FIFO related error code fields as follows: 0x0110: ODRs of enabled sensors in headless mode do not match, which means when headless mode is enabled for more than one sensor, these sensors are not set to the same ODR. 0x0111: unfiltered data is used in low power mode, which means in low power mode, only filtered data can be selected to fill FIFO. Because there is no real unfiltered data in low power mode, the sensor only gets the data based on the defined time interval. FIFO frame The BMI160 provides two different modes: headerless mode and header mode, as described in Chapter 3.They are detailed in following chapters. Header mode When FIFO is set to “header mode“, the data byte format differs depending on the type of frame. There are two basic frame types, i.e. control frame and regular data frame. Each different type of control frame has its own data byte format. It can contain skipped frames, sensortime data or FIFO configuration information, as described in BMI160 Datasheet. If the frame type is a regular frame (sensor data), the data byte section of the frame depends on how the data is being transmitted in this frame (as specified in the header byte section). It can include data from a single sensor or any combination of accelerometer, gyroscope and external sensor data. The following formula calculates the average size of the frame in Header mode: Frame_Size AVG = (Max(A odr ,G odr ,M odr )*1+6*A odr +6*G odr +8*M odr )/Max(A odr ,G odr ,M odr ) byte (1) The data stored in FIFO uses the following format in header mode:                                                    Table 3: Parts of FIFO data format in header mode Note: The above regular frame header contains the tags of interrupts in the last two bits fh_ext<1:0>. When fifo_tag_int1_en or fifo_tag_int2_en is enabled, the regular frame header may change. Take Accel only as an example, fifo_tag_int1_en and int1_input_en are enabled. If the Accel data is stored in FIFO while the interrupt pin 1 is high, the regular frame header is 0x85 instead of 0x84. There are other FIFO frame headers: 0x48: CFG frame, which indicates the range or other configuration changes of A, G and M during FIFO storing. 0x40: Skip frame, which indicates how many frames are skipped when FIFO is full. If more than 255 frames are skipped, 255 is returned as the number of skipped frames. 0x44: Sensortime frame. The data byte part of a Sensortime frame consists of 3 bytes and contains a 24-bit sensortime. The Sensortime frame does not consume memory in FIFO. 0x80: Overread frame. The data byte part of an Overread frame consists of a redundant byte 0x00. Detailed information on FIFO frame header format can be found in BMI160 Datasheet.    Example: how data stores in FIFO in Header mode Write 0x11, 0x15 into CMD register 0x7E in sequence to set A, G into normal power mode. Write 0x28 into register ACC_CONF (0x40) to set acceleration data rate to 100Hz. Write 0x29 into register GYR_CONF (0x42) to set gyro data rate to 200Hz. Enable and configure M via secondary interface according to AN First steps with the BMI160, set the magnetic data rate to 50Hz. Write 0xF2 into register FIFO_CONFIG_1 (0x47) to enable A, G and M data stored in FIFO. Also enable the header and timestamp for the FIFO. Then FIFO works and stores data in the following format: Table 4: FIFO data in header mode  Headerless mode When the FIFO is set to headerless mode, only sensor data is stored in the FIFO (in the same order as in the data register). Any combination of accelerometer, gyroscope and external sensor data can be stored. External interrupt tags are not supported in headerless mode. After the configuration is complete, the frame size in headerless mode is constant. The data stored in the FIFO uses the following formats in headerless mode:                                            Table 5: FIFO data formats in headerless mode  Note: When overread occurs, a byte stream of 0x0080 (which corresponds to (LSB, MSB) byte order to a data value of 0x8000) is returned in headerless mode. Example: How data stores in FIFO in Headerless mode Write 0x11, 0x15 to CMD register 0x7E in sequence to set A, G to normal power mode. Write 0x28 to register ACC_CONF (0x40) to set the acceleration data rate to 100Hz. Write 0x28 to register GYR_CONF (0x42) to set the gyro data rate to 100Hz. Enable and configure M via the secondary interface according to the application note “BMI160 Secondary Interface: Magnetometer”, and set the magnetic data rate to 100Hz. Write 0xE0 into register FIFO_CONFIG_1 (0x47) to enable A, G and M data stored in FIFO, and disable the header and timestamp for the FIFO. Then the FIFO works and stores data in the following format:                                                                 Table 6: FIFO data in headerless mode  Note: In Headerless mode, the output data rates of all enabled sensors for the FIFO should be identical. If the output data rates are different, the FIFO will wait until the data with the lowest output data rate is ready and then store the frame as described in Section 3.1.3.  Retrieving data from FIFO Communication speed and FIFO fill rate The communication speed determines the rate at which data can be read from the FIFO. To prevent data loss, fill the FIFO with a rate that does not exceed the read rate. The appropriate appropriate data rate of each sensor should be selected. For I2C protocol, a read sequence consists of a one-byte I2C write phase followed by the I2C read phase. Using the formula (1) in Section 4.1, the average frame size is approximately 13 bytes when A odr , G odr and M odr are 1600Hz, 1600Hz and 25 Hz correspondingly. The minimum time necessary for starting the burst read for I2C fast mode is roughly 75 µs. The minimum time to get the above-mentioned frame is roughly 360 µs, including all minimum start and stop setup and hold times and minimum cycle period. As a result, data can still be read out of the FIFO faster than it is put into the FIFO at the data rate of 1600 Hz, corresponding to a period of 625 µs. However, the theoretical maximum FIFO fill rate for the BMI160 FIFO can be calculated as follows: f FIFO_fill = Max(A odr ,G odr ,M odr ) * Frame_Size AVG = Max(A odr ,G odr ,M odr ) * 1+ 6 * A odr + 6 * G odr + 8 * M odr                                          (2) = 6400 + 6 * 1600 + 6 * 6400 + 8 * 800 = 60800 (bytes/second) = 486.4 kbit/s In this case, the maximum FIFO fill rate exceeds the speed of I2C fast mode. The data rates of the sensors can be adjusted for the I2C communication speed. On the other hand, SPI with higher speed can be used to meet the high FIFO fill rate requirement when all the sensors are with high output data rates. Watermark The watermark interrupt is triggered when the FIFO fill level in fifo_byte_counter in FIFO Length Registers (0x22-0x23) is above a pre-configured fifo_watermark in FIFO Configuration Registers (0x46-0x47) and it remains set until the condition causing it is eliminated. To clear the watermark interrupt, read the FIFO until the fill level in fifo_byte_counter is lower than the value stored in fifo_watermark; however, reading more than the valid frames in FIFO is recommended for two reasons: It prevents the watermark interrupt from being triggered too often, without compromising the benefit of using FIFO. A Sensortime frame is returned after the last valid frame when more data than valid frames in FIFO are read.    FIFO operation with watermark interrupt The example in Figure 6 shows how the FIFO operates with watermark interrupt. The pre-configured watermark is 220 bytes so that the unit of fifo_watermark is 4 bytes and is configured as 0x37. At Time0, the FIFO fill level in fifo_byte_counter is 218 bytes. At Time1, the FIFO fill level is updated to 239 bytes when Frame[19] is pushed into the FIFO. Then the FIFO watermark interrupt is fired. After some latency, the interrupt is serviced and a burst read that reads all the frames in the FIFO is issued. At Time2, the complete frame Frame[0] is read, fifo_byte_counter is updated but still above the watermark, so the FIFO watermark interrupt remains set. Until another complete frame Frame[1] is read at Time3, the updated fifo_byte_counter is below the watermark and the watermark interrupt is cleared.   Figure 6: Watermark Interrupt is cleared when FIFO Counter is below pre-configured watermark Watermark level and burst read length The watermark level (WM) can be calculated with the number of frames (F) that triggers a watermark interrupt: WM = F * Frame_Size AVG / 4                                                                                                     (3)        = F * (0.25+1.5*A odr / Max(A odr ,G odr ,M odr ) +1.5*G odr / Max(A odr ,G odr ,M odr ) +2*M odr / Max(A odr ,G odr ,M odr )) In order to read more data than the valid frames in FIFO, the minimum Burst Read Length can be roughly estimated with the calculated watermark level, FIFO fill rate, communication speed (Clock Rate), and the latency of serving watermark interrupt: Read_Length min = (WM*4 + f FIFO_fill * Latency fwm_int ) / (1 – f FIFO_fill / f CLK )                                      (4)   If I2C Fast mode is used and the maximum latency of serving watermark interrupt is 10 ms, the recommended burst read lengths for different sensor and watermark configurations are provided in Table 8.              Table 7: WM configuration and burst read length for different ORDs (I2C fast mode)   Note: New frames can be filled into FIFO during the latency for interrupt service and a long burst read. A high watermark level is not recommended if the sensors are set to high ODRs and the communication speed is not fast enough. Potential risk and possible solution There is a potential risk that watermark is triggered again shortly after it is cleared while the FIFO data is still being read. This may unintentionally call a false watermark interrupt service before the current watermark interrupt service is finished, and thus lead to a system crash. For the same communication speed, the higher the FIFO fill rate, the more likely the potential risk occurs. The risk is illustrated in Figure 7. At Time2, fifo_byte_counter is below the watermark level so the interrupt is cleared. However, at Time3, before the oldest frame Frame[2] is completely read out, the new frame Frame[20] is pushed into FIFO and an unwanted interrupt is triggered.                              Figure 7: Watermark Interrupt is triggered immediately after it is cleared One possible solution is to disable the watermark interrupt by setting bit 6 to ‘0’ in Register (0x51) INT_EN_1 at the beginning of the interrupt service and enable the watermark interrupt again before exiting the interrupt service.  Interrupt-based FIFO read example In the example below, the left hand side describes the steps of FIFO and watermark interrupt configuration for Accel 100 Hz, Gyro 100 Hz and Mag 25 Hz. Interrupt 1 of the BMI160 is set to output, and watermark interrupt is mapped to it. Then the watermark level is set to 148 bytes before the watermark interrupt is enabled. At the end of the configuration, FIFO is enabled for Accel, Gyro and Mag data, frame format is set to Header Mode and the Sensortime frame is enabled. The left hand side of the example below describes the steps of the watermark interrupt service. At the beginning of the service, the watermark interrupt is disabled to avoid the risk mentioned in Section 5.2.3. Then all the valid data frames and the Sensortime frame are read and interpreted. Before exiting the watermark interrupt service, the watermark interrupt must be enabled again.                                Figure 8: Watermark interrupt configuration and interrupt service  
    View full article
    ‎07-26-2019 09:30 AM
    Concept of auto-wakeup & auto-low power  Auto Wakeup As shown in the diagram, the wakeup function can generate an interrupt by detecting defined movement, while the auto-wakeup function can switch the BMA400 from low power mode to normal mode. During switching to normal mode, the sensor configurations defined in previous normal mode (before entering low power mode), like ODR, range, OSR, FIFO, interrupts, will be restored automatically. Therefore, the host only need to configure BMA400 once in initialization and no need to reconfigure the parameters after BMA400 enters normal mode by auto-wakeup function. The three possible triggers for wake-up from low-power mode are: by serial command by timeout by wake-up interrupt on activity The three conditions can be enabled in parallel. Please be notified that, the timeout wakeup can only switching BMA400 to normal mode if configured, and cannot be mapped to the interrupt pin(INT1 and INT2). Auto Low Power Except the serial command, there are three possible triggers can switch BMA400 to low-power automatically: by timeout by activity on Gen1(Gen1 interrupt will trigger the switching to low-power mode) by data ready (DRDY) The three conditions can be enabled in parallel. Also in timeout mode, the counter can be reset by interrupt from Gen2 interrupt. This can be used to enlarge the active time (in normal mode) of BMA400 if some activity is detected by Gen2. Relative registers  Use Cases In this section, several typical examples are presented with sample codes; you can modify them for your specific usage. Auto wakeup and Auto low power by timeout Case description In this case, both Auto wakeup & auto low power function are triggered by timeout. So after configuration and enabling, BMA400 will work in below sequence: Repeat:             Low power mode sampling (2.5ms ~ 10.24s)             Auto switches to normal mode by timeout             Normal mode sampling ((2.5ms ~ 10.24s))             Auto switches to low power mode by timeout  Parameters configure In this example, range = 2g, ODR=100Hz, Accel data source = filter1 Auto-lowpower relative Register(0x2A),Register(0x2B): auto_lp_timeout_thres = 400 (400 * 2.5ms = 1s), unsigned 12bit, timeout threshold, 2.5ms/lsb auto_lp_timeout: set to 1 here (enable), timeout as source for auto-low-power condition For mode auto_lp_timeout = 0x02, gen2 interrupt will reset the timeout counter, and this can be used to delay the auto-lowpower if some condition is fulfilled. For example, in watch/band, gen2 can be configured to detect the body movement, and only if no movement is detected, the timeout counter will be continued and after defined time, the sensor eventually goes into low power mode. Auto-wakeup relative wakeup_timeout_thres = 0x0FFF (max value, 0x0fff * 2.5ms = 10.24s) Register (0x2C) and (0x2D), unsigned 12bits, auto-wakeup timeout threshold, 2.5ms/lsb wkup_timeout: set to 1 (enable) Register (0x2D)  AUTOWAKEUP_1. wkup_timeout = 1; enable timerout triggering auto-wakeup  Sample codes #### BMA400 Auto wakeup and Auto low power features ##### _Usage of auto wakeup and auto low power features in sensor_ ``` c /* Auto wake-up timeout testing setting */ int8_t bma400_timeout_autowakeup_auto_lp(struct bma400_dev *dev) { int8_t rslt = 0; uint8_t power_mode; uint16_t int_status; struct bma400_device_setting dev_setting[2]; /* Selecting auto wakeup on timeout */ dev_setting[0].type = BMA400_AUTOWAKEUP_TIMEOUT; /* Selecting auto low power mode*/ dev_setting[1].type = BMA400_AUTO_LOW_POWER; /* Get the previously set settings */ rslt = bma400_get_device_setting(&dev_setting, 2, dev); if (rslt == BMA400_OK) { /* Enable auto wakeup on timeout feature */ dev_setting[0].conf.auto_wakeup.wakeup_timeout = BMA400_ENABLE; /* Set the timeout value as maximum (10.24s) */ dev_setting[0].conf.auto_wakeup.timeout_thres = BMA400_AUTO_WAKEUP_TIMEOUT_MAX; /* Set auto low power on timeout feature */ dev_setting[1].conf.auto_lp.auto_low_power_trigger = BMA400_AUTO_LP_TIMEOUT_EN; /* Set the timeout value as 1s (400*2.5ms) */ dev_setting[1].conf.auto_lp.auto_lp_timeout_threshold = 400; /* Set the configurations in sensor */ rslt = bma400_set_device_setting(&dev_setting, 2, dev); /* The sensor toggles between Low-power mode and Normal mode for every 10.24s * as configured by user which can be tested and verfied by reading the power mode * and printing it continuously as follows * while (1) { * rslt = bma400_get_power_mode(&power_mode, dev); * printf("\n POWER MODE : %d",power_mode); * } * The power mode toggling can be seen from the printed console output */ } return rslt; } Auto wakeup and auto low power by position Case description In this example, the wakeup interrupt is defined to detect the non-flat position of the sensor. A threshold (94mg) is configured, so if the sensor tilt over the threshold, the wakeup interrupt will be set and switch the BMA400 to normal mode(auto-wakeup function). Once entered into normal mode, the Gen1 will continuously detect the sensor position, and check if the sensor returns back into the range of flat, this range should be smaller than 94mg(here gen1 threshold is set to 40mg). So, once the gen1 condition is fulfilled, BMA400 will automatically switch to low power mode by auto-lowpower function.  Parameters configure Range = 4g, ODR=100, OSR=1  Auto-lowpower relative Register (0x2B) AUTOLOWPOW_1.gen1_int = 1; set this bit the interrupt from Gen1 will trigger the switching from normal mode to low power mode 1.1.1.2 Generic interrupt 1 (gen1) relative Register (0x3F) GEN1INT_CONFIG0: Set gen1_act_x_en, gen1_act_y_en, gen1_act_z_en = 1 (enable all 3 axes) gen1_data_src=1; select filter2 (fixed 100Hz) as data source gen1_act_refu = 0; manual update(fixed reference, configured by host) gen1_act_hyst = 0; disable Register (0x40) GEN1INT_CONFIG1: gen1_comb_sel = 1; logic AND gen1_criterion_sel = 0; inactivity interrupt This combination means that ALL (logic AND) three axes value should be WITHIN (inactivity interrupt) the threshold near the reference position. Register (0x41) GEN1INT_CONFIG2: gen1_int_thres = 5 (threshold = 5*8mg/lsb = 40mg) Register (0x42) GEN1INT_CONFIG3/Register (0x43) GEN1INT_CONFIG31 gen1_int_dur = 100 (monitor duration = 100samples * 1/100Hz(filter2) = 1s) Register (0x44) GEN1INT_CONFIG4 to Register (0x49) GEN1INT_CONFIG9: gen1_int_th_refx/y/z = (0, 0, 512); means (0, 0, 1g ) Range sensitive, (512 lsb represents 1g) @4g range So in this configuration gen1 interrupt will be set only if: Condition 1:  (|a_x-ref_x| <40mg) AND (|a_y-ref_y|<40mg) AND (|a_z-ref_z|<40mg) Condition 2: more than 100 continuous past samples fulfill condition 1  Auto-wakeup relative Register (0x2D) AUTOWAKEUP_1 wkup_int = 1; use wake-up interrupt for auto-wake-up Wakeup interrupt relative Register (0x2F) WKUP_INT_CONFIG0 wkup_x_en, wkup_y_en, wkup_z_en = 1; enable three axes num_of_samples = 3; 4(=3+1) continuous samples will be monitored in low power mode wkup_refu = 0; manual update, configured by host Register (0x30) WKUP_INT_CONFIG1 int_wkup_thres = 3; (3 * 1/32 * 1g = 94mg) @4g range, range sensitive, 8 bit unsigned value Register (0x31) WKUP_INT_CONFIG2 to Register (0x33) WKUP_INT_CONFIG4 int_wkup_refx/y/z = (0, 0, 32); (0, 0, 1g) @4g range, range sensitive So the wakeup interrupt will be set only if: Condition 1: (|acc_x - ref_x| > 94mg) OR (|acc_y - ref_y| > 94mg) OR (|acc_z - ref_z| > 94mg) Condition 2: more than 4 continuous past samples fulfill condition 1 Sample codes The sample codes are shown below, and please ignore the configuration of Gen2, which is not relative to this case. /* #### BMA400 Auto wakeup and Auto low power features ##### _Usage of auto wakeup and auto low power features in sensor_ */ /* Auto wake-up based on position testing setting */ int8_t bma400_position_autowakeup_auto_lp(struct bma400_dev *dev) { int8_t rslt = 0; uint8_t power_mode; uint16_t int_status; struct bma400_device_setting dev_setting[2]; /* Interrupt configuration structure */ struct interrupt_enable int_en; /* Selecting auto wakeup on wakeup interrupt event */ dev_setting[0].type = BMA400_AUTOWAKEUP_INT; /* Selecting auto low power mode*/ dev_setting[1].type = BMA400_AUTO_LOW_POWER; /* Get the previously set settings */ rslt = bma400_get_device_setting(&dev_setting, 2, dev); if (rslt == BMA400_OK) { dev_setting[0].conf.wakeup.wakeup_axes_en = BMA400_XYZ_AXIS_EN dev_setting[0].conf.wakeup.wakeup_ref_update = BMA400_MANUAL_UPDATE dev_setting[0].conf.wakeup.sample_count = BMA400_SAMPLE_COUNT_4 dev_setting[0].conf.wakeup.int_wkup_threshold = 3 dev_setting[0].conf.wakeup.int_wkup_ref_x = 0 dev_setting[0].conf.wakeup.int_wkup_ref_y = 0 dev_setting[0].conf.wakeup.int_wkup_ref_z = 32 /* (0, 0, 1g) */ dev_setting[0].conf.wakeup.int_map = BMA400_INT_CHANNEL_1 /* Enable auto low power on Gen1 trigger */ dev_setting[1].conf.auto_lp.auto_low_power_trigger = BMA400_AUTO_LP_GEN1_TRIGGER; /* Set the configurations in sensor */ rslt = bma400_set_device_setting(&dev_setting, 2, dev); if (rslt == BMA400_OK) { /* Enable the Generic interrupts in the sensor */ int_en.int_sel = BMA400_AUTO_WAKEUP_EN; int_en.conf = BMA400_ENABLE; rslt = bma400_enable_interrupt(&int_en, 1, dev); /* The sensor toggles between Low-power mode and Normal mode if tilt the device(sensor) * or place it back to flat * this can be verfied by reading the power mode and printing it continuously as follows * while (1) { * rslt = bma400_get_power_mode(&power_mode, dev); * printf("\n POWER MODE : %d",power_mode); * } * The power mode toggling can be seen from the printed console output */ } return rslt; } /*##### BMA400 Generic interrupt configuration ##### _Usage of Generic interrupt1 and 2 for activity/inactivity detection in sensor_ */ /* Generic Interrupt feature */ int8_t bma400_generic_interrupts_by_position(struct bma400_dev *dev) { int8_t rslt = 0; /* Variable to store interrupt status */ uint16_t int_status; /* Sensor configuration structure */ struct bma400_setting accel_settin[2]; /* Interrupt configuration structure */ struct interrupt_enable int_en[2]; /* Select the GEN1 and GEN2 interrupts for configuration */ accel_settin[0].type = BMA400_GEN1_INT; accel_settin[1].type = BMA400_GEN2_INT; /* Get the configurations set in the sensor */ rslt = bma400_get_sensor_setting(&accel_settin[0], 2, dev); /* Modify the required parameters from the "gen_int" structure present * inside the "bma400_setting" structure to configure the selected * GEN1/GEN2 interrupts */ if (rslt == BMA400_OK) { /* Set the GEN 1 interrupt for activity detection */ accel_settin[0].conf.gen_int.int_map = BMA400_INT_CHANNEL_2; accel_settin[0].conf.gen_int.axes_sel = BMA400_XYZ_AXIS_EN; accel_settin[0].conf.gen_int.criterion_sel = BMA400_INACTIVITY_INT; accel_settin[0].conf.gen_int.evaluate_axes = BMA400_ALL_AXES_INT; accel_settin[0].conf.gen_int.ref_update = BMA400_MANUAL_UPDATE; accel_settin[0].conf.gen_int.data_src=BMA400_DATA_SRC_ACC_FILT2; accel_settin[0].conf.gen_int.gen_int_thres = 0x05; accel_settin[0].conf.gen_int.gen_int_dur = 100; accel_settin[0].conf.gen_int.hysteresis = BMA400_HYST_0_MG; accel_settin[0].conf.gen_int.int_thres_ref_x = 0; accel_settin[0].conf.gen_int.int_thres_ref_y = 0; accel_settin[0].conf.gen_int.int_thres_ref_z = 512; /* (0, 0, 1g) for gen1 reference. */ /* Set the GEN 2 interrupt for in-activity detection */ accel_settin[1].conf.gen_int.int_map = BMA400_INT_CHANNEL_2; accel_settin[1].conf.gen_int.axes_sel = BMA400_XYZ_AXIS_EN; accel_settin[1].conf.gen_int.criterion_sel = BMA400_INACTIVITY_INT; accel_settin[1].conf.gen_int.evaluate_axes = BMA400_ANY_AXES_INT; accel_settin[1].conf.gen_int.ref_update = BMA400_ONE_TIME_UPDATE; accel_settin[1].conf.gen_int.data_src=BMA400_DATA_SRC_ACC_FILT1; accel_settin[1].conf.gen_int.gen_int_thres = 0x10; accel_settin[1].conf.gen_int.gen_int_dur = 0x01; accel_settin[1].conf.gen_int.hysteresis = BMA400_HYST_0_MG; /* Set the configurations in the sensor */ rslt = bma400_set_sensor_setting(&accel_settin[0], 2, dev); if (rslt == BMA400_OK) { /* Enable the Generic interrupts in the sensor */ int_en[0].int_sel = BMA400_GEN1_INT_EN; int_en[0].conf = BMA400_ENABLE; int_en[1].int_sel = BMA400_GEN2_INT_EN; int_en[1].conf = BMA400_DISABLE; rslt = bma400_enable_interrupt(&int_en[0], 2, dev); } } } } return rslt; } Auto wakeup and auto low power by activity Case description This example is suitable for activity detection, where the device (sensor) is not placed into a fixed position, like wearable devices. To achieve this, Gen1 can be used to detect status that the sensor is in stable status, like the user wearing the device is in sleep, standstill, and trigger the Auto-Lowpower to switch BMA400 into low power mode; in contrary, the auto-wakeup function can be configured to detect the activity, and wake the sensor into normal mode. The key differences between the implementation of actvity detecting(this example) and position detecting (example described in chapter 4.2), is the reference update mode and the relative threshold and number of samples. For activity detection, the reference update mode of wakeup & Gen1 functions should be configured as everytime which means every sample of acceleration will be taken as the reference of the coming wakeup & Gen1 calculation, so the reference will be updated continuously and regardless of any fixed position(as described in chapter 4.2). Parameters configure Range = 4g, ODR=100, OSR=1 Auto-lowpower relative Register (0x2B) AUTOLOWPOW_1.gen1_int = 1; set this bit the interrupt from Gen1 will trigger the switching from normal mode to low power mode Generic interrupt 1 (gen1) relative Register (0x3F) GEN1INT_CONFIG0: Set gen1_act_x_en, gen1_act_y_en, gen1_act_z_en = 1 (enable all 3 axes) gen1_data_src=1; select filter2 (fixed 100Hz) as data source gen1_act_refu = 2; everytime (every time automatically updated from the selected filter data) gen1_act_hyst = 0; disable Register (0x40) GEN1INT_CONFIG1: gen1_comb_sel = 1; logic AND gen1_criterion_sel = 0; inactivity interrupt This combination means that ALL (logic AND) three axes value should be WITHIN (inactivity interrupt) the threshold near the reference position. Register (0x41) GEN1INT_CONFIG2: gen1_int_thres = 5 (threshold = 5*8mg/lsb = 40mg) Register (0x42) GEN1INT_CONFIG3/Register (0x43) GEN1INT_CONFIG31 gen1_int_dur = 100 (monitor duration = 100samples * 1/100Hz(filter2) = 1s) Register (0x44) GEN1INT_CONFIG4 to Register (0x49) GEN1INT_CONFIG9: gen1_int_th_refx/y/z, no need to configure, if reference update mode is everytime   So in this configuration gen1 interrupt will be set only if: Condition 1:  (|a_x_current - ref_x_last| < 40mg) AND (|a_y_current - ref_y_last | < 40mg)   AND (|a_z_current - ref_z_last| < 40mg) Condition 2: more than 100 continuous past samples fulfill condition 1  Auto-wakeup relative Register (0x2D) AUTOWAKEUP_1 wkup_int = 1; use wake-up interrupt for auto-wake-up(switch BMA400 to normal) Wakeup interrupt relative Register (0x2F) WKUP_INT_CONFIG0 wkup_x_en, wkup_y_en, wkup_z_en = 1; enable three axes num_of_samples = 3; 4(=3+1) continuous samples will be monitored in low power mode; the less the samples, the more sensitive the wakeup detecting wkup_refu = 2; everytime update Register (0x30) WKUP_INT_CONFIG1 int_wkup_thres = 3; (3 * 1/32 * 1g = 94mg) @4g range, range sensitive, 8 bit unsigned value The smaller the threshold, the more sensitive the wakeup detecting Register (0x31) WKUP_INT_CONFIG2 to Register (0x33) WKUP_INT_CONFIG4 int_wkup_refx/y/z no need to configure if update mode is everytime So the wakeup interrupt will be set only if: Condition 1: (|acc_x_current - ref_x_last| > 94mg) OR (|acc_y_current - ref_y_last| > 94mg) OR (|acc_z_current - ref_z_last| > 94mg) Condition 2: more than 4 continuous past samples fulfill condition 1 Sample codes The sample codes are shown below, and please ignore the configuration of Gen2, which is not relative to this case. In this example, wakeup interrupt is mapped to INT1 pin while GEN1 interrupt to INT2 pin. Since the INT1 & GEN1 is configured mutually-exclusive, so mapping them to one interrupt pin will result in confusion. /* ######## ------------------- ################ */ /* #### BMA400 Auto wakeup and Auto low power features ##### _Usage of auto wakeup and auto low power features in sensor_ */ /* Auto wake-up based on activity testing setting */ int8_t bma400_activity_autowakeup_auto_lp(struct bma400_dev *dev) { int8_t rslt = 0; uint8_t power_mode; uint16_t int_status; struct bma400_device_setting dev_setting[2]; /* Interrupt configuration structure */ struct interrupt_enable int_en; /* Selecting auto wakeup on wakeup interrupt event */ dev_setting[0].type = BMA400_AUTOWAKEUP_INT; /* Selecting auto low power mode*/ dev_setting[1].type = BMA400_AUTO_LOW_POWER; /* Get the previously set settings */ rslt = bma400_get_device_setting(&dev_setting, 2, dev); if (rslt == BMA400_OK) { dev_setting[0].conf.wakeup.wakeup_axes_en = BMA400_XYZ_AXIS_EN dev_setting[0].conf.wakeup.wakeup_ref_update = BMA400_EVERY_TIME_UPDATE dev_setting[0].conf.wakeup.sample_count = BMA400_SAMPLE_COUNT_4 dev_setting[0].conf.wakeup.int_wkup_threshold = 3 /* dev_setting[0].conf.wakeup.int_wkup_ref_x = 0 */ /* dev_setting[0].conf.wakeup.int_wkup_ref_y = 0 */ /* dev_setting[0].conf.wakeup.int_wkup_ref_z = 32 (0, 0, 1g) */ dev_setting[0].conf.wakeup.int_map = BMA400_INT_CHANNEL_1 /* Enable auto low power on Gen1 trigger */ dev_setting[1].conf.auto_lp.auto_low_power_trigger = BMA400_AUTO_LP_GEN1_TRIGGER; /* Set the configurations in sensor */ rslt = bma400_set_device_setting(&dev_setting, 2, dev); if (rslt == BMA400_OK) { /* Enable the Generic interrupts in the sensor */ int_en.int_sel = BMA400_AUTO_WAKEUP_EN; int_en.conf = BMA400_ENABLE; rslt = bma400_enable_interrupt(&int_en, 1, dev); /* The sensor toggles between Low-power mode and Normal mode if tilt the device(sensor) * or place it back to flat * this can be verfied by reading the power mode and printing it continuously as follows * while (1) { * rslt = bma400_get_power_mode(&power_mode, dev); * printf("\n POWER MODE : %d",power_mode); * } * The power mode toggling can be seen from the printed console output */ } return rslt; } /*##### BMA400 Generic interrupt configuration ##### _Usage of Generic interrupt1 and 2 for activity/inactivity detection in sensor_ */ /* Generic Interrupt feature */ int8_t bma400_generic_interrupts_by_activity(struct bma400_dev *dev) { int8_t rslt = 0; /* Variable to store interrupt status */ uint16_t int_status; /* Sensor configuration structure */ struct bma400_setting accel_settin[2]; /* Interrupt configuration structure */ struct interrupt_enable int_en[2]; /* Select the GEN1 and GEN2 interrupts for configuration */ accel_settin[0].type = BMA400_GEN1_INT; accel_settin[1].type = BMA400_GEN2_INT; /* Get the configurations set in the sensor */ rslt = bma400_get_sensor_setting(&accel_settin[0], 2, dev); /* Modify the required parameters from the "gen_int" structure present * inside the "bma400_setting" structure to configure the selected * GEN1/GEN2 interrupts */ if (rslt == BMA400_OK) { /* Set the GEN 1 interrupt for activity detection */ accel_settin[0].conf.gen_int.int_map = BMA400_INT_CHANNEL_2; accel_settin[0].conf.gen_int.axes_sel = BMA400_XYZ_AXIS_EN; accel_settin[0].conf.gen_int.criterion_sel = BMA400_INACTIVITY_INT; accel_settin[0].conf.gen_int.evaluate_axes = BMA400_ALL_AXES_INT; accel_settin[0].conf.gen_int.ref_update = BMA400_EVERY_TIME_UPDATE; accel_settin[0].conf.gen_int.data_src=BMA400_DATA_SRC_ACC_FILT2; accel_settin[0].conf.gen_int.gen_int_thres = 0x05; accel_settin[0].conf.gen_int.gen_int_dur = 100; accel_settin[0].conf.gen_int.hysteresis = BMA400_HYST_0_MG; /* accel_settin[0].conf.gen_int.int_thres_ref_x = 0; */ /* accel_settin[0].conf.gen_int.int_thres_ref_y = 0; */ /* accel_settin[0].conf.gen_int.int_thres_ref_z = 512; */ /* (0, 0, 1g) for gen1 reference, can be ignored here. */ /* Set the GEN 2 interrupt for in-activity detection */ accel_settin[1].conf.gen_int.int_map = BMA400_INT_CHANNEL_2; accel_settin[1].conf.gen_int.axes_sel = BMA400_XYZ_AXIS_EN; accel_settin[1].conf.gen_int.criterion_sel = BMA400_INACTIVITY_INT; accel_settin[1].conf.gen_int.evaluate_axes = BMA400_ANY_AXES_INT; accel_settin[1].conf.gen_int.ref_update = BMA400_ONE_TIME_UPDATE; accel_settin[1].conf.gen_int.data_src=BMA400_DATA_SRC_ACC_FILT1; accel_settin[1].conf.gen_int.gen_int_thres = 0x10; accel_settin[1].conf.gen_int.gen_int_dur = 0x01; accel_settin[1].conf.gen_int.hysteresis = BMA400_HYST_0_MG; /* Set the configurations in the sensor */ rslt = bma400_set_sensor_setting(&accel_settin[0], 2, dev); if (rslt == BMA400_OK) { /* Enable the Generic interrupts in the sensor */ int_en[0].int_sel = BMA400_GEN1_INT_EN; int_en[0].conf = BMA400_ENABLE; int_en[1].int_sel = BMA400_GEN2_INT_EN; int_en[1].conf = BMA400_DISABLE; /* int this case, gen2 is disabled */ rslt = bma400_enable_interrupt(&int_en[0], 2, dev); } } } } return rslt; }                    
    View full article
    ‎07-19-2019 07:28 AM
    Sensor data type Double precision floating point version and Integer version are two states regarding compensation functions for temperature and pressure. The 24 bit pressure/temperature raw data is split and stored in three consecutive registers from 0x04 to 0x06 and 0x07 to 0x09 respectively. From API side, static double compensate_temperature and static int64_t compensate_temperature are used to compensate the raw temperature data and return the compensated temperature data in integer data type. Pressure sensor drift Used to represent errors in measured values. Basically, two drifts will appear on the sensor: one is solder drifts, and the other is long term drift.  Pressure sensor TCO (Offset temperature coefficient) The offset temperature coefficient is the change in the pressure signal introduced by a change of the temperature. The smaller for TCO value, the smaller the dependence on temperature. Two conditions need to be considered for offset temperature coefficient from pressure 700-1100hPa.  Pressure/temperature OSR (Oversampling) Oversampling is the process of sampling a signal at a sampling frequency significantly higher than the Nyquist rate. The rate of oversampling can be 1, 2, 4, 8, 16, and 32. Increasing the value of oversampling, then will get longer testing time, lower ODR, lower noise and larger power consumption. The default value for oversampling setting is 0x02 in register 0x1C for pressure and temperature measurement, bit 2..0 is for pressure measurement and bit 5..3 is for temperature measurement. In API, using int8_t set_forced_mode_with_osr and int8_t set_normal_mode to configure the oversampling values. The table below shows the recommended setting of oversampling.  Signal Filter for pressure/temperature This is a sliding filter which is aim to reduce the noise from the received signal. The filter coefficient can be set to 0 (bypass mode), 1, 3, 7, 15, 31, 63, and 127. In addition, it suppresses the disturbance in the output data without causing additional interface traffic and processor work load. The output of a next measurement step is filter using the following formula. The “CONFIG” Register 0x1F control the IIR filter coefficients view from bit 3...1. The default value for “CONFIG” is 0x00. Sensor time 3 bytes sensor time is split and stored in three consecutive registers which are 0x0C, 0x0D and 0x0E. Each register contain 8 bit sensor time data. Pressure accuracy This feature is used to represent how much accuracy can be achieved within the certain pressure range.  Two criteria as shown below  Data FIFO This is a 512 bytes FIFO (first-in-first-out) data buffer with feature used to enable data collecting in the FIFO. The register “FIFO_CONFIG_1” register contains the FIFO frame content configuration from bit 4…0.  The default value for “FIFO_CONFIG_1” is 0x02.  Configuring and reading FIFO data from API using the function int8_t configure_and_get_fifo_data. Data Interrupt Allow to signal certain events to the host processor. Different event can be mapped to the interrupt pin, which all are processed with a logical OR. The available interrupts are listed below and can be read in the “INT_STATUS” register” Bit 0, 1, and 3 are used to represent the interrupt status and is cleared after reading in register.  The function static int8_t get_int_status can be used to get the interrupt status from the sensor in API. Interrupt configuration can be set in the “INT_CTRL” register in 0x19. Bit 0, 1, 2, 3, 4 and 6 are used. The function static void fill_fifo_int_ctrl in API used to fill the FIFO interrupt control settings. More BMP388 sensor information can check from the following website https://www.bosch-sensortec.com/bst/products/all_products/bmp388 .    
    View full article
    ‎03-28-2019 08:57 AM
     About this guide This guide is intended for users who want to evaluate the performance of Bosch Sensortec’s BMA400. It describes how to install the Development Desktop 2.0 and use it to perform current and noise measurements for the BMA400, as well as introduce the BMA400’s anti-aliasing function, interrupt functions and FIFO usage, etc. General description The BMA400 is Bosch Sensortec’s first ultra-low-power acceleration sensor without compromising performance. It features 12-bit digital resolution, continuous measurement, selectable bandwidth, and ultra-low power consumption, allowing low-noise measurement of accelerations on three perpendicular axes. The BMA400 can sense tilt, orientation, tap/double-tap, and enable “plug and play” step counting with activity recognition, which makes it ideal for wearable devices that require extended battery life. In addition, equipped with two generic interrupts, the BMA400 can detect multiple defined movements and motions, reducing the workload of the MCU/AP. The Bosch Sensortec Application Board 2.0 provides a versatile and universal demonstration and development environment for Bosch Sensortec’s sensor products. It can be used in conjunction with the Bosch Sensortec Development Desktop software 2.0 to configure all sensor parameters and read/display/capture data on the connected PC. The Bosch Sensortec BMA400 shuttle board is a PCB with a BMA400 sensor mounted on it. It allows easy access to the sensor's pins via a simple socket. Since all Bosch Sensortec sensor shuttle boards have an identical footprint, they can be plugged into Bosch Sensortec’s advanced development tools (e.g. the development board). The BMA400 shuttle board can also be used for the user's own implementations as well. Prerequisites To evaluate the BMA400, the following items are required: Bosch Sensortec Application Board 2.0 BMA400 shuttle board Development desktop software 2.0 In addition, the following system requirements must be met: 32 or 64-bit Windows 7, Windows 8, or Windows 10 Microsoft .NET Framework 4.0 or higher 1 GB memory 1 GHz processor or greater USB 2.0 host controllers Hardware connection Prior to evaluation, the BMA400 shuttle board must be attached on to the Bosch Sensortec Application Board 2.0. Figure 1 shows the connected Bosch Sensortec Application Board 2.0 and BMA400 shuttle board and their key components.              Figure 1: Connection of BMA400 shuttle board and Bosch Sensortec Application Board 2.0 Figure 2 shows signals on the BMA400 shuttle board. The power, SPI, I2C, and INT signals are routed out from the BMA400 to the BMA400 shuttle board’s connectors. Pin 10 ~ 14 and pin 23 ~ 28 are internal signals, which can be ignored.                                                                    Figure 2: BMA400 Shuttle Board Signals Figure 3 show the schematic diagram of the BMA400 sensor on the BMA400 shuttle board.                      Figure 3: Schematic Diagram of the BMA400 Sensor on the BMA400 Shuttle Board Development Desktop 2.0 This chapter describes how to download and install the Development Desktop 2.0. Downloading The Development Desktop 2.0 can be downloaded from Bosch Sensortec website at https://www.bosch-sensortec.com/bst/support_tools/downloads/overview_downloads On the Downloads page, click the tab Software. Under Software, click the “+” sign besides Development Desktop Software to expand it, then click the installer and Development Desktop 2.0 user manual to download. See Figure 4.                                      Figure 4: Development Desktop 2.0 Download Page Installing For instructions on how to install the Development Desktop 2.0, see the downloaded Development Desktop 2.0 user manual. Getting started This chapter introduces the Development Desktop 2.0 UI and describes how to start it, use it to capture a data log. Starting the Development Desktop 2.0 To start the Development Desktop 2.0, do the following: Attach the BMA400 shuttle board onto the Bosch Sensortec Application Board 2.0. Connect the Bosch Sensortec Application Board 2.0 to the PC with a USB cable. Turn on the Power switch on the Bosch Sensortec Application Board 2.0. Double-click the Development Desktop 2.0 icon on the PC to start it. The screen shows below. Click Connect.                                                                 Figure 5: Development Desktop 2.0 Start Window Figure 6 shows the Development Desktop 2.0 UI. By default, the sensor is in sleep mode and should be set to normal mode. Once clicking Start Streaming at the lower bottom corner, the sensor data is plotted and displayed in the upper left part. Interrupt(s) will be plotted in the lower left part if enabled.                                                                Figure 6: Development Desktop 2.0 UI Capturing and analysing data log With the Development Desktop 2.0, data logs can be captured for analysis. To capture a data log, do the following(example 😞 Place the Bosch Sensortec Application Board 2.0 connected with the BMA400 shuttle board on a steady table, keeping them away from vibration. Connect the Bosch Sensortec Application Board 2.0 to the PC, then start the Development Desktop 2.0. In the Accelerometer settings section, set the sensor parameters as below: Power Mode = Normal OSR = 0 ODR = 50Hz Range = 2 4     Click Start Streaming to start data plotting.                                                             Figure 7: Settings for Capturing Data Log 5. Click Panels on the menu bar, then click Data Export.                                                                    Figure 8: Open the Data Export Panel 6. On the popup window, click Select Destination to specify a folder where you want to save the log file, set a file name and choose the file type (.csv is recommended) 7. Check Enable Data Log to start data logging.                                                                                  Figure 9: Enable Data Log 8 .    Uncheck Enable Data Log to stop logging. 9 .     Open the destination folder specified in Step 6, the log file can be found. The captured data log can then be used to evaluate the performance of the BMA400. Current measurement The BMA400 features ultra-low power consumption. To measure the BMA400’s current consumption, do the following: Remove the jumper of J504 on the Bosch Sensortec Application Board 2.0.                                                                                Figure 10: J504 Jumper 2.    Connect the multi-meter to the Bosch Sensortec Application Board 2.0. See Figure 11. 3.    Turn the switch on the multi-meter to point it to “μA". 4.   Start the Development Desktop 2.0 software on the PC. By default, the sensor is in Sleep mode, and the current ~0.15 μA. 5. Set the Power mode = Normal, OSR=0. In this case, the current is ~3.5 μA. Trying different ODRs (12.5 ~ 800 Hz), the measured current remains the same. 6. Set the Power mode = Low power, OSR = 0. In this case, the current is ~0.8 μA. In low power mode, the BMA400 ODR is fixed to 25 Hz.                                                       Figure 11: Current Measurement with Multi-meter Table 1 shows the current consumption table extracted from BMA400 Datasheet. When configuring Accelerometer settings, users can refer to this current consumption table to get appropriate values.                                                                   Figure 12: Settings for Low Power Mode                                                                    Figure 13: Settings for Normal Mode Noise measurement With Development Desktop 2.0, the noise generated can also be measured. The measured noise level varies depending on different accelerometer settings. Table 2 shows part of the noise table from BMA400 Datasheet. For example, in normal mode, when OSR = 2, ODR = 100, the RMS noise measured is approximately 1.93mg  as highlighted in the table.                                                                                                              Figure 14: Set OSR to 2 in Normal Mode                                                                              Figure 15: Set ODR to 100Hz After capturing a data log of the BMA400, users can get the noise by calculating the standard deviations for F, G, and H columns (i.e. data of X, Y, and Z axis), as shown in Figure 16.                                                                 Figure 16: Calculate the Noise with Data Log  Anti-aliasing evaluation In order to reduce current consumption, most sensors work in duty cycling sampling mode and the equivalent sampling rate can only be ~ 1/ODR due to the long sleep period. In this case, the output of the accelerometer is inevitably interfered by high frequency noise. However, the BMA400 uses  continuous sampling and filtering, and the actual sampling rate of the BMA400 is much greater than the ODR (output data rate). Therefore, it can easily filter out the high-frequency interference signals and recover real motion signals. Figure 17 illustrates the anti-aliasing principle of the BMA400.                                                                  Figure 17: BMA400 Anti-aliasing Principle Interrupt functions The BMA400 is integrated with multi-functional interrupts, including auto-wakeup/low power, generic interrupts 1 and 2, step counter, and orientation, which can be used in different scenarios. To configure auto-wakeup/low power, generic interrupt 1 and step counter, do the following: Click Panels > Memory Map > Interrupt View to open the Interrupt view.                                                                                  Figure 19: Interrupt View 2    Configure interrupt mapping parameters as shown in Figure 20, and enable Gen1, step counter interrupt, and wake up interrupt, then click Write.                                                                              Figure 20: Interrupt Configuration 3    Configure wakeup interrupt as shown in Figure 21, and check Enable Gen 1 trigger low power.                                                              Figure 21: Wakeup/Auto Low Power Configuration In this example, the condition of auto wakeup is: For x, y, or z axis, if >= 2 continuous acceleration differences of contiguous samples are bigger than 94mg, the wakeup interrupt will be triggered, and the BMA400 will enter normal mode. In low power mode, the sampling rate of the BMA400 is 25Hz, so 2 samples time means 80ms wakeup delay 4     Configure Gen1 (generic interrupt 1) for triggering auto-low-power.                                                        Figure 22: Generic Interrupt Configuration In this example, the trigger condition of Gen1 is: For x, y, and z axes, if >= 100 continuous acceleration differences of contiguous samples are lower than 24 mg, the Gen1 will interrupt and trigger the BMA400 to switch to low power mode. 5     Move the board and simulate the step movement, it can be seen that the BMA400 is switched to normal mode automatically, and the step counter is increasing (the first seven steps will not be displayed until the 8th step comes.)If the sensor stays still for more than 1s, the Gen1 is triggered and the BMA400 automatically goes to low power mode.                                                                                Figure 23: Interrupt Plotting FIFO usage The BMA400 is integrated with 1 Kbyte FIFO, which support watermark and full interrupts to host. To  configure FIFO usage, do the following: 1     Click Panels > Memory Map and choose FIFO View, as shown in Figure 24.                                                                                   Figure 24: Enable FIFO View 2      In the FIFO View, configure interrupt settings and FIFO watermark, click Write, and then click Start streaming.                                                                              Figure 25: FIFO View Additional Development Desktop 2.0 UI menus This chapter describes some useful configuration panels on the Development Desktop 2.0 UI menu. As shown in Figure 26, under Panels > Memory Map, users can switch between four views according to their own needs.                                                                          Figure 26: Configuration Panels Binary View: for reading/writing all the sensor registers Interrupt View: for configure the BMA400 features and interrupts FIFO view: for configuring FIFO SelfTest View: for performing self-test and showing the test result By clicking Panels > Register Access, users can read and write a single register. Figure 27 shows the popup register read and write configuration menu.                                                              Figure 27: Register Access Configuration Menu  
    View full article
    ‎07-29-2019 10:33 AM
    Introduction Accelerometer (Acc), Gyroscope (Gyro) and Magnetometer (Mag) sensors (components) have their own coordinates. By default BHA and BHI are configured to ENU axis convention (East-North-Up), as commonly used in consumer electronic devices. It is usually obtained by the integration of Accelerometer (Acc), Gyroscope (Gyro) and Magnetometer (Mag) sensors readings. The ENU coordinate system is defined as a direct orthonormal basis where:     x points east and is tangential to the ground.     y points north and is tangential to the ground.     z points towards the sky and is perpendicular to the ground.  Users can download the BHI/BHA firmware from Bosch Sensortec Website. All firmware’s coordinates are the same. Figure 2(left) shows the coordinate of the BHI/BHA shuttle board. Cares must be taken that the direction of BHI/BHA and Magnetometer sensor must follow the BHI/BHA shuttle board when customer do the PCB placement. Figure 2(right) shows the direction of BHI/BHA and Magnetometer on the shuttle board. It is the easiest and best way that customer can reuse the same coordinate of BHI/BHA shuttle board on their product. It is possible to change the coordinate based on customer definition. This document is to tell the customer the way how to do the axis-remapping on their products. Axes definition Define the coordination of your board (X BOARD, Y BOARD, Z BOARD ). Normally this is the default coordination system of your final application (i.e. your system coordination). In standard Android system the ENU (east north up) orientation is required. For other applications, the Z BOARD is normally pointing to the sky or ground when the board is placed on a horizontal surface. Find the coordinates of the sensors mounted on the board in their datasheets. Draw all the coordinates on the paper. Figure 3 shows an example. In Figure 3, it is highly recommended to follow the placement on the BHI160 shuttle board, if the user do not want to pay more effort on it.  If you are using a standard Bosch sensor, their coordinates follow the right-handed coordinate principle (Figure 4). You can apply it to find the sensor axes when it placed on the board.   Orientation matrix When the sensors axes orientation are different to the board, we need to convert it to the board coordinate by following formula: [X Y Z] is the board coordinate [Xs Ys Zs] is the sensor coordinate (C 0 … C 8 ) is the orientation matrix. The coefficient has three possible value: 1, 0 and -1. 1 --- Two axes are paralleled and have same direction -1 --- Two axes are paralleled and have opposite direction 0 --- Two axes are perpendicular Example If we have a board shown in Figure 3. On this board, there are a BHI160 and a BMM150. The dots on the sensor indicate their coordinates. You can try to find the coordinates and write the orientation matrix. Table 1shows the result. Orientation matrix: C s = (0 -1 0 1 0 0 0 0 1), Updating via product API (Host side) Basic configuration When customer follow the requirement (components placement), so only one matrix is needed for the sensor(A,M,G). Users can configure the axes before enable the BHI160/BHA250 by editting the remapping matrix in its .c file. The following code is content of the accelerometer_remapping_example.c in the API. Use this as a reference to update your matrix accordingly. The matrix can also be edited within the product API which is available on GitHub: https://github.com/BoschSensortec/BHy1_driver_and_MCU_solution int main(void) { u8 array[ARRAYSIZE], *fifoptr, bytes_left_in_fifo=0; u16 bytes_remaining, bytes_read; bhy_data_generic_t fifo_packet; bhy_data_type_t packet_type; BHY_RETURN_FUNCTION_TYPE result; s8 mapping[9] = {0}; s8 mapping_all[9] = {0 -1 0 1 0 0 0 0 1}; // new mapping matrix, example on Figure3 … … /* config mapping matrix, it is not necessary to change mapping matrix if its orientation is aligned with the board */ bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_ACC,mapping); // get current ACC mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_ACC,mapping_all); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_ACC,mapping); // check if the matrix is set successfully … … bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_GYRO,mapping); // get current GYRO mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_GYRO,mapping_all); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_GYRO,mapping); // check if the matrix is set successfully … … bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_MAG,mapping); // get current MAG mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_MAG,mapping_all); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_MAG,mapping); // check if the matrix is set successfully ​ Advanced configuration If the sensor placement is not followed the Shuttle Board, the user can configure matrix for each sensor. In this configuration, customer can place the sensor on the board as they need(no need to follow the chip placement on shuttle board). int main(void) { u8 array[ARRAYSIZE], *fifoptr, bytes_left_in_fifo=0; u16 bytes_remaining, bytes_read; bhy_data_generic_t fifo_packet; bhy_data_type_t packet_type; BHY_RETURN_FUNCTION_TYPE result; s8 mapping[9] = {0}; s8 mapping_ACC[9] = {0 -1 0 1 0 0 0 0 1}; // new mapping matrix, example on Figure3 s8 mapping_GYRO[9] = {0 -1 0 1 0 0 0 0 1}; // s8 mapping_MAG[9] = {0 -1 0 1 0 0 0 0 1}; // can be different … … /* config mapping matrix, it is not necessary to change mapping matrix if its orientation is aligned with the board */ bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_ACC,mapping); // get current ACC mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_ACC,mapping_ACC); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_ACC,mapping); // check if the matrix is set successfully … … bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_GYRO,mapping); // get current GYRO mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_GYRO,mapping_GYRO); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_GYRO,mapping); // check if the matrix is set successfully … … bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_MAG,mapping); // get current MAG mapping matrix bhy_set_mapping_matrix (PHYSICAL_SENSOR_INDEX_MAG,mapping_MAG); // set new mapping matrix in the fw bhy_get_mapping_matrix(PHYSICAL_SENSOR_INDEX_MAG,mapping); // check if the matrix is set successfully   For more details and technical support with respect to the product API the *.h file and the MCU porting please refer to the Bosch Sensortec documents “MCU Driver Porting Guide” and “Interfacing Reference Code from Generic Driver” for BHA and/or BHI placed within the section “Application notes”, available onhttps://www.bosch-sensortec.com/bst/support_tools/downloads/overview_downloads Check the orientation After the orientation matrix has been updated, you need to check whether the remapping is successful. You can read the uncalibrated data of the sensors to check if the remapping is successful. Please define the coordination of the board (X BOARD, Y BOARD, Z BOARD ) first. Check the Acc axes (XA, YA, ZA) Enable Acc uncalibrated data; Place the board on a horizontal surface and make sure Z BOARD is pointing to the sky. Z-axis should output 1g. Turn the board at perpendicular position and make sure X BOARD is pointing to the sky. X-axis should output 1g. Turn the board at perpendicular position and make sure Y BOARD is pointing to the sky. Y-axis should output 1g. Check the Gyro axes (XG, YG, ZG) If you use BHI160, the axes of Acc and Gyro are same. In Bosch product, a Gyro axis direction can be found by your right hand. Move your four fingers follow the rotation direction to make a fist and the thumb will be pointing to the positive axis like Figure 5 (This is similar to right-hand crew rule). Enable Gyro uncalibrated data; Place the board on a horizontal surface and make sure Z BOARD is pointing to the sky. Quickly rotate left 180 degree. The output has significant change is the rotation axis. It should be z-axis and output positive data. Rotate the board according to X BOARD and Y BOARD . Check the output with right-hand crew rule respectively. Check the Mag axes (XM, YM, ZM) Method 1 Enable Mag uncalibrated data and only log the first three data, which is the original data; Place the board on the table and make sure the X BOARD is pointing to the planet's North Pole by using a reference compass. Record the (X M, Y M, Z M ) stable output below. Then Point X BOARD to planet's South Pole and record the stable output. The axis output has the maximum difference is parallel to X BOARD Here |X 1 - X 2 | should be the largest, and X 1 > X 2 . Then the remapping is correct.   Apply same method to Y BOARD, Z BOARD to find if the orientation of other two axes are correct.  Method 2 1.Enable Mag uncalibrated data and only log the first three data; 2.Rotate the board in following steps and record the output data: If X1>X2 & X4>X3, min(X1,X2,X3,X4)=X2, and max(X1,X2,X3,X4)=X4; Y1>Y2 & Y4>Y3, min(Y1,Y2,Y3,Y4)=Y3, and max(Y1,Y2,Y3,Y4)=Y1; Z2>Z1. Then the remapping is correct.  
    View full article
    Top Contributors
    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist