智能洗衣机洗涤模式控制系统——从传感器到变频电机的完整技术链路

前言

前段时间帮一个家电厂做洗衣机控制板的方案,从水位检测到变频电机驱动,各种洗涤模式的逻辑都过了一遍。说实话,现代洗衣机的功能比想象中复杂得多,光洗涤模式就有十几种,每种模式背后都是一套精细的控制算法。

今天把洗衣机控制系统的技术细节整理出来,从硬件到软件,从传感器到执行器,希望能帮到对家电控制感兴趣的朋友。

系统整体架构

复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                      智能洗衣机控制系统架构                                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                      用户交互层                                      │  │
│   │   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                │  │
│   │   │  触摸屏/    │  │   旋钮      │  │   WiFi/     │                │  │
│   │   │  LED显示    │  │   按键      │  │   蓝牙模块   │                │  │
│   │   └──────┬──────┘  └──────┬──────┘  └──────┬──────┘                │  │
│   └──────────┼────────────────┼────────────────┼────────────────────────┘  │
│              │                │                │                           │
│              └────────────────┴────────┬───────┘                           │
│                                        │                                   │
│   ┌────────────────────────────────────┴────────────────────────────────┐  │
│   │                      主控MCU (STM32/ESP32)                          │  │
│   │                                                                     │  │
│   │   ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐      │  │
│   │   │ 洗涤模式  │  │ 安全保护  │  │ 故障诊断  │  │ 通信管理  │      │  │
│   │   │ 状态机    │  │ 模块      │  │ 模块      │  │ 模块      │      │  │
│   │   └───────────┘  └───────────┘  └───────────┘  └───────────┘      │  │
│   └────────────────────────────────────┬────────────────────────────────┘  │
│                                        │                                   │
│         ┌──────────────────────────────┼──────────────────────────────┐    │
│         │                              │                              │    │
│         ▼                              ▼                              ▼    │
│   ┌───────────────┐            ┌───────────────┐            ┌───────────────┐
│   │   传感器层    │            │   执行器层    │            │   电源管理    │
│   │               │            │               │            │               │
│   │ - 水位传感器  │            │ - 变频电机    │            │ - AC/DC转换  │
│   │ - 温度传感器  │            │ - 进水阀      │            │ - 继电器驱动 │
│   │ - 门锁检测    │            │ - 排水泵      │            │ - 过流保护   │
│   │ - 振动传感器  │            │ - 加热器      │            │               │
│   │ - 浊度传感器  │            │ - 门锁电机    │            │               │
│   │ - 称重传感器  │            │ - 蜂鸣器      │            │               │
│   └───────────────┘            └───────────────┘            └───────────────┘
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

硬件配置(典型滚筒洗衣机):
- 主控: STM32F103/ESP32
- 电机: BLDC变频电机 (300-1400rpm)
- 加热器: 1800-2000W PTC/电热管
- 进水阀: 2个电磁阀 (冷水/热水)
- 排水泵: 30-40W
- 水位传感器: 气压式
- 温度传感器: NTC 10K

传感器系统

水位检测

c 复制代码
/**
 * 水位传感器 - 气压式原理
 * 
 * 水位上升 → 气压管内气压增大 → 压力传感器检测
 * 输出: 频率信号或模拟电压
 */

#include "stm32f1xx_hal.h"

// 水位等级定义 (单位: mm 水柱压力对应值)
typedef enum {
    WATER_LEVEL_EMPTY = 0,
    WATER_LEVEL_LOW = 120,      // 低水位 ~15L
    WATER_LEVEL_MEDIUM = 180,   // 中水位 ~30L
    WATER_LEVEL_HIGH = 240,     // 高水位 ~45L
    WATER_LEVEL_FULL = 300,     // 满水位 ~55L
    WATER_LEVEL_OVERFLOW = 350  // 溢出警戒
} WaterLevel_t;

// 水位传感器配置
typedef struct {
    uint16_t adc_channel;
    uint16_t adc_min;           // 空桶ADC值
    uint16_t adc_max;           // 满水ADC值
    uint16_t filter_samples;    // 滤波采样数
    uint16_t overflow_threshold;
} WaterLevelConfig_t;

// 水位传感器状态
typedef struct {
    uint16_t raw_adc;
    uint16_t filtered_adc;
    uint16_t water_level_mm;    // 水位高度 (mm)
    float water_volume_L;       // 水量 (升)
    uint16_t adc_buffer[16];    // 滤波缓冲
    uint8_t buffer_index;
} WaterLevelState_t;

static WaterLevelConfig_t water_config = {
    .adc_channel = ADC_CHANNEL_0,
    .adc_min = 500,
    .adc_max = 3500,
    .filter_samples = 16,
    .overflow_threshold = 3600
};

static WaterLevelState_t water_state;

/**
 * 读取水位ADC并滤波
 */
uint16_t water_level_read_filtered(void)
{
    // 读取ADC
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    uint16_t adc_value = HAL_ADC_GetValue(&hadc1);
    
    // 滑动平均滤波
    water_state.adc_buffer[water_state.buffer_index] = adc_value;
    water_state.buffer_index = (water_state.buffer_index + 1) % water_config.filter_samples;
    
    uint32_t sum = 0;
    for (int i = 0; i < water_config.filter_samples; i++) {
        sum += water_state.adc_buffer[i];
    }
    
    water_state.filtered_adc = sum / water_config.filter_samples;
    water_state.raw_adc = adc_value;
    
    return water_state.filtered_adc;
}

/**
 * ADC转换为水位高度
 */
uint16_t water_level_get_mm(void)
{
    uint16_t adc = water_level_read_filtered();
    
    // 线性映射
    if (adc <= water_config.adc_min) {
        water_state.water_level_mm = 0;
    } else if (adc >= water_config.adc_max) {
        water_state.water_level_mm = WATER_LEVEL_FULL;
    } else {
        water_state.water_level_mm = (uint16_t)(
            (adc - water_config.adc_min) * WATER_LEVEL_FULL / 
            (water_config.adc_max - water_config.adc_min)
        );
    }
    
    return water_state.water_level_mm;
}

/**
 * 水位转换为水量 (根据桶形状计算)
 * 滚筒洗衣机内筒近似圆柱形
 */
float water_level_get_volume(void)
{
    uint16_t level_mm = water_level_get_mm();
    
    // 内筒参数 (典型10kg滚筒)
    const float drum_radius = 0.24f;  // 内筒半径 240mm
    const float drum_length = 0.45f;  // 内筒深度 450mm
    
    // 圆柱形水量计算 (简化,实际需考虑倾斜)
    // V = L × (R²×arccos((R-h)/R) - (R-h)×√(2Rh-h²))
    float h = level_mm / 1000.0f;  // 转换为米
    float R = drum_radius;
    float L = drum_length;
    
    if (h <= 0) return 0;
    if (h >= 2 * R) h = 2 * R;
    
    float ratio = (R - h) / R;
    if (ratio > 1) ratio = 1;
    if (ratio < -1) ratio = -1;
    
    float area = R * R * acosf(ratio) - (R - h) * sqrtf(2 * R * h - h * h);
    float volume = area * L * 1000;  // 转换为升
    
    water_state.water_volume_L = volume;
    return volume;
}

/**
 * 检查水位是否达到目标
 */
int water_level_reached(WaterLevel_t target)
{
    uint16_t current = water_level_get_mm();
    return (current >= target - 10);  // 允许10mm误差
}

/**
 * 检查是否溢出
 */
int water_level_overflow(void)
{
    return (water_state.filtered_adc > water_config.overflow_threshold);
}

温度检测

c 复制代码
/**
 * 温度传感器 - NTC热敏电阻
 * 
 * 典型: 10K NTC (25°C时10KΩ)
 * B值: 3950
 */

typedef struct {
    uint16_t adc_channel;
    float beta;             // B值
    float r_ref;            // 参考电阻 (25°C)
    float t_ref;            // 参考温度 (K)
    float r_series;         // 串联电阻
    float vref;             // 参考电压
} NTCConfig_t;

typedef struct {
    uint16_t raw_adc;
    float resistance;       // 当前电阻值
    float temperature;      // 温度 (°C)
    float filtered_temp;    // 滤波后温度
} NTCState_t;

static NTCConfig_t ntc_config = {
    .adc_channel = ADC_CHANNEL_1,
    .beta = 3950.0f,
    .r_ref = 10000.0f,      // 10K
    .t_ref = 298.15f,       // 25°C = 298.15K
    .r_series = 10000.0f,   // 10K串联电阻
    .vref = 3.3f
};

static NTCState_t ntc_water;   // 水温传感器
static NTCState_t ntc_heater;  // 加热器温度传感器

/**
 * 读取NTC温度
 * 
 * 电路: VCC --- R_series --- ADC --- NTC --- GND
 */
