Adds imu calibration

This commit is contained in:
Rune Harlyk
2025-12-24 12:53:20 +01:00
parent e22ac69e9b
commit 3be08a31ed
6 changed files with 82 additions and 1 deletions
+5
View File
@@ -1,5 +1,6 @@
export enum MessageTopic { export enum MessageTopic {
imu = 'imu', imu = 'imu',
imuCalibrate = 'imuCalibrate',
mode = 'mode', mode = 'mode',
input = 'input', input = 'input',
analytics = 'analytics', analytics = 'analytics',
@@ -160,6 +161,10 @@ export type IMUMsg = {
bmp: [number, number, number, boolean] bmp: [number, number, number, boolean]
} }
export type IMUCalibrationResult = {
success: boolean
}
export interface I2CDevice { export interface I2CDevice {
address: number address: number
part_number: string part_number: string
+35 -1
View File
@@ -6,7 +6,7 @@
import { slide } from 'svelte/transition' import { slide } from 'svelte/transition'
import { onDestroy, onMount } from 'svelte' import { onDestroy, onMount } from 'svelte'
import { socket } from '$lib/stores' import { socket } from '$lib/stores'
import { MessageTopic, type IMUMsg } from '$lib/types/models' import { MessageTopic, type IMUMsg, type IMUCalibrationResult } from '$lib/types/models'
import { useFeatureFlags } from '$lib/stores/featureFlags' import { useFeatureFlags } from '$lib/stores/featureFlags'
import { Rotate3d } from '$lib/components/icons' import { Rotate3d } from '$lib/components/icons'
@@ -14,6 +14,8 @@
const features = useFeatureFlags() const features = useFeatureFlags()
let intervalId: ReturnType<typeof setInterval> | number let intervalId: ReturnType<typeof setInterval> | number
let isCalibrating = $state(false)
let calibrationResult = $state<IMUCalibrationResult | null>(null)
let angleChartElement: HTMLCanvasElement let angleChartElement: HTMLCanvasElement
let tempChartElement: HTMLCanvasElement let tempChartElement: HTMLCanvasElement
@@ -206,14 +208,26 @@
imu.addData(data) imu.addData(data)
}) })
socket.on(MessageTopic.imuCalibrate, (data: IMUCalibrationResult) => {
isCalibrating = false
calibrationResult = data
})
initializeCharts() initializeCharts()
intervalId = setInterval(updateData, 200) intervalId = setInterval(updateData, 200)
}) })
onDestroy(() => { onDestroy(() => {
socket.off(MessageTopic.imu) socket.off(MessageTopic.imu)
socket.off(MessageTopic.imuCalibrate)
clearInterval(intervalId) clearInterval(intervalId)
}) })
function startCalibration() {
isCalibrating = true
calibrationResult = null
socket.sendEvent(MessageTopic.imuCalibrate, {})
}
</script> </script>
<SettingsCard collapsible={false}> <SettingsCard collapsible={false}>
@@ -224,6 +238,26 @@
<span>IMU</span> <span>IMU</span>
{/snippet} {/snippet}
<div class="flex items-center gap-2 mb-4">
<button
class="btn btn-sm btn-primary"
onclick={startCalibration}
disabled={isCalibrating || !$features.imu}
>
{#if isCalibrating}
<span class="loading loading-spinner loading-xs"></span>
Calibrating...
{:else}
Calibrate IMU
{/if}
</button>
{#if calibrationResult}
<span class="badge" class:badge-success={calibrationResult.success} class:badge-error={!calibrationResult.success}>
{calibrationResult.success ? 'Calibrated' : 'Failed'}
</span>
{/if}
</div>
{#if $features.imu} {#if $features.imu}
<div class="w-full overflow-x-auto"> <div class="w-full overflow-x-auto">
<div <div
+20
View File
@@ -123,6 +123,26 @@ class IMU : public SensorBase<IMUAnglesMsg> {
float getAngleZ() { return _msg.rpy[0]; } float getAngleZ() { return _msg.rpy[0]; }
bool calibrate() {
#if FT_ENABLED(USE_MPU6050)
if (!_msg.success) return false;
ESP_LOGI("IMU", "Starting calibration...");
_imu.CalibrateGyro(6);
_imu.CalibrateAccel(6);
ESP_LOGI("IMU", "Calibration complete");
return true;
#elif FT_ENABLED(USE_BNO055)
if (!_msg.success) return false;
ESP_LOGI("IMU", "Starting calibration...");
adafruit_bno055_offsets_t offsets;
bool result = _imu.getSensorOffsets(offsets);
ESP_LOGI("IMU", "Calibration complete");
return result;
#else
return false;
#endif
}
private: private:
#if FT_ENABLED(USE_MPU6050) #if FT_ENABLED(USE_MPU6050)
MPU6050 _imu; MPU6050 _imu;
+2
View File
@@ -74,6 +74,8 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
float leftDistance(); float leftDistance();
float rightDistance(); float rightDistance();
bool calibrateIMU();
StatefulHttpEndpoint<PeripheralsConfiguration> endpoint; StatefulHttpEndpoint<PeripheralsConfiguration> endpoint;
private: private:
+9
View File
@@ -134,6 +134,7 @@ void setupServer() {
#define EVENT_I2C_SCAN "i2cScan" #define EVENT_I2C_SCAN "i2cScan"
#define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM" #define EVENT_SERVO_CONFIGURATION_SETTINGS "servoPWM"
#define EVENT_SERVO_STATE "servoState" #define EVENT_SERVO_STATE "servoState"
#define EVENT_IMU_CALIBRATE "imuCalibrate"
void setupEventSocket() { void setupEventSocket() {
// Motion events // Motion events
@@ -159,6 +160,13 @@ void setupEventSocket() {
socket.emit(EVENT_I2C_SCAN, results); socket.emit(EVENT_I2C_SCAN, results);
}); });
socket.onEvent(EVENT_IMU_CALIBRATE, [&](JsonVariant &root, int originId) {
JsonDocument doc;
JsonVariant results = doc.to<JsonVariant>();
results["success"] = peripherals.calibrateIMU();
socket.emit(EVENT_IMU_CALIBRATE, results);
});
// Servo controller events // Servo controller events
socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS, socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS,
[&](JsonVariant &root, int originId) { servoController.servoEvent(root, originId); }); [&](JsonVariant &root, int originId) { servoController.servoEvent(root, originId); });
@@ -174,6 +182,7 @@ void IRAM_ATTR SpotControlLoopEntry(void *) {
peripherals.begin(); peripherals.begin();
servoController.begin(); servoController.begin();
motionService.begin(); motionService.begin();
peripherals.calibrateIMU();
for (;;) { for (;;) {
CALLS_PER_SECOND(SpotControlLoopEntry); CALLS_PER_SECOND(SpotControlLoopEntry);
+11
View File
@@ -185,4 +185,15 @@ void Peripherals::getSonarResult(JsonVariant &root) {
array[0] = _left_distance; array[0] = _left_distance;
array[1] = _right_distance; array[1] = _right_distance;
#endif #endif
}
bool Peripherals::calibrateIMU() {
#if FT_ENABLED(USE_MPU6050 || USE_BNO055)
beginTransaction();
bool result = _imu.calibrate();
endTransaction();
return result;
#else
return false;
#endif
} }