smartknob状态机
254 2024-09-07 08:53
用状态机优化下面代码
if (reading >= lower - (upper - lower) && reading < upper + (upper - lower) * 2)
{
long value = CLAMP(reading, lower, upper);
press_value_unit = 1. * (value - lower) / (upper - lower);
static bool pressed;
static bool accumulatable;
static uint8_t press_count;
static uint8_t release_count;
if (!pressed && accumulatable && press_value_unit > 0.75)
{
accumulatable = false;
// snprintf(buf_, sizeof(buf_), "accumulatable: %d", accumulatable);
// log(buf_);
}
else if (!pressed && !accumulatable && press_value_unit > 0.75)
{
pressed = true;
accumulatable = true;
motor_task_.playHaptic(true);
// snprintf(buf_, sizeof(buf_), "pressed: %d \t accumulatable: %d", pressed, accumulatable);
// log(buf_);
}
else if (pressed && accumulatable && press_value_unit > 0.75)
{
press_count++;
// snprintf(buf_, sizeof(buf_), "press_count: %d", press_count);
// log(buf_);
}
else if (pressed && accumulatable && press_value_unit < 0.25)
{
accumulatable = false;
}
else if (pressed && !accumulatable && press_value_unit < 0.25)
{
release_count++;
// snprintf(buf_, sizeof(buf_), "release_count: %d", release_count);
// log(buf_);
if (press_count > 30 && release_count > 2)
{
changeConfigToZero();
press_count = 0;
// snprintf(buf_, sizeof(buf_), "配置0");
// log(buf_);
motor_task_.playHaptic(false);
pressed = false;
}
else if (press_count > 2 && release_count > 2)
{
changeConfig(true);
press_count = 0;
// snprintf(buf_, sizeof(buf_), "下一个配置");
// log(buf_);
motor_task_.playHaptic(false);
pressed = false;
}
}
else
{
release_count = 0;
}
}
为了优化这段代码,我们可以使用一个状态机来管理不同的状态和事件。状态机可以帮助我们更清晰地管理状态转换,并且使代码更加模块化和易于维护。下面是一个简化的状态机实现的示例:
首先,我们定义状态和事件:
```c
enum State {
STATE_IDLE,
STATE_PRESSED,
STATE_ACCUMULATING,
STATE_RELEASED
};
enum Event {
EVENT_PRESS,
EVENT_ACCUMULATE,
EVENT_RELEASE,
EVENT_IDLE
};
```
然后,我们定义一个结构体来保存状态机的状态:
```c
struct StateMachine {
State state;
bool accumulatable;
uint8_t press_count;
uint8_t release_count;
};
```
接下来,我们定义状态转换函数:
```c
void handleEvent(StateMachine *sm, Event event, double press_value_unit, long lower, long upper) {
long value = CLAMP(reading, lower, upper);
double press_value_unit = 1. * (value - lower) / (upper - lower);
switch (sm->state) {
case STATE_IDLE:
if (press_value_unit > 0.75) {
sm->state = STATE_PRESSED;
sm->accumulatable = true;
// log("Pressed");
}
break;
case STATE_PRESSED:
if (press_value_unit > 0.75) {
if (sm->accumulatable) {
sm->state = STATE_ACCUMULATING;
sm->press_count++;
// log("Accumulating");
}
} else if (press_value_unit < 0.25) {
sm->state = STATE_RELEASED;
sm->release_count++;
// log("Released");
}
break;
case STATE_ACCUMULATING:
if (press_value_unit > 0.75) {
sm->press_count++;
// log("Press count: ", sm->press_count);
} else if (press_value_unit < 0.25) {
sm->state = STATE_RELEASED;
sm->accumulatable = false;
// log("Released");
}
break;
case STATE_RELEASED:
if (press_value_unit < 0.25) {
if (sm->press_count > 30 && sm->release_count > 2) {
changeConfigToZero();
sm->press_count = 0;
// log("Config 0");
motor_task_.playHaptic(false);
} else if (sm->press_count > 2 && sm->release_count > 2) {
changeConfig(true);
sm->press_count = 0;
// log("Next config");
motor_task_.playHaptic(false);
}
sm->state = STATE_IDLE;
} else {
sm->release_count = 0;
}
break;
}
}
```
最后,我们在主循环中使用状态机:
```c
StateMachine sm = {STATE_IDLE, true, 0, 0};
while (true) {
// 假设 reading 是从传感器读取的值
double reading = getSensorReading();
if (reading >= lower - (upper - lower) && reading < upper + (upper - lower) * 2) {
handleEvent(&sm, EVENT_PRESS, reading, lower, upper);
} else {
handleEvent(&sm, EVENT_IDLE, 0, lower, upper);
}
// 其他循环逻辑...
}
```
这个状态机的实现将原始的 if-else 逻辑分解为不同的状态和事件处理函数,使得代码更加清晰和易于理解。每个状态和事件都有明确的定义,这有助于未来的维护和扩展。
全部评论