float ntc_read_temperature(NTCState_t *ntc, NTCConfig_t *config)
{
    // 读取ADC
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    ntc->raw_adc = HAL_ADC_GetValue(&hadc1);
    
    // ADC转电压
    float voltage = (ntc->raw_adc / 4096.0f) * config->vref;
    
    // 计算NTC电阻
    // V = Vref × Rntc / (Rseries + Rntc)
    // Rntc = Rseries × V / (Vref - V)
    if (voltage >= config->vref - 0.01f) {
        ntc->resistance = 1000000;  // 开路
    } else if (voltage <= 0.01f) {
        ntc->resistance = 0;  // 短路
    } else {
        ntc->resistance = config->r_series * voltage / (config->vref - voltage);
    }
    
    // Steinhart-Hart方程简化版 (B参数方程)
    // 1/T = 1/T_ref + (1/B) × ln(R/R_ref)
    if (ntc->resistance > 0) {
        float ln_ratio = logf(ntc->resistance / config->r_ref);
        float inv_t = 1.0f / config->t_ref + ln_ratio / config->beta;
        ntc->temperature = (1.0f / inv_t) - 273.15f;  // 转摄氏度
    } else {
        ntc->temperature = 150.0f;  // 异常高温
    }
    
    // 一阶低通滤波
    static float alpha = 0.1f;
    ntc->filtered_temp = ntc->filtered_temp * (1 - alpha) + ntc->temperature * alpha;
    
    return ntc->filtered_temp;
}

/**
 * 读取水温
 */
float get_water_temperature(void)
{
    return ntc_read_temperature(&ntc_water, &ntc_config);
}

/**
 * 读取加热器温度 (用于过热保护)
 */
float get_heater_temperature(void)
{
    return ntc_read_temperature(&ntc_heater, &ntc_config);
}

称重传感器

c 复制代码
/**
 * 称重传感器 - 检测衣物重量
 * 
 * 使用应变片 + HX711 ADC
 * 用于自动判断水位和洗涤时间
 */

#include "hx711.h"

typedef struct {
    GPIO_TypeDef *dout_port;
    uint16_t dout_pin;
    GPIO_TypeDef *sck_port;
    uint16_t sck_pin;
    int32_t offset;         // 零点偏移
    float scale;            // 比例系数 (g/count)
} HX711Config_t;

typedef struct {
    int32_t raw_value;
    float weight_g;         // 重量 (克)
    float weight_kg;        // 重量 (千克)
    uint8_t stable;         // 稳定标志
} WeightState_t;

static HX711Config_t hx711_config = {
    .dout_port = GPIOB,
    .dout_pin = GPIO_PIN_0,
    .sck_port = GPIOB,
    .sck_pin = GPIO_PIN_1,
    .offset = 0,
    .scale = 0.5f  // 需要标定
};

static WeightState_t weight_state;

/**
 * HX711读取原始值
 */
