家在六楼,没有电梯。平常拿个小东西上楼还行,要是买个米面粮油啥的往楼上搬就有点费劲了。所以就使用esp32+esphome+小型卷扬机+轮胎+电动拉杆diy了个吊篮。
应用场景一;开车回来到楼下,东西卸入吊篮,开车去车库。
应用场景二;有快递到,无论是否在家,可以落下吊篮接收快递。
菜鸟一个,只能从esphome官网的帮助文档中抄,东拼西凑,总算拼成了。
用两个干簧管制作了一个电机转动圈数的传感器。电机轮盘上粘了两个磁铁,电机每转动一圈,会产生两个脉冲信号给esp32的io脚用于计数。使用esphome旋转编码器组件,可以较精准的控制电机转动的圈数。通过圈数,可以知道当前吊篮升降的高度。
esp32控制两组继电器模块,自带光耦隔离。两个10A的继电器控制电动拉杆,两个30A的继电器控制卷扬机。
两个行程开关,产生拉杆推到位与拉到位的信号给esp32。
又在卷扬机顶加了个行程开关,可以校正圈数传感器。
淘了俩个薄膜按键,粘到盒盖上,用于直接在盒子面板上操作。
5D摇杆做个线控,可以拉进屋操作。
web界面。
hass操作界面
操作视频。
代码如下,请各位大神指正。
esphome:
name: diao-lan
on_boot:
priority: -100.0
then:
- script.execute: caosi
preferences:
flash_write_interval: 1min
# name_add_mac_suffix: true
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: debug #VERBOSE #
logs:
script: none
select: none
sensor: none
# Enable Home Assistant API
api:
ota:
wifi:
{ssid: !secret wifi_ssid, password: !secret wifi_password, manual_ip: { static_ip: 192.168.2.86 , gateway: 192.168.2.1 , subnet: 255.255.255.0 } ,
ap: {ssid: "diao-lan" , password: "password"}}
web_server: {port: 80 , auth: {username: "users", password: "password" },local: true } ##,js_include: "./v2/www.js" ,js_url: "" ,version: 2
text_sensor:
##wifi信息;
- platform: wifi_info
ssid: { name: '1.2.${sbm}_wifi ID'}
mac_address: { name: 1.3.本机 Mac}
captive_portal: ##强制网络门户;
substitutions: ##替换##
sbm: "吊篮"
##按钮gpio##
ssan_gpio: GPIO27 ##上升按钮;
xjan_gpio: GPIO14 ##下降按钮;
lhan_gpio: GPIO26 ##拉回按钮;
tcan_gpio: GPIO25 ##推出按钮;
tzan_gpio: GPIO12 ##停止按钮;
zd_fang_gpio: GPIO32 ##自动放吊篮按钮;
zd_sou_gpio: GPIO33 ##自动收吊篮按钮;
##输出继电器##
sang_gpio: GPIO23 ##上升继电器;
xia_gpio: GPIO18 ##下降继电器;
tui_gpio: GPIO22 ##推出继电器;
la_gpio: GPIO19 ##拉回继电器;
##传感器gpio##
diaolan_s_gpio: GPIO5 ##吊篮上限位;
lagan_w_gpio: GPIO17 ##拉杆外限位;
lagan_n_gpio: GPIO16 ##拉杆内限位;
dlwz_a_gpio: "15" ##吊篮位置传感器A脚;
dlwz_b_gpio: "13" ##吊篮位置传感器B脚;
##数值组件##
number:
- platform: template ##升顶高度,电机最高上升圈数x2;
name: "8.9.${sbm}_升顶高度"
id: sdgd
internal: false
max_value: 146
min_value: 136
step: 1
initial_value: 142
optimistic: true ##实时反馈;
mode: box ##mode类型,auto,box,slider;
restore_value: True ##保存数值到闪存;
unit_of_measurement: 圈数
update_interval: 1s
##设置超时时间,-1即为不启用超时;
- platform: template
name: "8.8.${sbm}_超时收回"
id: cssj
internal: false
max_value: 15
min_value: -1
step: 1
initial_value: 5
optimistic: true ##实时反馈;
mode: box ##mode类型,auto,box,slider;
restore_value: True ##保存数值到闪存;
unit_of_measurement: 分钟
update_interval: 1s
on_value_range:
above: 1
then:
- script.execute: off_sdms
- if:
condition:
lambda: 'return id(cssj).state >= 0;'
then:
- script.execute: caosi
- logger.log: {format: " 已设置%.0f分钟超时自动收回吊篮。 ", args: [ 'id(cssj).state' ]}
else:
- script.execute: x_x
- script.stop: caosi
- logger.log: " 已关闭超时。 "
script: ##脚本##;
##关闭脚本;
- id: x_x
mode: restart
then:
- logger.log: "执行x_x脚本"
- script.stop: n_xiajiang
- script.stop: no_sengjiang
- script.stop: no_tuila
- script.stop: zd_fangdiaolan
- script.stop: zd_soudiaolan
- script.stop: w_xiajiang
- script.execute: off_sang
- script.execute: off_xia
- script.execute: off_tui
- script.execute: off_la
- script.execute: off_sdms
##检测并关闭手动开关##;
- id: off_sdms
mode: restart
then:
- if:
condition:
- switch.is_on: sdms ##检测上升是否开启##;
then:
- delay: 101ms
- logger.log: "off_sang:关闭手动模式。"
- switch.turn_off: sdms
##检测并关闭上升开关##;
- id: off_sang
mode: restart
then:
- if:
condition:
- switch.is_on: sang ##检测上升是否开启##;
then:
- delay: 101ms
- logger.log: "off_sang:关闭上升。"
- switch.turn_off: sang
##检测并关闭下降开关#;
- id: off_xia
mode: restart
then:
- if:
condition:
- switch.is_on: xia ##检测下降是否开启##;
then:
- delay: 101ms
- logger.log: "off_xia:关闭下降。"
- switch.turn_off: xia
##检测并关闭推出开关#;
- id: off_tui
mode: restart
then:
- if:
condition:
- switch.is_on: tui ##检测推出是否开启##;
then:
- delay: 101ms
- logger.log: "off_tui:关闭上升。"
- switch.turn_off: tui
##检测并关闭拉回开关#;
- id: off_la
mode: restart
then:
- if:
condition:
- switch.is_on: la ##检测拉回是否开启##;
then:
- delay: 101ms
- logger.log: "off_la:关闭上升。"
- switch.turn_off: la
##检测并关闭自动收吊篮开关#;
- id: off_zds_dl
mode: restart
then:
- if:
condition:
- switch.is_on: zds_dl ##检测自动收吊篮是否开启##;
then:
- delay: 101ms
- logger.log: "off_zds_dl:关闭自动收吊篮开关。"
- switch.turn_off: zds_dl
##检测并关闭自动放吊篮开关#;
- id: off_zdf_dl
mode: restart
then:
- if:
condition:
- switch.is_on: zdf_dl ##检测自动放吊篮是否开启##;
then:
- delay: 101ms
- logger.log: "off_zdf_dl :关闭自动放吊篮开关。"
- switch.turn_off: zdf_dl
##拉杆推拉规则;
- id: no_tuila
mode: restart
then:
- script.execute: off_sdms
- logger.log: "执行no_tuila脚本,拉杆推拉规则。"
- if:
condition:
- and:
- binary_sensor.is_off: diaolan_s
then:
- logger.log: "no_tuila:吊篮未升顶,禁止推拉。"
- script.execute: off_tui
- script.execute: off_la
- if:
condition:
- or:
- binary_sensor.is_on: lagan_w ##检测到拉杆是否推到位##;
then:
- delay: 1000ms #延时
- logger.log: "no_tuila:已推出到位。"
- script.execute: off_tui
- if:
condition:
- or:
- binary_sensor.is_on: lagan_n ##检测到拉杆是否拉到位##;
then:
- delay: 1000ms #延时
- logger.log: "no_tuila:已拉回到位。"
- script.execute: off_la
##吊篮升降规则;
- id: sengjiang ##调用全部升降脚本##;
mode: restart
then:
- script.execute: no_sengjiang
- script.execute: no_sengjiang_lg
- if:
condition:
- binary_sensor.is_on: lagan_w ##外推状态
then:
- logger.log: "sengjiang:运行w_xiajiang。"
- script.execute: w_xiajiang
- if:
condition:
- binary_sensor.is_on: lagan_n ##内收状态;
then:
- logger.log: "sengjiang:运行n_xiajiang。"
- script.execute: n_xiajiang
- id: no_sengjiang ##升顶自动停止##;
then:
- script.execute: off_sdms
- logger.log: "执行no_sengjiang脚本,吊篮升降规则。"
- wait_until:
condition:
- binary_sensor.is_on: diaolan_s ##检测吊篮是否已升顶##;
- switch.is_on: sang
timeout: 2min
- logger.log: "no_sengjiang:吊篮已升顶,关闭上升"
- script.execute: off_sang
- id: no_sengjiang_lg ##拉杆未到位,禁止升降操作##;
then:
- script.execute: off_sdms
- wait_until:
condition:
- binary_sensor.is_off: lagan_w ##检测到拉杆未推到位;
- binary_sensor.is_off: lagan_n
- logger.log: "no_sengjiang_lg: 拉杆未到位,禁止升降"
- script.execute: off_sang
- script.execute: off_xia
- id: w_xiajiang ##拉杆推到位,吊篮下降到位##;
then:
- script.execute: off_sdms
- wait_until:
condition:
- binary_sensor.is_on: lagan_w ##检测拉杆已推到位;
- lambda: 'return id(dlwz).state < 1;' ##下降到位;
- switch.is_on: xia ##下降继电器是开启状态;
timeout: 85s
- delay: 800ms #延时
- logger.log: "w_xiajiang:外部下降已降落到位,关闭下降"
- script.execute: off_xia ##关下降继电器;
- script.execute: off_zdf_dl ##关自动落吊篮开关;
- script.execute: caosi ##运行超时脚本;
- id: n_xiajiang ##拉杆拉到位,吊篮下降到位##;
then:
- script.execute: off_sdms
- logger.log: "执行n_xiajiang脚本"
- wait_until:
condition:
- lambda: |-
return id(dlwz).state < id(sdgd).state-3;
- binary_sensor.is_on: lagan_n ##检测拉杆已拉到位##;
timeout: 3500ms
- delay: 600ms #延时
- logger.log: {format: " n_xiajiang:已降落到%.0f,关闭下降,关闭自动收吊篮开关。", args: [ 'id(dlwz).state' ]}
- script.execute: off_xia
- script.execute: off_zds_dl
##自动放吊篮脚本;
- id: zd_fangdiaolan
mode: restart
then:
- script.execute: off_sdms
- logger.log: "执行zd_fangdiaolan脚本"
- switch.turn_on: sang ##打开上升;
- wait_until:
- binary_sensor.is_on: diaolan_s
- script.execute: off_sang ##关闭上升;
- logger.log: "zd_fangdiaolan: 关闭上升"
- switch.turn_on: tui
- logger.log: "zd_fangdiaolan: 打开拉杆推出"
- wait_until:
binary_sensor.is_on: lagan_w ##检测拉杆已推到位##;
- delay: 500ms #延时
- logger.log: "zd_fangdiaolan: 打开下降"
- switch.turn_on: xia
##自动收吊篮脚本;
- id: zd_soudiaolan
mode: restart
then:
- script.execute: off_sdms
- logger.log: "执行zd_soudiaolan脚本"
- switch.turn_on: sang ##打开上升;
- wait_until:
- binary_sensor.is_on: diaolan_s ##检测吊篮是否已升顶;
- script.execute: off_sang ##关闭上升;
- logger.log: "zd_soudiaolan:关闭上升"
- switch.turn_on: la
- logger.log: "zd_soudiaolan:拉杆拉回"
- wait_until:
binary_sensor.is_on: lagan_n ##检测拉杆已拉到位##;
- delay: 500ms #延时
- switch.turn_on: xia
- logger.log: "zd_soudiaolan打开下降"
##超时收回;
- id: caosi
mode: restart
then:
- script.execute: off_sdms
- logger.log: "执行caosi脚本"
- if:
condition:
and:
- lambda: 'return id(cssj).state >= 0;' ##超时设置是否开启;
- lambda: |-
return id(dlwz).state < id(sdgd).state;
- binary_sensor.is_off: lagan_n ##检测拉杆是否未拉回;
then:
- logger.log: {format: " %.0f分钟后执行自动收吊篮。 ", args: [ 'id(cssj).state' ]}
- delay: !lambda "return id(cssj).state*60000;"
- logger.log: {format: " 吊篮超过%.0f分钟未回收,已启动自动回收程序。 ", args: [ 'id(cssj).state' ]}
- switch.turn_on: zds_dl ##执行自动收吊篮;
else:
- script.stop: caosi
- logger.log: "已是收回状态,停止超时检测。"
sensor: ##传感器 ;
#wifi强度;
- {platform: wifi_signal , name: "1.1.${sbm}_WiFi强度", update_interval: 180s}
# - {platform: uptime , name: "1.6.${sbm}_运行时间" ,id: yxsj , update_interval: 600s}
##吊篮高度##;
- platform: rotary_encoder
name: "1.8.${sbm}_高度"
id: dlwz
restore_mode: RESTORE_DEFAULT_ZERO ##启动时恢复记忆值
publish_initial_value: True
pin_a:
number: ${dlwz_a_gpio}
inverted: true
mode:
input: true
pullup: true
pin_b:
number: ${dlwz_b_gpio}
inverted: true
mode:
input: true
pullup: true
filters:
- debounce: 100ms
on_value: ##新值触发;
- if:
condition:
- binary_sensor.is_off: lagan_n
- binary_sensor.is_off: lagan_w
then:
- script.execute: no_sengjiang
- if:
condition:
- binary_sensor.is_on: lagan_w
- switch.is_on: xia
then:
- script.execute: w_xiajiang
- if:
condition:
- binary_sensor.is_on: lagan_n
- switch.is_on: xia
then:
- script.execute: n_xiajiang
- if:
condition:
- binary_sensor.is_on: diaolan_s
then:
- sensor.rotary_encoder.set_value: ##升顶状态,矫正吊篮位置;
id: dlwz
value: !lambda "return id(sdgd).state;"
binary_sensor: ##
##按键##;
- platform: gpio
name: "9.5.${sbm}_停止按钮"
pin:
number: "${tzan_gpio}"
mode:
input: True
pullup: True
inverted: True
internal: true ##内部,不在前端显示
filters:
- delayed_on_off: 300ms
on_press:
- script.execute: off_sang
- script.execute: off_xia
- script.execute: off_tui
- script.execute: off_la
- script.stop: zd_soudiaolan
- script.stop: zd_fangdiaolan
on_click:
min_length: 5s
max_length: 10s
then:
- switch.turn_on: sdms
- platform: gpio
name: "9.1.${sbm}_上升按钮"
pin:
number: ${ssan_gpio}
mode:
input: True
pullup: True
inverted: True
internal: True
filters:
- delayed_on_off: 300ms
on_press:
- switch.toggle: sang
- platform: gpio
name: "9.2.${sbm}_下降按钮"
internal: True
pin:
number: ${xjan_gpio}
mode:
input: True
pullup: True
inverted: True
filters:
- delayed_on_off: 300ms
on_press:
- switch.toggle: xia
- platform: gpio
name: "9.3.${sbm}_推出按钮"
internal: True
id: tui_an
pin:
number: ${tcan_gpio}
mode:
input: True
pullup: True
inverted: True
filters:
- delayed_on_off: 300ms
on_press:
- switch.toggle: tui
- platform: gpio
name: "9.4.${sbm}_拉回按钮"
internal: True
id: la_an
pin:
number: ${lhan_gpio}
mode:
input: True
pullup: True
inverted: True
filters:
- delayed_on_off: 300ms ##防误触
on_press:
- switch.toggle: la
- platform: gpio
name: "自动放吊篮按钮"
internal: True
id: zd_fang_an
pin:
number: ${zd_fang_gpio}
mode:
input: True
pullup: True
inverted: True
filters:
- delayed_on_off: 300ms ##防误触
on_press:
- switch.toggle: zdf_dl
- platform: gpio
name: "自动收吊篮按钮"
internal: True
id: zd_sou_an
pin:
number: ${zd_sou_gpio}
mode:
input: True
pullup: True
inverted: True
filters:
- delayed_on_off: 300ms ##防误触
on_press:
- switch.toggle: zds_dl
##传感器##
- platform: gpio ##拉杆外限位##;
pin:
number: ${lagan_w_gpio}
mode:
input: True
pullup: True
inverted: True
name: "2.3.${sbm}_推出到位"
id: lagan_w
device_class: door
on_press:
- script.execute: w_xiajiang
- script.execute: no_sengjiang
- script.execute: no_tuila
on_release:
- script.execute: no_sengjiang_lg
- platform: gpio ##拉杆内限位##;
pin:
number: ${lagan_n_gpio}
mode:
input: True
pullup: True
inverted: True
name: "2.4.${sbm}_拉回到位"
id: lagan_n
device_class: door
on_press:
- script.execute: w_xiajiang
- script.execute: no_sengjiang
- script.execute: no_tuila
- script.execute: no_sengjiang_lg
- platform: gpio ##吊篮上升限位##;
pin:
number: ${diaolan_s_gpio}
mode:
input: True
pullup: True
# inverted: True
name: "2.5.${sbm}_上升到位"
id: diaolan_s
device_class: door
filters:
- delayed_on_off: 600ms
on_press:
- sensor.rotary_encoder.set_value: ##把吊篮位置矫正为最高值;
id: dlwz
value: !lambda "return id(sdgd).state;"
##输出交换机##
switch:
##卷扬机继电器;
##上##;
- platform: gpio
pin: ${sang_gpio}
name: "3.1.${sbm}_上"
id: sang
interlock: &jidianqi [sang,xia,tui,la] ##连锁组;
interlock_wait_time: 2s
restore_mode: ALWAYS_OFF ##上电时默认关闭;
device_class: SWITCH ##实体开关类型
on_turn_on:
then:
- if:
condition:
switch.is_off: sdms
then:
- script.execute: no_sengjiang
- script.execute: no_sengjiang_lg
##下##;
- platform: gpio
pin: ${xia_gpio}
name: "3.2.${sbm}_下"
id: xia
interlock: *jidianqi ##连锁组;
interlock_wait_time: 2s
restore_mode: ALWAYS_OFF ##上电时默认关闭;
device_class: SWITCH ##实体开关类型
on_turn_on:
if:
condition:
switch.is_off: sdms
then:
script.execute: sengjiang
##电动拉杆继电器;
##推##;
- platform: gpio
pin: ${tui_gpio}
name: "3.3.${sbm}_推"
id: tui
interlock: *jidianqi ##连锁组;
interlock_wait_time: 1000ms
restore_mode: ALWAYS_OFF ##上电时默认关闭。
device_class: SWITCH ##实体开关类型
on_turn_on:
if:
condition:
switch.is_off: sdms
then:
script.execute: no_tuila
##拉##;
- platform: gpio
pin: ${la_gpio}
name: "3.4.${sbm}_拉"
id: la
interlock: *jidianqi ##连锁组;
interlock_wait_time: 1000ms
restore_mode: ALWAYS_OFF ##上电时默认关闭。
device_class: SWITCH ##实体开关类型
on_turn_on:
if:
condition:
switch.is_off: sdms
then:
script.execute: no_tuila
##模板开关##
- platform: template
name: "9.0${sbm}_手动模式"
id: sdms
optimistic: true ##实时反馈;
restore_mode: ALWAYS_OFF
on_turn_on: ##打开执行;
then:
- delay: 20s
- script.execute: off_sdms
- platform: template
name: "8.1.自动放${sbm}"
id: zdf_dl
optimistic: true ##实时反馈;
restore_mode: ALWAYS_OFF
on_turn_on: ##打开执行;
then:
- switch.turn_off: zds_dl
- if:
condition:
and:
- binary_sensor.is_on: lagan_n
then:
- delay: 600ms
- script.execute: zd_fangdiaolan
else:
- logger.log: "错误!吊篮不在内部位置,不能执行自动落吊篮"
- delay: 2s
- switch.turn_off: zdf_dl
on_turn_off: ##关闭执行;
then:
- script.stop: x_x
- platform: template
name: "8.2.自动收${sbm}"
id: zds_dl
optimistic: true ##实时反馈;
restore_mode: ALWAYS_OFF
on_turn_on: ##打开执行;
then:
- switch.turn_off: zdf_dl
- if:
condition:
- and:
- lambda: |-
return id(dlwz).state < id(sdgd).state;
- binary_sensor.is_off: lagan_n
then:
- delay: 600ms
- script.execute: zd_soudiaolan
else:
- logger.log: "错误!吊篮已是收回状态,不需要执行自动收吊篮"
- delay: 2s
- switch.turn_off: zds_dl
on_turn_off: ##关闭执行;
then:
- script.stop: x_x
|