ESPHome 2026.5.1
Loading...
Searching...
No Matches
servo.cpp
Go to the documentation of this file.
1#include "servo.h"
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
4#include <cinttypes>
5
6namespace esphome::servo {
7
8static const char *const TAG = "servo";
9
10uint32_t global_servo_id = 1911044085ULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
11
13 ESP_LOGCONFIG(TAG,
14 "Servo:\n"
15 " Idle Level: %.1f%%\n"
16 " Min Level: %.1f%%\n"
17 " Max Level: %.1f%%\n"
18 " Auto-detach time: %" PRIu32 " ms\n"
19 " Run duration: %" PRIu32 " ms",
20 this->idle_level_ * 100.0f, this->min_level_ * 100.0f, this->max_level_ * 100.0f,
22}
23
25 float v;
26 if (this->restore_) {
28 global_servo_id++;
29 if (this->rtc_.load(&v)) {
30 this->target_value_ = v;
31 this->internal_write(v);
32 this->state_ = STATE_ATTACHED;
33 this->start_millis_ = millis();
34 return;
35 }
36 }
37 this->detach();
38}
39
41 // check if auto_detach_time_ is set and servo reached target
42 if (this->auto_detach_time_ && this->state_ == STATE_TARGET_REACHED) {
43 if (millis() - this->start_millis_ > this->auto_detach_time_) {
44 this->detach();
45 this->start_millis_ = 0;
46 ESP_LOGD(TAG, "Detached on auto_detach_time");
47 }
48 }
49 if (this->target_value_ != this->current_value_ && this->state_ == STATE_ATTACHED) {
50 if (this->transition_length_) {
51 float new_value;
52 float travel_diff = this->target_value_ - this->source_value_;
53 uint32_t target_runtime = abs((int) ((travel_diff) * this->transition_length_ * 1.0f / 2.0f));
54 uint32_t current_runtime = millis() - this->start_millis_;
55 float percentage_run = current_runtime * 1.0f / target_runtime * 1.0f;
56 if (percentage_run > 1.0f) {
57 percentage_run = 1.0f;
58 }
59 new_value = this->target_value_ - (1.0f - percentage_run) * (this->target_value_ - this->source_value_);
60 this->internal_write(new_value);
61 } else {
62 this->internal_write(this->target_value_);
63 }
64 }
65 if (this->target_value_ == this->current_value_ && this->state_ == STATE_ATTACHED) {
67 this->start_millis_ = millis(); // set current stamp for potential auto_detach_time_ check
68 ESP_LOGD(TAG, "Reached target");
69 }
70}
71
72void Servo::write(float value) {
73 value = clamp(value, -1.0f, 1.0f);
74 if ((this->state_ == STATE_DETACHED) && (this->target_value_ == value)) {
75 this->internal_write(value);
76 } else {
77 this->save_level_(value);
78 }
79 this->target_value_ = value;
80 this->source_value_ = this->current_value_;
81 this->state_ = STATE_ATTACHED;
82 this->start_millis_ = millis();
83 ESP_LOGD(TAG, "New target: %f", value);
84}
85
86void Servo::internal_write(float value) {
87 value = clamp(value, -1.0f, 1.0f);
88 float level;
89 if (value < 0.0) {
90 level = std::lerp(this->idle_level_, this->min_level_, -value);
91 } else {
92 level = std::lerp(this->idle_level_, this->max_level_, value);
93 }
94 this->output_->set_level(level);
95 this->current_value_ = value;
96}
97
99 this->state_ = STATE_DETACHED;
100 this->output_->set_level(0.0f);
101}
102
103void Servo::save_level_(float v) {
104 if (this->restore_)
105 this->rtc_.save(&v);
106}
107
108} // namespace esphome::servo
void set_level(float state)
Set the level of this float output, this is called from the front-end.
uint32_t start_millis_
Definition servo.h:46
void loop() override
Definition servo.cpp:40
uint32_t transition_length_
Definition servo.h:40
void write(float value)
Definition servo.cpp:72
uint32_t auto_detach_time_
Definition servo.h:39
void setup() override
Definition servo.cpp:24
void dump_config() override
Definition servo.cpp:12
output::FloatOutput * output_
Definition servo.h:34
void internal_write(float value)
Definition servo.cpp:86
ESPPreferenceObject rtc_
Definition servo.h:41
void save_level_(float v)
Definition servo.cpp:103
uint32_t global_servo_id
Definition servo.cpp:10
ESPPreferences * global_preferences
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:28
static void uint32_t
ESPPreferenceObject make_preference(size_t, uint32_t, bool)
Definition preferences.h:24