int32_t hx711_read_raw(void)
{
    // 等待数据准备好
    while (HAL_GPIO_ReadPin(hx711_config.dout_port, hx711_config.dout_pin));
    
    int32_t value = 0;
    
    // 读取24位数据
    for (int i = 0; i < 24; i++) {
        HAL_GPIO_WritePin(hx711_config.sck_port, hx711_config.sck_pin, GPIO_PIN_SET);
        value = value << 1;
        HAL_GPIO_WritePin(hx711_config.sck_port, hx711_config.sck_pin, GPIO_PIN_RESET);
        
        if (HAL_GPIO_ReadPin(hx711_config.dout_port, hx711_config.dout_pin)) {
            value++;
        }
    }
    
    // 第25个脉冲设置增益
    HAL_GPIO_WritePin(hx711_config.sck_port, hx711_config.sck_pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(hx711_config.sck_port, hx711_config.sck_pin, GPIO_PIN_RESET);
    
    // 符号扩展
    if (value & 0x800000) {
        value |= 0xFF000000;
    }
    
    return value;
}

/**
 * 读取衣物重量
 */
float weight_read_kg(void)
{
    // 多次采样取平均
    int32_t sum = 0;
    const int samples = 10;
    
    for (int i = 0; i < samples; i++) {
        sum += hx711_read_raw();
        HAL_Delay(10);
    }
    
    weight_state.raw_value = sum / samples;
    weight_state.weight_g = (weight_state.raw_value - hx711_config.offset) * hx711_config.scale;
    weight_state.weight_kg = weight_state.weight_g / 1000.0f;
    
    // 稳定性判断
    static float last_weight = 0;
    weight_state.stable = (fabsf(weight_state.weight_kg - last_weight) < 0.1f);
    last_weight = weight_state.weight_kg;
    
    return weight_state.weight_kg;
}

/**
 * 根据衣物重量推荐水位
 */
WaterLevel_t weight_recommend_water_level(float weight_kg)
{
    if (weight_kg < 2.0f) {
        return WATER_LEVEL_LOW;
    } else if (weight_kg < 4.0f) {
        return WATER_LEVEL_MEDIUM;
    } else if (weight_kg < 6.0f) {
        return WATER_LEVEL_HIGH;
    } else {
        return WATER_LEVEL_FULL;
    }
}

/**
 * 零点校准
 */
void weight_tare(void)
{
    int32_t sum = 0;
    const int samples = 20;
    
    for (int i = 0; i < samples; i++) {
        sum += hx711_read_raw();
        HAL_Delay(50);
    }
    
    hx711_config.offset = sum / samples;
}

门锁与安全检测

c 复制代码
/**
 * 门锁系统
 * 
 * 电磁门锁 + 门开关检测
 */

typedef enum {
    DOOR_STATE_OPEN,
    DOOR_STATE_CLOSED,
    DOOR_STATE_LOCKED,
    DOOR_STATE_ERROR
} DoorState_t;

typedef struct {
    GPIO_TypeDef *lock_port;
    uint16_t lock_pin;
    GPIO_TypeDef *switch_port;
    uint16_t switch_pin;
    GPIO_TypeDef *feedback_port;  // 锁舌到位检测
    uint16_t feedback_pin;
} DoorLockConfig_t;

typedef struct {
    DoorState_t state;
    uint8_t switch_closed;      // 门开关状态
    uint8_t lock_engaged;       // 锁舌到位
    uint32_t lock_time;         // 上锁时间
    uint8_t lock_failed;        // 锁定失败标志
} DoorLockState_t;

static DoorLockConfig_t door_config;
static DoorLockState_t door_state;

/**
 * 检测门状态
 */
DoorState_t door_get_state(void)
{
    // 读取门开关
    door_state.switch_closed = !HAL_GPIO_ReadPin(
        door_config.switch_port, door_config.switch_pin
    );
    
    // 读取锁舌状态
    door_state.lock_engaged = !HAL_GPIO_ReadPin(
        door_config.feedback_port, door_config.feedback_pin
    );
    
    if (!door_state.switch_closed) {
        door_state.state = DOOR_STATE_OPEN;
    } else if (door_state.lock_engaged) {
        door_state.state = DOOR_STATE_LOCKED;
    } else {
        door_state.state = DOOR_STATE_CLOSED;
    }
    
    return door_state.state;
}

/**
 * 锁门
 */
int door_lock(void)
{
    // 检查门是否关闭
    if (!door_state.switch_closed) {
        return -1;  // 门未关
    }
    
    // 启动电磁锁
    HAL_GPIO_WritePin(door_config.lock_port, door_config.lock_pin, GPIO_PIN_SET);
    door_state.lock_time = HAL_GetTick();
    
    // 等待锁舌到位 (最多3秒)
    while (!door_state.lock_engaged && 
           (HAL_GetTick() - door_state.lock_time) < 3000) {
        door_get_state();
        HAL_Delay(100);
    }
    
    if (!door_state.lock_engaged) {
        // 锁定失败
        HAL_GPIO_WritePin(door_config.lock_port, door_config.lock_pin, GPIO_PIN_RESET);
        door_state.lock_failed = 1;
        return -2;
    }
    
    door_state.state = DOOR_STATE_LOCKED;
    return 0;
}

/**
 * 解锁门
 * 
 * 注意:高温或高速旋转时不能解锁
 */
int door_unlock(float water_temp, int motor_running)
{
    // 安全检查
    if (water_temp > 55.0f) {
        return -1;  // 水温过高
    }
    
    if (motor_running) {
        return -2;  // 电机运行中
    }
    
    // 释放电磁锁
    HAL_GPIO_WritePin(door_config.lock_port, door_config.lock_pin, GPIO_PIN_RESET);
    
    // 等待锁舌释放
    HAL_Delay(500);
    
    door_get_state();
    
    if (door_state.lock_engaged) {
        return -3;  // 解锁失败
    }
    
    door_state.state = DOOR_STATE_CLOSED;
    return 0;
}

执行器控制

变频电机驱动

c 复制代码
/**
 * BLDC变频电机控制
 * 
 * 滚筒洗衣机使用直驱或皮带传动BLDC电机
 * 转速范围: 0-1400 RPM
 */

typedef enum {
    MOTOR_DIR_CW,       // 顺时针
    MOTOR_DIR_CCW,      // 逆时针
    MOTOR_DIR_STOP
} MotorDirection_t;

typedef struct {
    // PWM配置
    TIM_HandleTypeDef *htim;
    uint32_t channel;
    
    // 方向控制GPIO
    GPIO_TypeDef *dir_port;
    uint16_t dir_pin;
    
    // 使能控制
    GPIO_TypeDef *en_port;
    uint16_t en_pin;
    
    // 转速反馈 (霍尔传感器)
    TIM_HandleTypeDef *htim_hall;
    uint8_t pole_pairs;     // 极对数
    
    // PID参数
    float kp, ki, kd;
    
    // 限制
    uint16_t max_rpm;
    uint16_t min_rpm;
    float max_accel;        // 最大加速度 RPM/s
} MotorConfig_t;

typedef struct {
    MotorDirection_t direction;
    uint16_t target_rpm;
    uint16_t actual_rpm;
    float duty_cycle;
    
    // PID状态
    float integral;
    float last_error;
    
    // 保护状态
    uint8_t overcurrent;
    uint8_t overtemp;
    uint8_t stall;
    
    // 运行统计
    uint32_t run_time_ms;
    uint32_t start_time;
} MotorState_t;

static MotorConfig_t motor_config;
static MotorState_t motor_state;

/**
 * 读取电机转速 (通过霍尔传感器)
 */
uint16_t motor_read_rpm(void)
{
    // 读取霍尔脉冲频率
    uint32_t hall_freq = __HAL_TIM_GET_COUNTER(motor_config.htim_hall);
    __HAL_TIM_SET_COUNTER(motor_config.htim_hall, 0);
    
    // 频率转RPM
    // RPM = (freq × 60) / (pole_pairs × 6)
    // 6 = 每个电周期的霍尔变化次数
    if (hall_freq > 0) {
        motor_state.actual_rpm = (hall_freq * 60) / (motor_config.pole_pairs * 6);
    } else {
        motor_state.actual_rpm = 0;
    }
    
    return motor_state.actual_rpm;
}

/**
 * PID转速控制
 */
float motor_pid_control(uint16_t target_rpm, uint16_t actual_rpm, float dt)
{
    float error = (float)target_rpm - (float)actual_rpm;
    
    // 比例项
    float p_term = motor_config.kp * error;
    
    // 积分项 (带限幅)
    motor_state.integral += error * dt;
    if (motor_state.integral > 100) motor_state.integral = 100;
    if (motor_state.integral < -100) motor_state.integral = -100;
    float i_term = motor_config.ki * motor_state.integral;
    
    // 微分项
    float d_term = motor_config.kd * (error - motor_state.last_error) / dt;
    motor_state.last_error = error;
    
    // 输出
    float output = p_term + i_term + d_term;
    
    // 限幅
    if (output > 100) output = 100;
    if (output < 0) output = 0;
    
    return output;
}

/**
 * 设置电机转速
 */
void motor_set_speed(uint16_t rpm, MotorDirection_t dir)
{
    // 限制最大转速
    if (rpm > motor_config.max_rpm) {
        rpm = motor_config.max_rpm;
    }
    
    motor_state.target_rpm = rpm;
    motor_state.direction = dir;
    
    // 设置方向
    if (dir == MOTOR_DIR_CW) {
        HAL_GPIO_WritePin(motor_config.dir_port, motor_config.dir_pin, GPIO_PIN_SET);
    } else if (dir == MOTOR_DIR_CCW) {
        HAL_GPIO_WritePin(motor_config.dir_port, motor_config.dir_pin, GPIO_PIN_RESET);
    }
    
    // 启动或停止
    if (rpm > 0 && dir != MOTOR_DIR_STOP) {
        HAL_GPIO_WritePin(motor_config.en_port, motor_config.en_pin, GPIO_PIN_SET);
        motor_state.start_time = HAL_GetTick();
    } else {
        HAL_GPIO_WritePin(motor_config.en_port, motor_config.en_pin, GPIO_PIN_RESET);
        motor_state.target_rpm = 0;
    }
}

/**
 * 电机控制循环 (在定时器中断中调用)
 */
void motor_control_loop(void)
{
    static uint32_t last_time = 0;
    uint32_t now = HAL_GetTick();
    float dt = (now - last_time) / 1000.0f;
    last_time = now;
    
    if (dt <= 0 || dt > 0.1f) return;
    
    // 读取实际转速
    motor_read_rpm();
    
    // 加速度限制 (软启动)
    static uint16_t ramped_target = 0;
    float max_delta = motor_config.max_accel * dt;
    
    if (motor_state.target_rpm > ramped_target) {
        ramped_target += (uint16_t)max_delta;
        if (ramped_target > motor_state.target_rpm) {
            ramped_target = motor_state.target_rpm;
        }
    } else if (motor_state.target_rpm < ramped_target) {
        if (ramped_target > max_delta) {
            ramped_target -= (uint16_t)max_delta;
        } else {
            ramped_target = 0;
        }
    }
    
    // PID计算
    motor_state.duty_cycle = motor_pid_control(ramped_target, motor_state.actual_rpm, dt);
    
    // 设置PWM
    uint32_t pulse = (uint32_t)(motor_state.duty_cycle * motor_config.htim->Init.Period / 100);
    __HAL_TIM_SET_COMPARE(motor_config.htim, motor_config.channel, pulse);
    
    // 更新运行时间
    if (motor_state.actual_rpm > 0) {
        motor_state.run_time_ms = now - motor_state.start_time;
    }
    
    // 堵转检测
    if (motor_state.target_rpm > 50 && motor_state.actual_rpm < 10 && 
        motor_state.run_time_ms > 3000) {
        motor_state.stall = 1;
        motor_set_speed(0, MOTOR_DIR_STOP);  // 停机保护
    }
}

/**
 * 洗涤动作 - 正反转摆动
 */
void motor_wash_action(uint16_t rpm, uint16_t cw_time_ms, uint16_t ccw_time_ms, 
                       uint16_t pause_time_ms)
{
    // 顺时针
    motor_set_speed(rpm, MOTOR_DIR_CW);
    HAL_Delay(cw_time_ms);
    
    // 暂停
    motor_set_speed(0, MOTOR_DIR_STOP);
    HAL_Delay(pause_time_ms);
    
    // 逆时针
    motor_set_speed(rpm, MOTOR_DIR_CCW);
    HAL_Delay(ccw_time_ms);
    
    // 暂停
    motor_set_speed(0, MOTOR_DIR_STOP);
    HAL_Delay(pause_time_ms);
}

加热控制

c 复制代码
/**
 * 加热系统控制
 * 
 * PTC加热器或电热管,通过继电器/可控硅控制
 */

typedef struct {
    GPIO_TypeDef *relay_port;
    uint16_t relay_pin;
    float max_power_w;          // 最大功率
    float temp_threshold_high;  // 过热保护温度
    float temp_threshold_low;   // 恢复温度
} HeaterConfig_t;

typedef struct {
    uint8_t enabled;
    float target_temp;
    float current_temp;
    float heater_temp;          // 加热器本体温度
    uint8_t heating;            // 正在加热
    uint8_t overtemp;           // 过热保护
    uint32_t heat_time_ms;      // 本次加热时间
    uint32_t total_heat_time;   // 总加热时间
} HeaterState_t;

static HeaterConfig_t heater_config = {
    .relay_port = GPIOC,
    .relay_pin = GPIO_PIN_0,
    .max_power_w = 2000,
    .temp_threshold_high = 90,
    .temp_threshold_low = 80
};

static HeaterState_t heater_state;

/**
 * 加热开关控制
 */
void heater_set(uint8_t on)
{
    if (on && !heater_state.overtemp) {
        HAL_GPIO_WritePin(heater_config.relay_port, heater_config.relay_pin, GPIO_PIN_SET);
        heater_state.heating = 1;
    } else {
        HAL_GPIO_WritePin(heater_config.relay_port, heater_config.relay_pin, GPIO_PIN_RESET);
        heater_state.heating = 0;
    }
}

/**
 * 温度控制 - 带滞环
 */
void heater_control_loop(void)
{
    // 读取温度
    heater_state.current_temp = get_water_temperature();
    heater_state.heater_temp = get_heater_temperature();
    
    // 过热保护检查
    if (heater_state.heater_temp > heater_config.temp_threshold_high) {
        heater_state.overtemp = 1;
        heater_set(0);
        return;
    }
    
    // 过热恢复
    if (heater_state.overtemp && 
        heater_state.heater_temp < heater_config.temp_threshold_low) {
        heater_state.overtemp = 0;
    }
    
    if (!heater_state.enabled) {
        heater_set(0);
        return;
    }
    
    // 滞环控制
    float hysteresis = 2.0f;  // 2度滞环
    
    if (heater_state.current_temp < heater_state.target_temp - hysteresis) {
        heater_set(1);
    } else if (heater_state.current_temp > heater_state.target_temp + hysteresis) {
        heater_set(0);
    }
    // 在滞环范围内保持当前状态
}

/**
 * 设置目标温度
 */
void heater_set_target(float temp)
{
    // 限制温度范围
    if (temp < 20) temp = 20;
    if (temp > 95) temp = 95;
    
    heater_state.target_temp = temp;
    heater_state.enabled = 1;
}

/**
 * 关闭加热
 */
void heater_disable(void)
{
    heater_state.enabled = 0;
    heater_set(0);
}

/**
 * 估算加热时间
 */
uint32_t heater_estimate_time(float current_temp, float target_temp, float water_volume_L)
{
    if (current_temp >= target_temp) return 0;
    
    float delta_temp = target_temp - current_temp;
    
    // Q = m × c × ΔT
    // t = Q / P
    // 水的比热容 c = 4186 J/(kg·°C)
    float energy_j = water_volume_L * 4186 * delta_temp;
    float time_s = energy_j / (heater_config.max_power_w * 0.9f);  // 90%效率
    
    return (uint32_t)(time_s * 1000);  // 转毫秒
}

进水阀与排水泵

c 复制代码
/**
 * 进水阀控制
 * 
 * 通常有冷水阀和热水阀(部分机型)
 */

typedef enum {
    INLET_VALVE_COLD,
    INLET_VALVE_HOT,
    INLET_VALVE_BOTH,
    INLET_VALVE_NONE
} InletValve_t;

typedef struct {
    GPIO_TypeDef *cold_port;
    uint16_t cold_pin;
    GPIO_TypeDef *hot_port;
    uint16_t hot_pin;
} InletValveConfig_t;

static InletValveConfig_t inlet_config;

/**
 * 控制进水阀
 */
void inlet_valve_set(InletValve_t valve)
{
    switch (valve) {
    case INLET_VALVE_COLD:
        HAL_GPIO_WritePin(inlet_config.cold_port, inlet_config.cold_pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(inlet_config.hot_port, inlet_config.hot_pin, GPIO_PIN_RESET);
        break;
    case INLET_VALVE_HOT:
        HAL_GPIO_WritePin(inlet_config.cold_port, inlet_config.cold_pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(inlet_config.hot_port, inlet_config.hot_pin, GPIO_PIN_SET);
        break;
    case INLET_VALVE_BOTH:
        HAL_GPIO_WritePin(inlet_config.cold_port, inlet_config.cold_pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(inlet_config.hot_port, inlet_config.hot_pin, GPIO_PIN_SET);
        break;
    case INLET_VALVE_NONE:
    default:
        HAL_GPIO_WritePin(inlet_config.cold_port, inlet_config.cold_pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(inlet_config.hot_port, inlet_config.hot_pin, GPIO_PIN_RESET);
        break;
    }
}

/**
 * 排水泵控制
 */
typedef struct {
    GPIO_TypeDef *pump_port;
    uint16_t pump_pin;
} DrainPumpConfig_t;

static DrainPumpConfig_t drain_config;

void drain_pump_set(uint8_t on)
{
    HAL_GPIO_WritePin(drain_config.pump_port, drain_config.pump_pin, 
                      on ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

/**
 * 进水到指定水位
 */
int fill_water_to_level(WaterLevel_t target, uint32_t timeout_ms)
{
    uint32_t start = HAL_GetTick();
    
    inlet_valve_set(INLET_VALVE_COLD);
    
    while (!water_level_reached(target)) {
        // 超时检查
        if (HAL_GetTick() - start > timeout_ms) {
            inlet_valve_set(INLET_VALVE_NONE);
            return -1;  // 进水超时
        }
        
        // 溢出检查
        if (water_level_overflow()) {
            inlet_valve_set(INLET_VALVE_NONE);
            return -2;  // 溢出
        }
        
        HAL_Delay(100);
    }
    
    inlet_valve_set(INLET_VALVE_NONE);
    return 0;
}

/**
 * 排水到空
 */
int drain_water(uint32_t timeout_ms)
{
    uint32_t start = HAL_GetTick();
    
    drain_pump_set(1);
    
    while (water_level_get_mm() > 10) {  // 允许少量残留
        if (HAL_GetTick() - start > timeout_ms) {
            drain_pump_set(0);
            return -1;  // 排水超时
        }
        
        HAL_Delay(100);
    }
    
    // 多排几秒确保排干
    HAL_Delay(5000);
    drain_pump_set(0);
    
    return 0;
}

洗涤模式定义

模式参数结构

c 复制代码
/**
 * 洗涤模式参数定义
 */

// 洗涤阶段
typedef enum {
    WASH_PHASE_PREWASH,         // 预洗
    WASH_PHASE_MAIN_WASH,       // 主洗
    WASH_PHASE_RINSE,           // 漂洗
    WASH_PHASE_SPIN,            // 脱水
    WASH_PHASE_DRY              // 烘干(部分机型)
} WashPhase_t;

// 单个洗涤阶段参数
typedef struct {
    WashPhase_t phase;
    
    // 水位和温度
    WaterLevel_t water_level;
    float water_temp;           // 0 = 不加热
    
    // 电机参数
    uint16_t motor_rpm;
    uint16_t rotate_time_ms;    // 单次旋转时间
    uint16_t pause_time_ms;     // 暂停时间
    
    // 时间
    uint32_t duration_ms;       // 阶段持续时间
    
    // 特殊标志
    uint8_t drain_after;        // 结束后排水
    uint8_t add_detergent;      // 是否投放洗涤剂
    uint8_t gentle_mode;        // 轻柔模式
} WashPhaseConfig_t;

// 完整洗涤程序
typedef struct {
    char name[32];
    
    // 阶段配置
    WashPhaseConfig_t phases[10];
    uint8_t num_phases;
    
    // 脱水参数
    uint16_t spin_rpm;          // 脱水转速
    uint32_t spin_duration_ms;  // 脱水时间
    
    // 漂洗次数
    uint8_t rinse_count;
    
    // 估计时间
    uint32_t estimated_time_min;
    
    // 适用衣物
    char suitable_for[64];
    
    // 特殊功能
    uint8_t allow_pause;        // 允许暂停添衣
    uint8_t night_mode;         // 夜间模式
    uint8_t eco_mode;           // 节能模式
} WashProgram_t;

标准洗涤模式

c 复制代码
/**
 * 标准洗涤模式定义
 */

// 标准洗模式
static const WashProgram_t PROGRAM_STANDARD = {
    .name = "标准洗",
    .num_phases = 5,
    .phases = {
        // 预洗
        {
            .phase = WASH_PHASE_PREWASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 0,            // 冷水
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 5 * 60 * 1000,   // 5分钟
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 主洗
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 40,           // 40度
            .motor_rpm = 50,
            .rotate_time_ms = 15000,
            .pause_time_ms = 5000,
            .duration_ms = 15 * 60 * 1000,  // 15分钟
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 0
        },
        // 漂洗1
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 漂洗2
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 1000,
            .rotate_time_ms = 0,        // 连续旋转
            .pause_time_ms = 0,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 0
        }
    },
    .spin_rpm = 1000,
    .spin_duration_ms = 8 * 60 * 1000,
    .rinse_count = 2,
    .estimated_time_min = 55,
    .suitable_for = "棉麻、化纤等日常衣物",
    .allow_pause = 1,
    .night_mode = 0,
    .eco_mode = 0
};

// 加热洗模式 (高温消毒)
static const WashProgram_t PROGRAM_HOT_WASH = {
    .name = "高温洗",
    .num_phases = 5,
    .phases = {
        // 预洗 - 温水
        {
            .phase = WASH_PHASE_PREWASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 40,
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 主洗 - 高温
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 60,           // 60度高温
            .motor_rpm = 50,
            .rotate_time_ms = 15000,
            .pause_time_ms = 5000,
            .duration_ms = 25 * 60 * 1000,  // 25分钟
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 0
        },
        // 漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 45,
            .rotate_time_ms = 10000,
            .pause_time_ms = 3000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 1200,
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 0
        }
    },
    .spin_rpm = 1200,
    .spin_duration_ms = 10 * 60 * 1000,
    .rinse_count = 2,
    .estimated_time_min = 90,
    .suitable_for = "床单、毛巾、内衣等需消毒衣物",
    .allow_pause = 0,       // 高温时不允许开门
    .night_mode = 0,
    .eco_mode = 0
};

// 羽绒服模式
static const WashProgram_t PROGRAM_DOWN_JACKET = {
    .name = "羽绒服",
    .num_phases = 6,
    .phases = {
        // 浸泡
        {
            .phase = WASH_PHASE_PREWASH,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 30,           // 温水浸泡
            .motor_rpm = 25,            // 极低转速
            .rotate_time_ms = 5000,
            .pause_time_ms = 30000,     // 长暂停
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 1,
            .gentle_mode = 1
        },
        // 轻柔洗涤
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 30,
            .motor_rpm = 30,            // 低转速
            .rotate_time_ms = 8000,
            .pause_time_ms = 10000,
            .duration_ms = 15 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        // 多次漂洗 - 羽绒需要充分漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_FULL,
            .water_temp = 0,
            .motor_rpm = 30,
            .rotate_time_ms = 8000,
            .pause_time_ms = 10000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_FULL,
            .water_temp = 0,
            .motor_rpm = 30,
            .rotate_time_ms = 8000,
            .pause_time_ms = 10000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_FULL,
            .water_temp = 0,
            .motor_rpm = 30,
            .rotate_time_ms = 8000,
            .pause_time_ms = 10000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        // 低速脱水 - 避免羽绒结块
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 600,           // 低速脱水
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 6 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 1
        }
    },
    .spin_rpm = 600,
    .spin_duration_ms = 6 * 60 * 1000,
    .rinse_count = 3,
    .estimated_time_min = 70,
    .suitable_for = "羽绒服、羽绒被等蓬松衣物",
    .allow_pause = 1,
    .night_mode = 0,
    .eco_mode = 0
};

// 毛绒/羊毛模式
static const WashProgram_t PROGRAM_WOOL = {
    .name = "毛绒/羊毛",
    .num_phases = 4,
    .phases = {
        // 轻柔洗涤
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 30,           // 低温
            .motor_rpm = 25,            // 极低转速
            .rotate_time_ms = 5000,
            .pause_time_ms = 15000,     // 长暂停
            .duration_ms = 12 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 1
        },
        // 漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 25,
            .rotate_time_ms = 5000,
            .pause_time_ms = 15000,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 25,
            .rotate_time_ms = 5000,
            .pause_time_ms = 15000,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        // 极低速脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 400,           // 极低速脱水
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 4 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 1
        }
    },
    .spin_rpm = 400,
    .spin_duration_ms = 4 * 60 * 1000,
    .rinse_count = 2,
    .estimated_time_min = 40,
    .suitable_for = "羊毛、羊绒、丝绸等精细衣物",
    .allow_pause = 1,
    .night_mode = 0,
    .eco_mode = 0
};

// 夜间洗模式
static const WashProgram_t PROGRAM_NIGHT = {
    .name = "夜间洗",
    .num_phases = 5,
    .phases = {
        // 静音预洗
        {
            .phase = WASH_PHASE_PREWASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 0,
            .motor_rpm = 35,            // 低转速降噪
            .rotate_time_ms = 8000,
            .pause_time_ms = 5000,
            .duration_ms = 5 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 1
        },
        // 静音主洗
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 30,
            .motor_rpm = 40,            // 降低转速
            .rotate_time_ms = 12000,
            .pause_time_ms = 5000,
            .duration_ms = 20 * 60 * 1000,  // 延长时间补偿
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 0
        },
        // 漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 35,
            .rotate_time_ms = 10000,
            .pause_time_ms = 5000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_HIGH,
            .water_temp = 0,
            .motor_rpm = 35,
            .rotate_time_ms = 10000,
            .pause_time_ms = 5000,
            .duration_ms = 10 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 静音脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 800,           // 降低脱水转速
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 10 * 60 * 1000,  // 延长时间
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 0
        }
    },
    .spin_rpm = 800,
    .spin_duration_ms = 10 * 60 * 1000,
    .rinse_count = 2,
    .estimated_time_min = 70,
    .suitable_for = "夜间洗涤,降低噪音",
    .allow_pause = 1,
    .night_mode = 1,
    .eco_mode = 0
};

