From 4d4e8361ffddf490bc56a37f65c8e7142afbdea6 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Thu, 26 Jun 2025 09:49:30 +0200 Subject: [PATCH] Add IMU app --- .../META-INF/MANIFEST.JSON | 24 +++++ .../apps/com.micropythonos.imu/assets/imu.py | 95 ++++++++++++++++++ .../res/mipmap-mdpi/icon_64x64.png | Bin 0 -> 6013 bytes 3 files changed, 119 insertions(+) create mode 100644 internal_filesystem/apps/com.micropythonos.imu/META-INF/MANIFEST.JSON create mode 100644 internal_filesystem/apps/com.micropythonos.imu/assets/imu.py create mode 100644 internal_filesystem/apps/com.micropythonos.imu/res/mipmap-mdpi/icon_64x64.png diff --git a/internal_filesystem/apps/com.micropythonos.imu/META-INF/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.imu/META-INF/MANIFEST.JSON new file mode 100644 index 00000000..1ebd601e --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.imu/META-INF/MANIFEST.JSON @@ -0,0 +1,24 @@ +{ +"name": "IMU", +"publisher": "MicroPythonOS", +"short_description": "Inertial Measurement Unit Visualization", +"long_description": "Visualize data from the Intertial Measurement Unit, also known as the accellerometer.", +"icon_url": "https://apps.micropythonos.com/apps/com.micropythonos.helloworld/icons/com.micropythonos.imu.0.0.1_64x64.png", +"download_url": "https://apps.micropythonos.com/apps/com.micropythonos.helloworld/mpks/com.micropythonos.mu.0.0.1.mpk", +"fullname": "com.micropythonos.imu", +"version": "0.0.1", +"category": "hardware", +"activities": [ + { + "entrypoint": "assets/imu.py", + "classname": "IMU", + "intent_filters": [ + { + "action": "main", + "category": "launcher" + } + ] + } + ] +} + diff --git a/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py b/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py new file mode 100644 index 00000000..f9fc5357 --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py @@ -0,0 +1,95 @@ +from mpos.apps import Activity + +class IMU(Activity): + + sensor = None + refresh_timer = None + + # widgets: + sliderx = None + slidery = None + sliderz = None + slidergx = None + slidergy = None + slidergz = None + + def onCreate(self): + screen = lv.obj() + self.templabel = lv.label(screen) + self.templabel.align(lv.ALIGN.TOP_MID, 0, 10) + self.sliderx = lv.slider(screen) + self.sliderx.align(lv.ALIGN.CENTER, 0, -60) + self.slidery = lv.slider(screen) + self.slidery.align(lv.ALIGN.CENTER, 0, -30) + self.sliderz = lv.slider(screen) + self.sliderz.align(lv.ALIGN.CENTER, 0, 0) + self.slidergx = lv.slider(screen) + self.slidergx.align(lv.ALIGN.CENTER, 0, 30) + self.slidergy = lv.slider(screen) + self.slidergy.align(lv.ALIGN.CENTER, 0, 60) + self.slidergz = lv.slider(screen) + self.slidergz.align(lv.ALIGN.CENTER, 0, 90) + try: + from machine import Pin, I2C + from qmi8658 import QMI8658 + import machine + self.sensor = QMI8658(I2C(0, sda=machine.Pin(48), scl=machine.Pin(47))) + except Exception as e: + warning = f"Warning: could not initialize IMU hardware:\n{e}" + print(warning) + self.templabel.set_text(warning) + self.setContentView(screen) + + def onStart(self, screen): + self.refresh_timer = lv.timer_create(self.refresh, 100, None) + + def onStop(self, screen): + if self.refresh_timer: + self.refresh_timer.delete() + + + def map_nonlinear(self, value: float) -> int: + # Preserve sign and work with absolute value + sign = 1 if value >= 0 else -1 + abs_value = abs(value) + # Apply non-linear transformation (square root) to absolute value + # Scale input range [0, 200] to [0, sqrt(200)] first + sqrt_value = (abs_value ** 0.5) + # Scale to output range [0, 100] + # Map [0, sqrt(200)] to [50, 100] for positive, [0, 50] for negative + max_sqrt = 200.0 ** 0.5 # Approx 14.142 + scaled = (sqrt_value / max_sqrt) * 50.0 # Scale to [0, 50] + return int(50.0 + (sign * scaled)) # Shift to [0, 100] + + def refresh(self, timer): + if self.sensor: + #print(f"""{sensor.temperature=} {sensor.acceleration=} {sensor.gyro=}""") + temp = self.sensor.temperature + ax = self.sensor.acceleration[0] + axp = int((ax * 100 + 100)/2) + ay = self.sensor.acceleration[1] + ayp = int((ay * 100 + 100)/2) + az = self.sensor.acceleration[2] + azp = int((az * 100 + 100)/2) + # values between -200 and 200 => /4 becomes -50 and 50 => +50 becomes 0 and 100 + gx = self.map_nonlinear(self.sensor.gyro[0]) + gy = self.map_nonlinear(self.sensor.gyro[1]) + gz = self.map_nonlinear(self.sensor.gyro[2]) + self.templabel.set_text(f"IMU chip temperature: {temp:.2f}°C") + else: + #temp = 12.34 + import random + randomnr = random.randint(0,100) + axp = randomnr + ayp = 50 + azp = 75 + gx = 45 + gy = 50 + gz = 55 + self.sliderx.set_value(axp, lv.ANIM.OFF) + self.slidery.set_value(ayp, lv.ANIM.OFF) + self.sliderz.set_value(azp, lv.ANIM.OFF) + self.slidergx.set_value(gx, lv.ANIM.OFF) + self.slidergy.set_value(gy, lv.ANIM.OFF) + self.slidergz.set_value(gz, lv.ANIM.OFF) + diff --git a/internal_filesystem/apps/com.micropythonos.imu/res/mipmap-mdpi/icon_64x64.png b/internal_filesystem/apps/com.micropythonos.imu/res/mipmap-mdpi/icon_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..334a8777e97a9fda7abcc7e6e6a197f1d52aa56e GIT binary patch literal 6013 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 literal 0 HcmV?d00001