🤹 Adds option for direct control of multiple servos

This commit is contained in:
Rune Harlyk
2025-05-15 19:59:06 +02:00
parent ee17f6862c
commit e09ec81f1d
2 changed files with 79 additions and 62 deletions
+41 -30
View File
@@ -1,41 +1,47 @@
<script lang="ts"> <script lang="ts">
import SettingsCard from '$lib/components/SettingsCard.svelte'; import SettingsCard from '$lib/components/SettingsCard.svelte'
import type { ServoConfiguration, Servo } from '$lib/types/models'; import type { ServoConfiguration, Servo } from '$lib/types/models'
import Spinner from '$lib/components/Spinner.svelte'; import Spinner from '$lib/components/Spinner.svelte'
import { socket } from '$lib/stores'; import { socket } from '$lib/stores'
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte'
import { throttler as Throttler } from '$lib/utilities'; import { throttler as Throttler } from '$lib/utilities'
import { MotorOutline } from '$lib/components/icons'; import { MotorOutline } from '$lib/components/icons'
let isLoading = false; let isLoading = false
let active = $state(false); let active = $state(false)
let servoId = $state(0); let servoId = $state(0)
const throttler = new Throttler(); let allServos = $state(false)
const throttler = new Throttler()
const sweep = (event: any) => { const sweep = (event: any) => {
let channel = event.detail.channel; let channel = event.detail.channel
socket.sendEvent('servoConfiguration', { servos: [{ channel, sweep: true }] }); socket.sendEvent('servoConfiguration', { servos: [{ channel, sweep: true }] })
}; }
const activateServo = (event: any) => { const activateServo = (event: any) => {
socket.sendEvent('servoState', { active: 1 }); socket.sendEvent('servoState', { active: 1 })
}; }
const deactivateServo = (event: any) => { const deactivateServo = (event: any) => {
socket.sendEvent('servoState', { active: 0 }); socket.sendEvent('servoState', { active: 0 })
}; }
let pwm = $state(306); let pwm = $state(306)
const updatePWM = () => { const updatePWM = () => {
throttler.throttle(() => { throttler.throttle(() => {
socket.sendEvent('servoPWM', { servo_id: servoId, pwm }); socket.sendEvent('servoPWM', { servo_id: servoId, pwm })
}, 10); }, 10)
}; }
const toggleMode = () => {
servoId = allServos ? -1 : 0
}
</script> </script>
<SettingsCard collapsible={false}> <SettingsCard collapsible={false}>
@@ -43,7 +49,7 @@
<MotorOutline class="lex-shrink-0 mr-2 h-6 w-6 self-end" /> <MotorOutline class="lex-shrink-0 mr-2 h-6 w-6 self-end" />
{/snippet} {/snippet}
{#snippet title()} {#snippet title()}
<span >Servo</span> <span>Servo</span>
{/snippet} {/snippet}
{pwm} {pwm}
<input <input
@@ -52,23 +58,28 @@
max="600" max="600"
bind:value={pwm} bind:value={pwm}
oninput={updatePWM} oninput={updatePWM}
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" />
/>
{#if isLoading} {#if isLoading}
<Spinner /> <Spinner />
{:else} {:else}
<div class="flex flex-col"> <div class="flex flex-col">
<h2 class="text-lg">General servo configuration</h2> <h2 class="text-lg">General servo configuration</h2>
<span class="flex items-center gap-2"> <span>
<label for="servoId">Servo active {servoId}</label> <label for="mode">All servoes</label>
<input type="range" min="0" max="11" step="1" bind:value={servoId} /> <input type="checkbox" class="toggle" bind:checked={allServos} onchange={toggleMode} />
</span>
<span>
<label for="active">Active</label>
<input <input
type="checkbox" type="checkbox"
class="toggle" class="toggle"
bind:checked={active} bind:checked={active}
onchange={active ? activateServo : deactivateServo} onchange={active ? activateServo : deactivateServo} />
/> </span>
<span class="flex items-center gap-2">
<label for="servoId">Servo active {servoId}</label>
<input type="range" min="0" max="11" step="1" bind:value={servoId} />
</span> </span>
</div> </div>
{/if} {/if}
@@ -74,9 +74,15 @@ class ServoController : public StatefulService<ServoSettings> {
void servoEvent(JsonObject &root, int originId) { void servoEvent(JsonObject &root, int originId) {
control_state = SERVO_CONTROL_STATE::PWM; control_state = SERVO_CONTROL_STATE::PWM;
uint8_t servo_id = root["servo_id"]; int8_t servo_id = root["servo_id"];
int pwm = root["pwm"].as<int>(); uint16_t pwm = root["pwm"].as<uint16_t>();
pcaWrite(servo_id, pwm); if (servo_id < 0) {
uint16_t pwms[12];
std::fill_n(pwms, 12, pwm);
_pca.setMultiplePWM(pwms, 12);
} else {
_pca.setPWM(servo_id, 0, pwm);
}
ESP_LOGI("SERVO_CONTROLLER", "Setting servo %d to %d", servo_id, pwm); ESP_LOGI("SERVO_CONTROLLER", "Setting servo %d to %d", servo_id, pwm);
} }