// 节能模式
static const WashProgram_t PROGRAM_ECO = {
    .name = "节能洗",
    .num_phases = 4,
    .phases = {
        // 主洗 - 低水位、低温、延长时间
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_LOW,
            .water_temp = 20,           // 低温或不加热
            .motor_rpm = 45,
            .rotate_time_ms = 20000,    // 延长摔打时间
            .pause_time_ms = 8000,
            .duration_ms = 25 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 0
        },
        // 单次漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 0,
            .motor_rpm = 45,
            .rotate_time_ms = 15000,
            .pause_time_ms = 5000,
            .duration_ms = 12 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 喷淋漂洗(省水)
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_LOW,  // 低水位+喷淋
            .water_temp = 0,
            .motor_rpm = 100,               // 边转边喷淋
            .rotate_time_ms = 30000,
            .pause_time_ms = 0,
            .duration_ms = 5 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 1000,
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 8 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 0
        }
    },
    .spin_rpm = 1000,
    .spin_duration_ms = 8 * 60 * 1000,
    .rinse_count = 2,
    .estimated_time_min = 60,
    .suitable_for = "轻度脏污衣物,省水省电",
    .allow_pause = 1,
    .night_mode = 0,
    .eco_mode = 1
};

// 快洗模式
static const WashProgram_t PROGRAM_QUICK = {
    .name = "快洗15分钟",
    .num_phases = 3,
    .phases = {
        // 快速洗涤
        {
            .phase = WASH_PHASE_MAIN_WASH,
            .water_level = WATER_LEVEL_LOW,
            .water_temp = 0,
            .motor_rpm = 55,
            .rotate_time_ms = 10000,
            .pause_time_ms = 2000,
            .duration_ms = 6 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 1,
            .gentle_mode = 0
        },
        // 单次漂洗
        {
            .phase = WASH_PHASE_RINSE,
            .water_level = WATER_LEVEL_MEDIUM,
            .water_temp = 0,
            .motor_rpm = 50,
            .rotate_time_ms = 8000,
            .pause_time_ms = 2000,
            .duration_ms = 5 * 60 * 1000,
            .drain_after = 1,
            .add_detergent = 0,
            .gentle_mode = 0
        },
        // 快速脱水
        {
            .phase = WASH_PHASE_SPIN,
            .water_level = WATER_LEVEL_EMPTY,
            .water_temp = 0,
            .motor_rpm = 1200,
            .rotate_time_ms = 0,
            .pause_time_ms = 0,
            .duration_ms = 4 * 60 * 1000,
            .drain_after = 0,
            .add_detergent = 0,
            .gentle_mode = 0
        }
    },
    .spin_rpm = 1200,
    .spin_duration_ms = 4 * 60 * 1000,
    .rinse_count = 1,
    .estimated_time_min = 15,
    .suitable_for = "少量轻度脏污衣物",
    .allow_pause = 1,
    .night_mode = 0,
    .eco_mode = 0
};

模式参数对比

c 复制代码
/**
 * 各模式参数对比表
 */

/*
┌────────────────────────────────────────────────────────────────────────────────────────┐
│                           洗涤模式参数对比                                              │
├──────────────┬────────┬────────┬────────┬────────┬────────┬────────────────────────────┤
│    模式      │ 水温   │ 水位   │ 洗涤转速│ 脱水转速│ 时间   │         特点               │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 标准洗       │ 40°C   │ 中     │ 50rpm  │ 1000rpm│ 55min  │ 日常衣物通用               │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 高温洗       │ 60°C   │ 中     │ 50rpm  │ 1200rpm│ 90min  │ 杀菌消毒,床品内衣         │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 羽绒服       │ 30°C   │ 高     │ 30rpm  │ 600rpm │ 70min  │ 低转速防结块,多次漂洗     │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 毛绒/羊毛    │ 30°C   │ 高     │ 25rpm  │ 400rpm │ 40min  │ 极低转速,保护纤维         │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 夜间洗       │ 30°C   │ 中     │ 40rpm  │ 800rpm │ 70min  │ 低噪音,延长时间补偿       │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 节能洗       │ 20°C   │ 低     │ 45rpm  │ 1000rpm│ 60min  │ 省水省电,延长摔打         │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 快洗15分钟   │ 冷水   │ 低     │ 55rpm  │ 1200rpm│ 15min  │ 少量轻污,单次漂洗         │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 童装         │ 40°C   │ 高     │ 40rpm  │ 800rpm │ 60min  │ 多次漂洗,去除洗涤剂残留   │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 运动服       │ 30°C   │ 中     │ 45rpm  │ 1000rpm│ 45min  │ 去除汗味,保护弹性         │
├──────────────┼────────┼────────┼────────┼────────┼────────┼────────────────────────────┤
│ 大件床品     │ 40°C   │ 满     │ 35rpm  │ 800rpm │ 80min  │ 满水位,低转速防缠绕       │
└──────────────┴────────┴────────┴────────┴────────┴────────┴────────────────────────────┘

转速与效果关系:
- 洗涤转速越高,摔打力越大,去污效果越好,但对衣物磨损也越大
- 脱水转速越高,脱水效果越好,但噪音越大,对精细衣物可能造成损伤

温度与效果关系:
- 温度越高,洗涤剂活性越强,去污效果越好
- 但高温会使某些衣物缩水变形
- 60°C以上可有效杀灭大部分细菌

水位与效果关系:
- 水位越高,衣物浸泡越充分,但用水量大
- 低水位靠摔打洗涤,省水但需延长时间
*/

洗涤状态机

c 复制代码
/**
 * 洗涤状态机
 */

