<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[BMI270 on AtomS3R (C126) sign-flips in accelerometer output around high-acceleration events]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">This is copy of the question already asked at <a href="https://github.com/m5stack/M5Unified/issues/230" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/m5stack/M5Unified/issues/230</a></p>
<p dir="auto">Is my test correct? Is this a bad sensor, an an expected sensor limitation? Can it be somehow corrected in hardware settings or software (I'm using M5Unified) ?</p>
<p dir="auto">BMI270 sensor (in M5Stack ATOM S3R C126) produces sign-flips in accelerometer output during high-acceleration events.<br />
By sign-flips I mean that consecutive samples show oscillations where acceleration values flip sign within 10 ms.</p>
<p dir="auto">To test, use the provided code and perform this experiment:</p>
<ol>
<li>Sensor held in hand, palm facing down</li>
<li>Soft pillow placed on rigid table</li>
<li>Hand dropped from ~30cm onto pillow</li>
<li>At impact, hand pressed hard through pillow until table was felt underneath (reducing bounce)</li>
</ol>
<p dir="auto">Example sign-flips, focusing on z-axis (normal to the display) sensor movement trajectory.</p>
<pre><code>grep "14827 " -B 2 -A 10 output.txt
 14807 | raw:( -2285,  -997, -6448) | cal:( -0.236,  0.570, -1.576)  (sensor descent)
 14817 | raw:( -3578,   235,-11929) | cal:(  0.065,  0.885, -2.914)  (sensor descent)
 14827 | raw:( -3527,  1539,-23443) | cal:(  0.383,  0.873, -5.725)  (sensor descent)
 14837 | raw:( -1190,  1725,-32768) | cal:(  0.429,  0.302,  7.999)  FLIP (saturated: raw=-32768)
 14847 | raw:(  2501,  1160,-32768) | cal:(  0.291, -0.599,  7.999)  (saturated)
 14857 | raw:(  7932,  -168,-32580) | cal:( -0.033, -1.925, -7.955)  FLIP BACK
 14867 | raw:( 16790,  -344,-27327) | cal:( -0.076, -4.087, -6.673)
 14881 | raw:( 32767, -7830,  9186) | cal:( -1.904, -7.988,  2.241)  GAP (14867+10=14877, but shows 14881)
 14891 | raw:( 31414,-11571, 31595) | cal:( -2.817, -7.658,  7.712)
 14901 | raw:( 12632,  -802, 32767) | cal:( -0.188, -3.072,  7.998)  (saturated again)
 14911 | raw:( -4568, -9861, 24476) | cal:( -2.400,  1.127,  5.974)
 14921 | raw:(  5535, -2038,-16586) | cal:( -0.490, -1.339, -4.051)  ANOTHER FLIP
 14931 | raw:( -5016, 12606,  9124) | cal:(  3.085,  1.236,  2.226)
</code></pre>
<p dir="auto">What could be the reason for this behavior?<br />
I'm not very familiar with IMUs, so below there are some guesses I was able to find online.<br />
Could this be due to the lack of FIFO reading <a href="https://github.com/m5stack/M5Unified/issues/123" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/m5stack/M5Unified/issues/123</a>, sensor filter ringing, MEMS mechanical resonance, or the prolonged effect of the acceleration range saturation?</p>
<p dir="auto">Are there any workarounds to avoid such flips?</p>
<p dir="auto">The measurement code:</p>
<pre><code>/**
 * @file accel_drop_impact.ino
 * @brief Detect acceleration sign-flips during controlled hand-assisted impacts
 *
 * Test procedure:
 *
 * 1. Sensor held in hand, palm facing down
 * 2. Soft pillow placed on rigid table
 * 3. Hand dropped from ~30cm onto pillow
 * 4. At impact, hand pressed hard through pillow until table was felt underneath (reducing bounce)
 */

#include &lt;M5Unified.h&gt;

static const uint32_t SAMPLING_FREQUENCY_HZ = 100;
static const uint32_t SAMPLING_INTERVAL_MS = 1000 / SAMPLING_FREQUENCY_HZ;  // 10ms

void setup() {
    auto cfg = M5.config();
    cfg.serial_baudrate = 115200;
    M5.begin(cfg);

    Serial.println("\n=== BMI270 HAND-CONTROLLED IMPACT SIGN-FLIP DETECTION ===");
    Serial.println("Using M5Unified defaults: 100 Hz sampling, ±8g accel range");
    Serial.println();

    // Re-initialize I2C
    M5.In_I2C.begin((i2c_port_t)I2C_NUM_0, 45, 0);
    delay(100);
    M5.Imu.update();
    delay(100);

    // M5Unified default calibration
    Serial.println("Calibrating accelerometer baseline (2 seconds)...");
    M5.Imu.setCalibration(64, 64, 64);
    delay(2000);
    M5.Imu.setCalibration(0, 0, 0);

    Serial.println();
    Serial.println("Output format:");
    Serial.println("  timestamp_ms | raw:(x,y,z) LSBs | cal:(x,y,z) g");
    Serial.println("  (all three axes to detect erratic values and cross-talk)");
    Serial.println();
    Serial.println("Ready. Start hand-assisted drops...");
    Serial.println("---");
}

void loop() {
    static uint32_t lastPrint = 0;
    uint32_t now = millis();

    if (M5.Imu.update()) {
        int16_t raw_x = M5.Imu.getRawData(0);
        int16_t raw_y = M5.Imu.getRawData(1);
        int16_t raw_z = M5.Imu.getRawData(2);

        auto data = M5.Imu.getImuData();
        float cal_x = data.accel.x;
        float cal_y = data.accel.y;
        float cal_z = data.accel.z;

        // Print all samples at configured sampling frequency to capture erratic sign-flips
        // (even low values following high values are important for detecting oscillations)
        if (now - lastPrint &gt;= SAMPLING_INTERVAL_MS) {
            Serial.printf("%6lu | raw:(%6d,%6d,%6d) | cal:(%7.3f,%7.3f,%7.3f)\n",
                now,
                raw_x, raw_y, raw_z,
                cal_x, cal_y, cal_z);
            lastPrint = now;
        }
    }

    delay(1);
}
</code></pre>
<p dir="auto">The serial output capture code:</p>
<pre><code>#!/usr/bin/env python3
"""
Capture full-frequency serial output from drop impact test to file.

Usage:
    python capture_serial.py /dev/ttyACM0 output.txt

The script will:
1. Connect to serial port at 115200 baud
2. Read all incoming data
3. Save to file in real-time
4. Press Ctrl+C to stop
"""

import sys
import serial
import time

def capture_serial(port: str, output_file: str) -&gt; None:
    try:
        ser = serial.Serial(port, 115200, timeout=1)
        print(f"Connected to {port} at 115200 baud")
        print(f"Saving to {output_file}")
        print("Ctrl+C to stop\n")

        with open(output_file, 'w') as f:
            start_time = time.time()
            line_count = 0

            while True:
                if ser.in_waiting:
                    line = ser.readline().decode('utf-8', errors='ignore')
                    if line:
                        f.write(line)
                        f.flush()  # Flush to disk immediately
                        line_count += 1

                        # Print progress every 50 lines
                        if line_count % 50 == 0:
                            elapsed = time.time() - start_time
                            print(f"[{elapsed:.1f}s] {line_count} lines captured")

    except KeyboardInterrupt:
        elapsed = time.time() - start_time
        print(f"\n\nCapture complete!")
        print(f"Total lines: {line_count}")
        print(f"Elapsed: {elapsed:.1f}s")
        print(f"Saved to: {output_file}")
    except serial.SerialException as e:
        print(f"Serial error: {e}")
        sys.exit(1)
    finally:
        if 'ser' in locals():
            ser.close()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: python capture_serial.py &lt;device&gt; &lt;output_file&gt;")
        sys.exit(1)

    port = sys.argv[1]
    output_file = sys.argv[2]

    capture_serial(port, output_file)
</code></pre>
]]></description><link>https://community.m5stack.com/topic/8130/bmi270-on-atoms3r-c126-sign-flips-in-accelerometer-output-around-high-acceleration-events</link><generator>RSS for Node</generator><lastBuildDate>Wed, 29 Apr 2026 07:44:10 GMT</lastBuildDate><atom:link href="https://community.m5stack.com/topic/8130.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 10 Mar 2026 17:06:36 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to BMI270 on AtomS3R (C126) sign-flips in accelerometer output around high-acceleration events on Wed, 11 Mar 2026 14:27:47 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/doop4" aria-label="Profile: doop4">@<bdi>doop4</bdi></a><br />
I'm not familiar with the M5Unified driver; but I've worked with the bmi270 and written a micropython driver for it..</p>
<p dir="auto">Despite your pillow; you will still get a bit of bounce.. (I've spent time testing this chip, it's very hard to not get any bounce when you do this sort of test.)</p>
<p dir="auto">But, I think you are seeing the device going out of range; at which point you get weird/invalid readings.</p>
<p dir="auto">I dont see anywhere in your code setting the acceleration range; the max is +/- 16G, but <strong>it defaults to +/- 8g, which is where your readings appear to fail.</strong> I guess M5Unified has a method for setting this? Try the biggest range.</p>
<p dir="auto">Also; you can set filtering based on an average mode; the default is to average 4 readings (the sensor runs at 20MHz) but this can be set all the way up to 128.</p>
<p dir="auto">The M5Unified driver is using 'direct readings' (just like my driver), do not confuse this with 'FIFO' mode; which is an automated, IRQ triggered high-speed burst capture method. You read the dataset out from the chip buffer after the event has ended. AFIK the M5 drivers do not support this.</p>
]]></description><link>https://community.m5stack.com/post/30766</link><guid isPermaLink="true">https://community.m5stack.com/post/30766</guid><dc:creator><![CDATA[easytarget]]></dc:creator><pubDate>Wed, 11 Mar 2026 14:27:47 GMT</pubDate></item></channel></rss>