转载:【新提醒】6月4日更新!永速直流风扇改装WiFi和无极调速 - 『HomeAssistant』综合讨论区 - 『瀚思彼岸』» 智能家居技术论坛 - Powered by Discuz! (hassbian.com)

6.4日更新:
修改了8266这边风速变动后对单片机反馈的动作。
在按下按键后12秒内,不进行反馈,避免了按下按键后反复横跳

6.2日更新:
1:增加了关闭数码管的功能
2:增加一个嗡鸣器开关,配置为IO5,可以连接一个高电平触发继电器模块。断开嗡鸣器的连线,把继电器串进去即可。
3:提供一个esphome固件,需要按下面的说明接线。

目前存在的bug:
1:挡位反馈在调到某些值的时候反复横跳

先看效果吧,放个B站连接。
https://www.bilibili.com/video/BV1u7421R7sc






虽然家里已经有三把风扇了。。。但还是需要挪着用。。很不爽。
然后刷视频看到一款永速的风扇,直流无刷。价格只要85元起(五叶)。那么必拿下!
实际购买7叶款拼夕夕用卷81元购入。

到手第一时间拆机

主控板长这样。
这个风扇之前有改装方案,但只是模拟按键按下。所以我另行探索。研究一番发现数码管左下是主控单片机,嗡鸣器上方的是无刷驱动芯片
PWM信号就是那四个焊盘的第二个,通过下方的R11连接连接到单片机
本次改装的重点就是围绕这单片机出来的PWM占空比信号
接下来上我的电路连接图:


首先去掉R11,下端经过原先的电阻,过10k电阻下拉。中间点引出到8266.用来检测占空比,因为单片机电平是5v,下拉是为了控制电压不高于3.3v。避免损坏8266。
然后四个按键除了直连8266的IO的,还有一组经过串电阻后并联,下拉后接到8266的IO4,聪明的朋友猜猜这是为了啥

然后看看我的最终连接效果


就是这个样子

「教程」永速风扇改装WiFi接入Homeassistant--接线篇_哔哩哔哩_bilibili

8266的供电我本来准备在7505后面再串个ldo,但实测7505很烫,所以换成dcdc直接12v-3.3。
我买的没有遥控摇头,如果是遥控摇头,程序里我已经定义了摇头的输出是IO16,接到对应点,然后找个io检测摇头按键,就不另说了

再来看看ha中的样子

风扇主实体


所有实体

然后定时时间只用来显示,输入无用。

程序依旧使用esphome
我直接贴上主要配置

esphome:
  name: ys-fan
  friendly_name: ys_fan

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "Hf8kKpSZhaagJvza0lN38HA8LnyvV+Osgdkh+rjs2ug="

ota:
  password: "d2c9dea60d1131ee7534c00b2f01e18b"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ys-Fan"
    password: "12345678"

captive_portal:

globals: ##定义全局变量
  - id: duty_previous  ##存储占空比值
    type: float
    restore_value: no
    initial_value: '0.0'      
binary_sensor:  #定义二进制传感器组件
  - platform: gpio  #使用GPIO类
    pin:
      number: 4     #定义检测IO4
      mode: INPUT_PULLUP   #定义IO为上拉模式
      inverted: True       #定义反向触发,即IO和负极短接(变为低电平)触发
    id: button1
    filters:    #过滤
      - delayed_on: 100ms   #持续多久才触发,不要小于下面模拟按键按下的时间.一般不用改
    on_multi_click:  ##判断多次按下及长按,这里使用是为了避免模拟长按电源键被检测到,只响应单击操作。
      - timing:  #单击
          - ON for at most 0.4s
          - OFF for at least 0.1s
        then:
        - delay: 500ms  #等待500毫秒,使单片机输出的占空比稳定后再检测
        - number.to_min:  #归零上次按下的时间
            id: number2
        - if: #检测按下的是定时键
            condition:
              - fan.is_on: dc_fan    
            then:      
              - lambda: |-
                  float duty_current = id(duty).state;
                  if (abs(duty_current - id(duty_previous)) <= 1) {
                    // 对比按下前后的占空比值,用来判断按下的是定时键,因为按它占空比不会变。。。
                    // 当是定时键就使数定时时间加1
                      auto call = id(number1).make_call();
                      call.number_increment(true);
                      call.perform();
                  }
                  // 更新duty_previous值为当前duty值
                  id(duty_previous) = duty_current;     
        - if:           #如果
            condition:  #判断条件,下面是占空比小于9
              lambda: |-
                return id(duty).state < 9;
            then:       #执行动作,关掉风扇
              - fan.turn_off:
                  id: dc_fan 
            else:      #反之则打开风扇,并将检测到的占空比值设为风速
              - fan.turn_on:
                  id: dc_fan 
                  speed: !lambda |-
                    return  id(duty).state/1.0;                       
      - timing:  #双击
            - ON for at most 1s
            - OFF for at most 1s
            - ON for at most 1s
            - OFF for at least 0.1s
        then:

      - timing: #长按
          - ON for 1s to 5s
          - OFF for at least 0.1s
        then:

output:  #定义输出组件
  - platform: esp8266_pwm  ##PWM信号,风扇调速
    pin: 15  #使用的IO
    frequency: 1000 Hz
    id: pwm1    
  - platform: esp8266_pwm  ##PWM信号,摇头电机
    pin: 16
    frequency: 1000 Hz
    id: pwm2  

##下面定义模拟按下按键的输出IO    
  - platform: gpio
    pin: 0
    id: key_power  #电源键
    inverted: True
  - platform: gpio
    pin: 12  
    id: key_up    #加挡键
    inverted: True
  - platform: gpio
    pin: 13
    id: key_down  #减挡键
    inverted: True
  - platform: gpio
    pin: 2
    id: key_timer #定时键
    inverted: True 
fan:  #定义风扇组件
  - platform: speed #speed是可调速风扇
    output: pwm1    #定义PWM的输出ID
    name: "永速风扇"
    id: dc_fan      #定义ID,用于自动化及其它组建的调用   
    restore_mode: RESTORE_DEFAULT_OFF  #系统重启后的状态。RESTORE_DEFAULT_OFF为尝试恢复之前状态,如失败则为关
    oscillation_output: pwm2    #定义摇头的输出
    on_turn_on: #风扇开启时的动作
      then:     #提供两种写法,lamba语句和ESPhome的自动化配置流程(已注释)
        - lambda: |-
            if (id(duty).state < 1) {
              // 占空比小于1,表示单片机没有开,执行模拟按下电源键,开启单片机
              id(power).press(); 
            }    

        # - if: 
        #     condition: 
        #       - sensor.in_range: #传感器值小于1
        #           id: duty
        #           below: 1
        #     then:
        #       - button.press: power

    on_turn_off: #风扇关掉时的动作
      then:
        - number.to_min:  #让定时值归0
            id: number1
        - lambda: |-
            if (id(duty).state > 1 && id(duty).state < 100) {
              // 占空比大于1小于100,表示单片机还开着,执行模拟按下电源键,关闭单片机
              id(power).press(); 
            }   

        # - if: 
        #     condition: 
        #       - sensor.in_range: #传感器值大于1
        #           id: duty
        #           above: 1
        #           below: 100
        #     then:
        #       - button.press: power
               
sensor:
  - platform: duty_cycle  #检测单片机输出的占空比,用于判断单片机控制风扇是否关机,以及设置风速。
    pin: 14    #这里使用IO14进行检测,可自行根据实际连接引脚进行更改
    update_interval: 200ms  #检测间隔
    id: duty   #定义ID,用于自动化及其它组建的调用 


button:  #定义模拟按下的按键
  - platform: output
    name: "1 息屏"
    internal: false    #定义是否仅内部使用,修改为true将不在ha界面中显示。
    output: key_power  #使用的输出id
    duration: 1500ms   #模拟长按电源键,实现关闭数码管
    id: dispaly       
  - platform: output
    name: "2 定时"
    internal: false
    output: key_timer
    duration: 70ms   #模拟按下多久,实测70毫秒OJBK,小于50不触发似乎。 
    on_press: #每次按下使数值定时时间+1
      then: 
        if:
          condition:
            - fan.is_on: dc_fan
          then:  
            - number.increment:
                id: number1
                cycle: true  
  - platform: output
    name: "3 电源键"
    internal: True  
    output: key_power  
    id: power
    duration: 70ms                   
  - platform: output
    name: "4增加挡位"
    internal: true
    output: key_up
    duration: 70ms 
    id: up 
  - platform: output
    name: "5 减小挡位"
    internal: true
    output: key_down
    duration: 70ms   
    id: down                 
number:  #定义数值组件
  - platform: template  #number1用于显示定时时间
    name: "0 定时时间"
    id: number1
    optimistic: true
    min_value: 0
    max_value: 12
    step: 1  
    mode: BOX 
  - platform: template #number2用于记录上次按下时间,秒
    id: number2
    optimistic: true
    min_value: 0
    max_value: 100
    step: 1  
    mode: BOX       
switch:
  - platform: gpio
    name: "0 嗡鸣器开关"
    pin: 5
    restore_mode: RESTORE_DEFAULT_OFF           
#反馈状态到单片机
interval:  #定义间隔时间组件
  - interval: 1s  #每秒一次
    then:
      - number.increment: 
          id: number2
      - if:
          condition:  ##按键操作超过12秒才进行动作
            - number.in_range:
                id: number2
                above: 12 
          then:  
            - if:
                condition:
                  - fan.is_on: dc_fan
                then:
                  - lambda: |-
                      if (id(dc_fan).speed > id(duty).state + 5) {
                        // 如果风扇速度大于占空比值+5,则触发增加挡位
                        id(up).press(); 
                      } else if (id(dc_fan).speed < id(duty).state - 5) {
                        // 如果风扇速度小于占空比值-5,则触发减小挡位
                        id(down).press(); 
                      }           
  - interval: 60min  #每1小说使数值定时时间-1
    then:
      - number.decrement:
          id: number1
          cycle: false    

烧录固件下载

ys-fan (1).bin


大佬们和聪明的朋友应该已经从配置里看出来了。我使用原单片机检测按下的时间和esphome设定的检测时间差,来实现通过io模拟按键按下与按下实体按键时esp的检测不冲突,
实现ha调整风速后,对应到数码管的显示,以及在ha中按定时和按键按定时均能正确累加定时时间。

然后通过按下后判断占空比有没有变化来识别按的是不是定时键也是有些取巧了。

如果不需要把ha调整后的风速挡位反馈回单片机的话,本次改装只需使用3个IO。