typedef enum {
    STATE_IDLE,             // 空闲
    STATE_PREPARING,        // 准备(检查门锁等)
    STATE_FILLING,          // 进水
    STATE_HEATING,          // 加热
    STATE_WASHING,          // 洗涤
    STATE_DRAINING,         // 排水
    STATE_SPINNING,         // 脱水
    STATE_RINSING,          // 漂洗
    STATE_PAUSED,           // 暂停
    STATE_ADDING_CLOTHES,   // 添衣中
    STATE_FINISHED,         // 完成
    STATE_ERROR             // 故障
} WashState_t;

typedef struct {
    WashState_t state;
    const WashProgram_t *program;   // 当前程序
    uint8_t current_phase;          // 当前阶段索引
    
    // 时间管理
    uint32_t phase_start_time;
    uint32_t total_elapsed_time;
    uint32_t remaining_time;
    
    // 运行参数
    float current_temp;
    uint16_t current_water_level;
    uint16_t current_motor_rpm;
    
    // 中途添衣
    uint8_t add_clothes_requested;
    uint8_t add_clothes_allowed;
    
    // 错误信息
    uint8_t error_code;
    char error_message[64];
} WashContext_t;

static WashContext_t wash_ctx;

/**
 * 状态机主循环
 */
void wash_state_machine_run(void)
{
    switch (wash_ctx.state) {
    case STATE_IDLE:
        // 等待用户启动
        break;
        
    case STATE_PREPARING:
        handle_preparing();
        break;
        
    case STATE_FILLING:
        handle_filling();
        break;
        
    case STATE_HEATING:
        handle_heating();
        break;
        
    case STATE_WASHING:
        handle_washing();
        break;
        
    case STATE_DRAINING:
        handle_draining();
        break;
        
    case STATE_SPINNING:
        handle_spinning();
        break;
        
    case STATE_RINSING:
        handle_rinsing();
        break;
        
    case STATE_PAUSED:
        handle_paused();
        break;
        
    case STATE_ADDING_CLOTHES:
        handle_adding_clothes();
        break;
        
    case STATE_FINISHED:
        handle_finished();
        break;
        
    case STATE_ERROR:
        handle_error();
        break;
    }
    
    // 更新剩余时间
    update_remaining_time();
    
    // 安全检查
    safety_check();
}

/**
 * 准备阶段
 */
void handle_preparing(void)
{
    // 检查门锁状态
    DoorState_t door = door_get_state();
    
    if (door == DOOR_STATE_OPEN) {
        // 等待关门
        return;
    }
    
    // 尝试锁门
    if (door != DOOR_STATE_LOCKED) {
        if (door_lock() != 0) {
            set_error(ERROR_DOOR_LOCK_FAIL, "门锁失败");
            return;
        }
    }
    
    // 检查衣物重量
    float weight = weight_read_kg();
    if (weight > 10.0f) {  // 超过10kg
        set_error(ERROR_OVERLOAD, "衣物过重");
        return;
    }
    
    // 进入进水阶段
    wash_ctx.state = STATE_FILLING;
    wash_ctx.phase_start_time = HAL_GetTick();
}

/**
 * 进水阶段
 */
void handle_filling(void)
{
    WashPhaseConfig_t *phase = &wash_ctx.program->phases[wash_ctx.current_phase];
    
    // 检查是否达到目标水位
    if (water_level_reached(phase->water_level)) {
        inlet_valve_set(INLET_VALVE_NONE);
        
        // 需要加热?
        if (phase->water_temp > 0 && 
            get_water_temperature() < phase->water_temp - 5) {
            wash_ctx.state = STATE_HEATING;
        } else {
            wash_ctx.state = STATE_WASHING;
        }
        
        wash_ctx.phase_start_time = HAL_GetTick();
        return;
    }
    
    // 继续进水
    inlet_valve_set(INLET_VALVE_COLD);
    
    // 溢出保护
    if (water_level_overflow()) {
        inlet_valve_set(INLET_VALVE_NONE);
        set_error(ERROR_OVERFLOW, "水位溢出");
    }
    
    // 超时保护 (5分钟)
    if (HAL_GetTick() - wash_ctx.phase_start_time > 5 * 60 * 1000) {
        inlet_valve_set(INLET_VALVE_NONE);
        set_error(ERROR_FILL_TIMEOUT, "进水超时");
    }
}

/**
 * 加热阶段
 */
void handle_heating(void)
{
    WashPhaseConfig_t *phase = &wash_ctx.program->phases[wash_ctx.current_phase];
    
    float current_temp = get_water_temperature();
    wash_ctx.current_temp = current_temp;
    
    // 达到目标温度
    if (current_temp >= phase->water_temp - 2) {
        heater_disable();
        wash_ctx.state = STATE_WASHING;
        wash_ctx.phase_start_time = HAL_GetTick();
        return;
    }
    
    // 继续加热
    heater_set_target(phase->water_temp);
    heater_control_loop();
    
    // 同时低速搅动,均匀加热
    static uint32_t last_rotate = 0;
    if (HAL_GetTick() - last_rotate > 30000) {  // 每30秒
        motor_wash_action(30, 5000, 5000, 2000);
        last_rotate = HAL_GetTick();
    }
    
    // 超时保护 (30分钟)
    if (HAL_GetTick() - wash_ctx.phase_start_time > 30 * 60 * 1000) {
        heater_disable();
        set_error(ERROR_HEAT_TIMEOUT, "加热超时");
    }
}

/**
 * 洗涤阶段
 */
void handle_washing(void)
{
    WashPhaseConfig_t *phase = &wash_ctx.program->phases[wash_ctx.current_phase];
    
    // 检查是否完成当前阶段
    if (HAL_GetTick() - wash_ctx.phase_start_time >= phase->duration_ms) {
        motor_set_speed(0, MOTOR_DIR_STOP);
        
        // 排水
        if (phase->drain_after) {
            wash_ctx.state = STATE_DRAINING;
        } else {
            advance_to_next_phase();
        }
        
        wash_ctx.phase_start_time = HAL_GetTick();
        return;
    }
    
    // 执行洗涤动作
    motor_wash_action(
        phase->motor_rpm,
        phase->rotate_time_ms,
        phase->rotate_time_ms,
        phase->pause_time_ms
    );
    
    // 维持水温
    if (phase->water_temp > 0) {
        heater_set_target(phase->water_temp);
        heater_control_loop();
    }
}

/**
 * 排水阶段
 */
void handle_draining(void)
{
    // 检查是否排干
    if (water_level_get_mm() < 20) {
        drain_pump_set(0);
        
        // 进入下一阶段
        advance_to_next_phase();
        wash_ctx.phase_start_time = HAL_GetTick();
        return;
    }
    
    // 继续排水
    drain_pump_set(1);
    
    // 超时保护 (3分钟)
    if (HAL_GetTick() - wash_ctx.phase_start_time > 3 * 60 * 1000) {
        drain_pump_set(0);
        set_error(ERROR_DRAIN_TIMEOUT, "排水超时");
    }
}

/**
 * 脱水阶段
 */
void handle_spinning(void)
{
    WashPhaseConfig_t *phase = &wash_ctx.program->phases[wash_ctx.current_phase];
    
    // 检查是否完成
    if (HAL_GetTick() - wash_ctx.phase_start_time >= phase->duration_ms) {
        motor_set_speed(0, MOTOR_DIR_STOP);
        advance_to_next_phase();
        return;
    }
    
    // 平衡检测
    if (check_unbalance()) {
        // 尝试重新平衡
        motor_set_speed(0, MOTOR_DIR_STOP);
        HAL_Delay(3000);
        
        // 低速重新分布衣物
        motor_wash_action(50, 5000, 5000, 2000);
        motor_wash_action(50, 5000, 5000, 2000);
    }
    
    // 逐步提升转速
    static uint16_t current_rpm = 0;
    if (current_rpm < phase->motor_rpm) {
        current_rpm += 50;  // 每次增加50rpm
        if (current_rpm > phase->motor_rpm) {
            current_rpm = phase->motor_rpm;
        }
    }
    
    motor_set_speed(current_rpm, MOTOR_DIR_CW);
    
    // 持续排水
    drain_pump_set(1);
}

/**
 * 中途添衣处理
 */
void handle_adding_clothes(void)
{
    static uint32_t add_start_time = 0;
    
    // 首次进入
    if (add_start_time == 0) {
        add_start_time = HAL_GetTick();
        
        // 停止电机
        motor_set_speed(0, MOTOR_DIR_STOP);
        
        // 等待电机完全停止
        HAL_Delay(3000);
        
        // 检查水温
        if (get_water_temperature() > 50) {
            // 温度过高,不能开门
            wash_ctx.add_clothes_allowed = 0;
            wash_ctx.state = wash_ctx.state;  // 返回之前状态
            add_start_time = 0;
            return;
        }
        
        // 解锁门
        if (door_unlock(get_water_temperature(), 0) != 0) {
            wash_ctx.add_clothes_allowed = 0;
            wash_ctx.state = STATE_WASHING;  // 返回洗涤
            add_start_time = 0;
            return;
        }
        
        wash_ctx.add_clothes_allowed = 1;
    }
    
    // 等待用户操作
    DoorState_t door = door_get_state();
    
    // 超时检查 (2分钟)
    if (HAL_GetTick() - add_start_time > 2 * 60 * 1000) {
        // 超时,关门继续
        if (door == DOOR_STATE_CLOSED) {
            door_lock();
            wash_ctx.state = STATE_WASHING;
            add_start_time = 0;
        }
        return;
    }
    
    // 用户关门后继续
    if (door == DOOR_STATE_CLOSED && 
        HAL_GetTick() - add_start_time > 5000) {  // 至少等5秒
        door_lock();
        wash_ctx.state = STATE_WASHING;
        wash_ctx.phase_start_time = HAL_GetTick();  // 重置阶段时间
        add_start_time = 0;
    }
}

