Add IMU app

This commit is contained in:
Thomas Farstrike
2025-06-26 09:49:30 +02:00
parent f8676c8dbc
commit 4d4e8361ff
3 changed files with 119 additions and 0 deletions
@@ -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"
}
]
}
]
}
@@ -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)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB