init
This commit is contained in:
commit
1d7af0615e
15 files changed
+942
No files matched your search
@@ -0,0 +1,97 @@
|
||||
#include <ESP32Servo.h>
|
||||
#include <Preferences.h>
|
||||
#include "app.h"
|
||||
#include "config.h"
|
||||
|
||||
static Servo servo;
|
||||
static Preferences prefs;
|
||||
|
||||
static int volumeToUs(uint8_t volume) {
|
||||
return map(volume, 0, 100, SERVO_MIN_US, SERVO_MAX_US);
|
||||
}
|
||||
|
||||
static void applyRelay(bool on) {
|
||||
digitalWrite(PIN_RELAY, on ? RELAY_ACTIVE_LEVEL : !RELAY_ACTIVE_LEVEL);
|
||||
}
|
||||
|
||||
// Owns the servo, the relay and NVS. Other tasks only send commands.
|
||||
void controlTask(void *arg) {
|
||||
pinMode(PIN_RELAY, OUTPUT);
|
||||
|
||||
prefs.begin("volume", false);
|
||||
AppState st;
|
||||
st.volume = prefs.getUChar("vol", 30);
|
||||
st.relay = prefs.getBool("relay", false);
|
||||
setState(st);
|
||||
applyRelay(st.relay);
|
||||
|
||||
servo.setPeriodHertz(50);
|
||||
int currentUs = volumeToUs(st.volume);
|
||||
servo.attach(PIN_SERVO, SERVO_MIN_US, SERVO_MAX_US);
|
||||
servo.writeMicroseconds(currentUs);
|
||||
TickType_t lastMove = xTaskGetTickCount();
|
||||
|
||||
bool dirty = false;
|
||||
TickType_t lastChange = 0;
|
||||
|
||||
Serial.printf("[control] restored volume=%u relay=%d\n", st.volume, st.relay);
|
||||
|
||||
for (;;) {
|
||||
int targetUs = volumeToUs(st.volume);
|
||||
bool moving = currentUs != targetUs;
|
||||
TickType_t wait = (moving || dirty || servo.attached())
|
||||
? pdMS_TO_TICKS(SERVO_UPDATE_MS)
|
||||
: portMAX_DELAY;
|
||||
|
||||
Command cmd;
|
||||
if (xQueueReceive(cmdQueue, &cmd, wait) == pdTRUE) {
|
||||
AppState prev = st;
|
||||
switch (cmd.type) {
|
||||
case CmdType::VolumeDelta:
|
||||
st.volume = constrain((int)st.volume + cmd.value, 0, 100);
|
||||
break;
|
||||
case CmdType::VolumeSet:
|
||||
st.volume = constrain((int)cmd.value, 0, 100);
|
||||
break;
|
||||
case CmdType::RelayToggle:
|
||||
st.relay = !st.relay;
|
||||
break;
|
||||
case CmdType::RelaySet:
|
||||
st.relay = cmd.value != 0;
|
||||
break;
|
||||
}
|
||||
if (st.relay != prev.relay) {
|
||||
applyRelay(st.relay);
|
||||
Serial.printf("[control] relay %s\n", st.relay ? "ON" : "OFF");
|
||||
}
|
||||
if (st.volume != prev.volume || st.relay != prev.relay) {
|
||||
setState(st);
|
||||
dirty = true;
|
||||
lastChange = xTaskGetTickCount();
|
||||
}
|
||||
targetUs = volumeToUs(st.volume);
|
||||
}
|
||||
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
|
||||
// Smooth servo movement toward the target
|
||||
if (currentUs != targetUs) {
|
||||
int diff = targetUs - currentUs;
|
||||
int step = constrain(diff, -SERVO_SPEED_US_PER_STEP, SERVO_SPEED_US_PER_STEP);
|
||||
currentUs += step;
|
||||
if (!servo.attached()) servo.attach(PIN_SERVO, SERVO_MIN_US, SERVO_MAX_US);
|
||||
servo.writeMicroseconds(currentUs);
|
||||
lastMove = now;
|
||||
} else if (servo.attached() && now - lastMove >= pdMS_TO_TICKS(SERVO_DETACH_IDLE_MS)) {
|
||||
servo.detach();
|
||||
}
|
||||
|
||||
// Delayed save to spare flash wear while the encoder is being turned
|
||||
if (dirty && now - lastChange >= pdMS_TO_TICKS(SAVE_DELAY_MS)) {
|
||||
prefs.putUChar("vol", st.volume);
|
||||
prefs.putBool("relay", st.relay);
|
||||
dirty = false;
|
||||
Serial.printf("[control] saved volume=%u relay=%d\n", st.volume, st.relay);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user