/**
 * 进入下一阶段
 */
void advance_to_next_phase(void)
{
    wash_ctx.current_phase++;
    
    if (wash_ctx.current_phase >= wash_ctx.program->num_phases) {
        // 所有阶段完成
        wash_ctx.state = STATE_FINISHED;
        return;
    }
    
    WashPhaseConfig_t *next_phase = &wash_ctx.program->phases[wash_ctx.current_phase];
    
    // 根据阶段类型设置状态
    switch (next_phase->phase) {
    case WASH_PHASE_PREWASH:
    case WASH_PHASE_MAIN_WASH:
    case WASH_PHASE_RINSE:
        wash_ctx.state = STATE_FILLING;
        break;
    case WASH_PHASE_SPIN:
        wash_ctx.state = STATE_SPINNING;
        break;
    default:
        wash_ctx.state = STATE_FILLING;
        break;
    }
}

/**
 * 完成处理
 */
void handle_finished(void)
{
    // 停止所有执行器
    motor_set_speed(0, MOTOR_DIR_STOP);
    heater_disable();
    inlet_valve_set(INLET_VALVE_NONE);
    drain_pump_set(0);
    
    // 解锁门
    door_unlock(get_water_temperature(), 0);
    
    // 蜂鸣提示
    buzzer_beep(3, 500, 300);  // 响3声
    
    // 可以发送WiFi通知
    // wifi_notify_complete();
}

/**
 * 暂停功能
 */
void wash_pause(void)
{
    if (wash_ctx.state == STATE_SPINNING || 
        wash_ctx.state == STATE_ERROR) {
        return;  // 脱水和错误状态不能暂停
    }
    
    // 记录当前状态
    static WashState_t paused_from_state;
    paused_from_state = wash_ctx.state;
    
    // 停止执行器
    motor_set_speed(0, MOTOR_DIR_STOP);
    heater_disable();
    inlet_valve_set(INLET_VALVE_NONE);
    
    wash_ctx.state = STATE_PAUSED;
}

/**
 * 恢复功能
 */
void wash_resume(void)
{
    if (wash_ctx.state != STATE_PAUSED) {
        return;
    }
    
    // 检查门锁
    if (door_get_state() != DOOR_STATE_LOCKED) {
        if (door_lock() != 0) {
            return;  // 锁门失败,不能恢复
        }
    }
    
    // 恢复到之前状态
    wash_ctx.state = STATE_WASHING;  // 简化处理
}

/**
 * 请求中途添衣
 */
void wash_request_add_clothes(void)
{
    // 只有在允许暂停的模式和阶段才能添衣
    if (!wash_ctx.program->allow_pause) {
        return;
    }
    
    // 脱水阶段不能添衣
    if (wash_ctx.state == STATE_SPINNING) {
        return;
    }
    
    // 水温检查
    if (get_water_temperature() > 50) {
        return;
    }
    
    wash_ctx.add_clothes_requested = 1;
    wash_ctx.state = STATE_ADDING_CLOTHES;
}

安全保护系统

c 复制代码
/**
 * 安全保护系统
 */

typedef enum {
    ERROR_NONE = 0,
    ERROR_DOOR_LOCK_FAIL,       // 门锁故障
    ERROR_DOOR_OPEN,            // 门未关
    ERROR_OVERLOAD,             // 超载
    ERROR_OVERFLOW,             // 溢水
    ERROR_FILL_TIMEOUT,         // 进水超时
    ERROR_DRAIN_TIMEOUT,        // 排水超时
    ERROR_HEAT_TIMEOUT,         // 加热超时
    ERROR_MOTOR_STALL,          // 电机堵转
    ERROR_MOTOR_OVERCURRENT,    // 电机过流
    ERROR_HEATER_OVERTEMP,      // 加热器过热
    ERROR_WATER_TEMP_HIGH,      // 水温过高
    ERROR_VIBRATION,            // 异常振动
    ERROR_UNBALANCE,            // 不平衡
    ERROR_SENSOR_FAULT,         // 传感器故障
    ERROR_COMM_FAULT            // 通信故障
} ErrorCode_t;

typedef struct {
    ErrorCode_t code;
    char message[64];
    uint32_t timestamp;
    uint8_t recoverable;        // 是否可恢复
} ErrorLog_t;

#define MAX_ERROR_LOGS 20
static ErrorLog_t error_logs[MAX_ERROR_LOGS];
static uint8_t error_log_count = 0;

/**
 * 设置错误
 */
void set_error(ErrorCode_t code, const char *message)
{
    wash_ctx.error_code = code;
    strncpy(wash_ctx.error_message, message, sizeof(wash_ctx.error_message) - 1);
    wash_ctx.state = STATE_ERROR;
    
    // 记录错误日志
    if (error_log_count < MAX_ERROR_LOGS) {
        error_logs[error_log_count].code = code;
        strncpy(error_logs[error_log_count].message, message, 63);
        error_logs[error_log_count].timestamp = HAL_GetTick();
        error_logs[error_log_count].recoverable = is_error_recoverable(code);
        error_log_count++;
    }
    
    // 紧急停机
    emergency_stop();
}

/**
 * 紧急停机
 */
void emergency_stop(void)
{
    motor_set_speed(0, MOTOR_DIR_STOP);
    heater_disable();
    inlet_valve_set(INLET_VALVE_NONE);
    drain_pump_set(0);
}

/**
 * 安全检查 (周期调用)
 */
void safety_check(void)
{
    // 1. 门锁状态检查
    if (wash_ctx.state != STATE_IDLE && 
        wash_ctx.state != STATE_FINISHED &&
        wash_ctx.state != STATE_ERROR &&
        wash_ctx.state != STATE_ADDING_CLOTHES) {
        
        DoorState_t door = door_get_state();
        if (door != DOOR_STATE_LOCKED) {
            set_error(ERROR_DOOR_OPEN, "门已打开");
            return;
        }
    }
    
    // 2. 水位溢出检查
    if (water_level_overflow()) {
        inlet_valve_set(INLET_VALVE_NONE);
        drain_pump_set(1);  // 紧急排水
        set_error(ERROR_OVERFLOW, "水位溢出");
        return;
    }
    
    // 3. 水温检查
    float water_temp = get_water_temperature();
    if (water_temp > 95) {
        heater_disable();
        set_error(ERROR_WATER_TEMP_HIGH, "水温过高");
        return;
    }
    
    // 4. 加热器温度检查
    float heater_temp = get_heater_temperature();
    if (heater_temp > 150) {
        heater_disable();
        set_error(ERROR_HEATER_OVERTEMP, "加热器过热");
        return;
    }
    
    // 5. 电机堵转检查
    if (motor_state.stall) {
        set_error(ERROR_MOTOR_STALL, "电机堵转");
        return;
    }
    
    // 6. 振动检查 (脱水时)
    if (wash_ctx.state == STATE_SPINNING) {
        if (check_excessive_vibration()) {
            motor_set_speed(0, MOTOR_DIR_STOP);
            set_error(ERROR_VIBRATION, "异常振动");
            return;
        }
    }
    
    // 7. 传感器自检
    if (!check_sensors_ok()) {
        set_error(ERROR_SENSOR_FAULT, "传感器故障");
        return;
    }
}

/**
 * 不平衡检测
 */
int check_unbalance(void)
{
    // 通过振动传感器或电机电流波动检测
    // 简化实现:检测电机电流波动
    static float current_samples[10];
    static int sample_idx = 0;
    
    float motor_current = read_motor_current();
    current_samples[sample_idx] = motor_current;
    sample_idx = (sample_idx + 1) % 10;
    
    // 计算电流标准差
    float mean = 0;
    for (int i = 0; i < 10; i++) {
        mean += current_samples[i];
    }
    mean /= 10;
    
    float variance = 0;
    for (int i = 0; i < 10; i++) {
        variance += (current_samples[i] - mean) * (current_samples[i] - mean);
    }
    variance /= 10;
    
    float std_dev = sqrtf(variance);
    
    // 波动超过阈值认为不平衡
    return (std_dev > mean * 0.2f);  // 波动超过20%
}

/**
 * 异常振动检测
 */
int check_excessive_vibration(void)
{
    // 读取加速度传感器(如果有)
    // 或通过电机电流分析
    // 简化:返回0表示正常
    return 0;
}

用户界面与显示

c 复制代码
/**
 * 用户界面控制
 */

typedef struct {
    // 显示内容
    char mode_name[32];
    uint32_t remaining_time_min;
    uint8_t current_phase;
    float water_temp;
    uint16_t spin_rpm;
    
    // 状态指示
    uint8_t washing;
    uint8_t heating;
    uint8_t spinning;
    uint8_t door_locked;
    uint8_t error;
    
    // 选项
    uint8_t selected_mode;
    uint8_t temp_option;        // 温度选项 0=冷水, 1=30°, 2=40°, 3=60°
    uint8_t spin_option;        // 脱水选项 0=不脱水, 1=低速, 2=中速, 3=高速
    uint8_t rinse_option;       // 漂洗次数
} UIState_t;

static UIState_t ui_state;

// 可选模式列表
static const WashProgram_t *available_programs[] = {
    &PROGRAM_STANDARD,
    &PROGRAM_HOT_WASH,
    &PROGRAM_DOWN_JACKET,
    &PROGRAM_WOOL,
    &PROGRAM_NIGHT,
    &PROGRAM_ECO,
    &PROGRAM_QUICK
};
#define NUM_PROGRAMS (sizeof(available_programs) / sizeof(available_programs[0]))

/**
 * 更新显示
 */
void ui_update_display(void)
{
    // 更新状态
    ui_state.remaining_time_min = wash_ctx.remaining_time / 60000;
    ui_state.water_temp = wash_ctx.current_temp;
    ui_state.current_phase = wash_ctx.current_phase;
    ui_state.door_locked = (door_get_state() == DOOR_STATE_LOCKED);
    ui_state.error = (wash_ctx.state == STATE_ERROR);
    ui_state.washing = (wash_ctx.state == STATE_WASHING);
    ui_state.heating = heater_state.heating;
    ui_state.spinning = (wash_ctx.state == STATE_SPINNING);
    
    // 发送到显示模块
    // display_show_mode(ui_state.mode_name);
    // display_show_time(ui_state.remaining_time_min);
    // display_show_temp(ui_state.water_temp);
    // display_show_status_icons(...);
}

/**
 * 按键处理
 */
void ui_handle_key(uint8_t key)
{
    switch (key) {
    case KEY_MODE:
        // 切换模式
        if (wash_ctx.state == STATE_IDLE) {
            ui_state.selected_mode = (ui_state.selected_mode + 1) % NUM_PROGRAMS;
            strncpy(ui_state.mode_name, 
                    available_programs[ui_state.selected_mode]->name, 31);
        }
        break;
        
    case KEY_START:
        // 启动/暂停
        if (wash_ctx.state == STATE_IDLE) {
            wash_start(available_programs[ui_state.selected_mode]);
        } else if (wash_ctx.state == STATE_PAUSED) {
            wash_resume();
        } else {
            wash_pause();
        }
        break;
        
    case KEY_TEMP:
        // 温度选项
        if (wash_ctx.state == STATE_IDLE) {
            ui_state.temp_option = (ui_state.temp_option + 1) % 4;
        }
        break;
        
    case KEY_SPIN:
        // 脱水选项
        if (wash_ctx.state == STATE_IDLE) {
            ui_state.spin_option = (ui_state.spin_option + 1) % 4;
        }
        break;
        
    case KEY_ADD_CLOTHES:
        // 添衣按钮
        wash_request_add_clothes();
        break;
        
    case KEY_POWER:
        // 电源键 - 长按关机
        // ...
        break;
    }
}

/**
 * 启动洗涤
 */
void wash_start(const WashProgram_t *program)
{
    // 复制程序(允许用户修改参数)
    wash_ctx.program = program;
    wash_ctx.current_phase = 0;
    wash_ctx.state = STATE_PREPARING;
    wash_ctx.total_elapsed_time = 0;
    wash_ctx.remaining_time = program->estimated_time_min * 60 * 1000;
    wash_ctx.error_code = ERROR_NONE;
    
    strncpy(ui_state.mode_name, program->name, 31);
}

WiFi远程控制

c 复制代码
/**
 * WiFi远程控制模块
 */

#include "esp_wifi.h"
#include "mqtt_client.h"

typedef struct {
    uint8_t connected;
    char device_id[32];
    char mqtt_topic[64];
} WiFiState_t;

static WiFiState_t wifi_state;

/**
 * 上报状态到云端
 */
void wifi_report_status(void)
{
    if (!wifi_state.connected) return;
    
    // 构建JSON状态
    char json[512];
    snprintf(json, sizeof(json),
        "{"
        "\"state\":\"%d\","
        "\"mode\":\"%s\","
        "\"phase\":%d,"
        "\"remaining_time\":%lu,"
        "\"water_temp\":%.1f,"
        "\"door_locked\":%d,"
        "\"error\":%d,"
        "\"error_msg\":\"%s\""
        "}",
        wash_ctx.state,
        wash_ctx.program ? wash_ctx.program->name : "无",
        wash_ctx.current_phase,
        wash_ctx.remaining_time / 60000,
        wash_ctx.current_temp,
        (door_get_state() == DOOR_STATE_LOCKED) ? 1 : 0,
        wash_ctx.error_code,
        wash_ctx.error_message
    );
    
    mqtt_publish(wifi_state.mqtt_topic, json);
}

/**
 * 处理远程命令
 */
void wifi_handle_command(const char *cmd, const char *params)
{
    if (strcmp(cmd, "start") == 0) {
        // 远程启动
        int mode_idx = atoi(params);
        if (mode_idx >= 0 && mode_idx < NUM_PROGRAMS) {
            wash_start(available_programs[mode_idx]);
        }
    }
    else if (strcmp(cmd, "pause") == 0) {
        wash_pause();
    }
    else if (strcmp(cmd, "resume") == 0) {
        wash_resume();
    }
    else if (strcmp(cmd, "stop") == 0) {
        // 强制停止
        wash_ctx.state = STATE_IDLE;
        emergency_stop();
        door_unlock(get_water_temperature(), 0);
    }
    else if (strcmp(cmd, "query") == 0) {
        wifi_report_status();
    }
}

/**
 * 完成通知
 */
void wifi_notify_complete(void)
{
    if (!wifi_state.connected) return;
    
    char json[128];
    snprintf(json, sizeof(json),
        "{\"event\":\"complete\",\"mode\":\"%s\",\"duration\":%lu}",
        wash_ctx.program->name,
        wash_ctx.total_elapsed_time / 60000
    );
    
    mqtt_publish(wifi_state.mqtt_topic, json);
}

总结

洗衣机控制系统的核心技术:

模块 关键技术
水位检测 气压式传感器、ADC滤波、水量计算
温度控制 NTC热敏电阻、滞环控制、过热保护
称重检测 应变片+HX711、自动水位推荐
门锁系统 电磁锁、安全联锁、高温禁开
电机驱动 BLDC变频、PID调速、软启动、堵转检测
加热控制 继电器/可控硅、温度维持、能耗估算
洗涤程序 多阶段控制、参数化配置、模式切换
安全保护 多重保护、错误恢复、紧急停机

各洗涤模式的设计原则:

模式 核心特点
标准洗 平衡去污效果和衣物保护
高温洗 60°C杀菌,适合床品内衣
羽绒服 低转速防结块,多次漂洗
毛绒 极低转速,保护纤维
夜间洗 降噪为主,延长时间补偿
节能洗 低水位+延长摔打,省水省电
快洗 短时间,适合轻污衣物

希望这篇文章对想了解洗衣机控制技术的朋友有帮助。代码可以作为参考框架使用,实际产品需要根据具体硬件进行调整。有问题欢迎评论区交流~


参考资料:

  • 海尔/美的洗衣机维修手册
  • STM32家电控制方案
  • BLDC电机驱动技术
  • 家电安全标准 GB4706
相关推荐
清风6666661 天前
基于单片机的智能感应式汽车雨刮器控制系统设计
单片机·嵌入式硬件·汽车·毕业设计·课程设计·期末大作业
Godspeed Zhao1 天前
现代智能车机系统4——HPC(1)
架构·汽车
Godspeed Zhao1 天前
现代智能汽车中的无线技术6——蜂窝移动通信技术(5)
汽车·信息与通信
应用市场2 天前
汽车自动雨刷与雨量感应系统全解析——从光学原理到控制算法
汽车
zsmydz8882 天前
4G车载TBOX共享汽车实现远程控制
汽车·tbox·4g t-box·汽车tbox·车联网车载智能终端
Godspeed Zhao3 天前
现代智能汽车中的无线技术4——蜂窝移动通信技术(3)
架构·汽车·信息与通信
汤姆yu4 天前
基于深度学习YOLOv8的车辆汽车速度检测系统
yolo·汽车
车载诊断技术4 天前
2025结束,2026新的开始
汽车·电子电气架构·2025结束,2026新的开始
secondyoung4 天前
TLE9180短路检测功能总结
经验分享·嵌入式硬件·mcu·汽车·流程图·infineon·tle9180