Xiao ESP32C3 ESPHome 智能 ThermoStat
这篇 Wiki 将逐步指导如何制作一个 Xiao ESP32C3 ESPHome 智能温控器。现在我们开始吧!
硬件准备
如果你想完整地跟随本教程,你需要准备以下硬件。
Seeed Studio XIAO ESP32C3 | Seeed Studio 扩展板 | Home Assistant 设备 e.g. Seeed Studio 家居助理 黄色 |
---|---|---|
Grove Sensors
Grove - 温度和湿度传感器Pro (DHT22/AM2302) | Grove - 2 通道 SPDT 继电器 | Grove - 继电器大电流 5V/10A | Grove - OLED 显示屏 0.96 英寸(SSD1315) | 瞬时按钮(任何类型都可以) |
---|---|---|---|---|
软件准备
安装 Home Assistant
确保你已经安装并运行了 Home Assistant。这里有多篇 Wiki 介绍如何将 Home Assistant 刷入 产品 。 我使用的是由 Raspberry Pi CM4 提供支持的 Home Assistant Yellow,所以我可以 直接使用官方方式将操作系统刷入 Home Assistant Yellow。
在 Home Assistant 上安装 ESPHome
ESPHome 可以作为 Home Assistant 插件 安装,可以通过插件商店轻松安装。
- 步骤 1. 点击 INSTALL
- 步骤 2. 启用所有选项并点击 START
如果 ESPHome 成功加载,你将看到以下窗口:
开始使用
一旦所有的软件和硬件都准备好,我们就可以开始了。
1. 将 Seeed Studio XIAO ESP32C3 添加到 ESPHome
- 步骤 1. 点击 + NEW DEVICE
- 步骤 2. 点击 CONTINUE
- 步骤 3. 输入设备的 名称 并输入WiFi 凭据,如 网络名称 和 密码。然后点击 下一步
- 步骤 4. 选择 ESP32-C3 并点击
- 步骤 5. 点击 SKIP 因为我们将手动配置这个板子
2. 创建并上传 YAML 配置
- 步骤 1. 点击 EDIT 在新创建的 Board 下
步骤 7. 创建并上传 YAML 配置
代码说明:
名称:"thermostat"
板子配置:
闪存模式设置为 DIO。
板子指定为 "seeed_xiao_esp32c3",使用 Arduino 框架。开机时的操作:
显示日志信息:"Booting thermostat."
关闭三个继电器:heat、cooling 和 fan。
延迟 500 毫秒。
执行名为 "boot_beep" 的脚本。脚本配置:
启动蜂鸣脚本:
打开蜂鸣器,将其频率设置为产生蜂鸣声,并在 300 毫秒后关闭。API 和 OTA 配置:
API:
指定了加密密钥。
OTA:
设置密码为 "13371337" 用于无线更新。蜂鸣器输出:
使用 LEDC 平台配置,连接到引脚 5。Wi-Fi 配置:
指定连接 Wi-Fi 的 SSID 和密码。
回退热点(强制门户)配置为 SSID "Xiao-Esp32C3" 和密码 "13371337"。I2C 配置:
配置与 SDA 引脚 6 和 SCL 引脚 7 的 I2C 通信。字体配置:
为显示器定义了两种不同大小的字体。显示器配置:
使用 SSD1315 I2C 显示器,并通过 lambda 函数格式化和显示信息。 显示温度(华氏度)、湿度、Wi-Fi 信号强度和 IP 地址。传感器配置:
使用 DHT22 传感器读取温度和湿度,更新间隔为 10 秒。
包含 Wi-Fi 信号传感器,更新间隔为 20 秒。文本传感器配置:
显示温控器的 IP 地址和 ESPHome 版本。开关配置:
配置三个 GPIO 开关,用于 relay_heat、relay_cooling 和 relay_fan。二进制传感器配置:
配置一个二进制传感器,用于循环风扇按钮按下。
按下按钮时,它控制气候系统的风扇模式。气候配置:
使用指定的温度传感器实现温控功能。
定义加热、冷却、风扇模式和空闲状态的动作。
设置温度限制、步骤大小和默认预设。
将此内容粘贴到您的 ESPHome 设备配置 yaml 文件中。您也可以点击 这里 下载完整的 .yaml 文件。
esphome:
name: ecostat
platformio_options:
board_build.flash_mode: dio
on_boot:
priority: 750
then:
- logger.log: "Booting EcoStat"
- delay: 500ms
- lambda: |-
id(relay_heat).turn_off();
id(relay_cooling).turn_off();
id(relay_fan).turn_off();
id(ecostat_control_heat).mode = CLIMATE_MODE_OFF;
id(ecostat_control_cooling).mode = CLIMATE_MODE_OFF;
- script.execute: boot_beep
esp32:
board: seeed_xiao_esp32c3
variant: esp32c3
framework:
type: arduino
platform_version: 5.4.0
#logger:
# 级别:VERY_VERBOSE
api:
encryption:
key: "YOURKEYHERE"
ota:
password: "13371337"
script:
- id: boot_beep
then:
# 第一 ^E
- output.turn_on: buzzer
- output.ledc.set_frequency:
id: buzzer
frequency: 659.25Hz # E
- output.set_level:
id: buzzer
level: "50%"
- delay: 150ms
- output.turn_off: buzzer
- output.turn_on: buzzer
- output.ledc.set_frequency:
id: buzzer
frequency: 1000Hz
- output.set_level:
id: buzzer
level: "50%"
- delay: 150ms
- output.turn_off: buzzer
output:
- platform: ledc
pin: 5
id: buzzer
wifi:
ssid: YOURWIFINAME
password: YOURWIFIPASS
# 在 wifi 连接失败的情况下启用回退热点(强制门户)
ap:
ssid: "Xiao-Esp32C3 Fallback Hotspot"
password: "13371337"
i2c:
sda: 6
scl: 7
scan: False
font:
# gfonts://family[@weight]
- file: "gfonts://Roboto"
id: roboto
size: 20
- file: "gfonts://Poppins@700"
id: inter
size: 10
display:
- platform: SSD1315_i2c
id: oled
model: "SSD1315 128x64"
address: 0x3C
lambda: |-
float temp_celsius = id(temp).state;
float temp_fahrenheit = (temp_celsius * 9.0 / 5.0) + 32.0;
char temp_str[6]; // Buffer for temperature string
dtostrf(temp_celsius, 4, 1, temp_str); // Convert Celsius to string with 1 decimal place
it.print(28, 0, id(inter), id(ip_address).state.c_str());
it.printf(0, 18, id(roboto), "T: %.1f ", temp_fahrenheit);
it.printf(70, 18, id(roboto), "H: %d", int(id(humidity).state));
it.printf(31, 45, id(inter), "RSSI: %d", int(id(rssi).state));
climate:
- platform: thermostat
name: "EcoStat Heating"
id: ecostat_control_heat
sensor: temp
heat_deadband: 2 °F
heat_overrun: 0
min_heating_run_time: 60s
min_heating_off_time: 120s
min_idle_time: 3min
visual:
min_temperature: 60 °F
max_temperature: 80 °F
temperature_step:
current_temperature: 0.1
target_temperature: 1.0
target_temperature_low: 65 °F
heat_action:
- switch.turn_on: relay_heat
idle_action:
- switch.turn_off: relay_heat
default_preset: Normal
preset:
- name: Normal
default_target_temperature_low: 65 °F
- platform: thermostat
name: "EcoStat Cooling"
id: ecostat_control_cooling
sensor: temp
cool_deadband: 2 °F
cool_overrun: 0
min_cooling_off_time: 20s
min_cooling_run_time: 60s
min_idle_time: 3min
visual:
min_temperature: 60 °F
max_temperature: 80 °F
temperature_step:
current_temperature: 0.1
target_temperature: 1.0
target_temperature_low: 70 °F
cool_action:
- switch.turn_on: relay_cooling
idle_action:
- switch.turn_off: relay_cooling
min_fan_mode_switching_time: 20s
fan_mode_on_action:
- switch.turn_on: relay_fan
fan_mode_off_action:
- switch.turn_off: relay_fan
default_preset: Normal
preset:
- name: Normal
default_target_temperature_high: 70 °F
sensor:
- platform: dht
pin: 20
model: DHT22
update_interval: 10s
temperature:
name: "EcoStat Temperature"
id: temp
humidity:
name: "EcoStat Humidity"
id: humidity
- platform: wifi_signal
name: "Wi-Fi Signal Strength"
id: rssi
update_interval: 20s
text_sensor:
- platform: wifi_info
ip_address:
name: "EcoStat IP Address"
id: ip_address
- platform: version
name: "EcoStat ESPHome Version"
switch:
- platform: gpio
id: relay_heat
pin:
number: 10
mode: OUTPUT
- platform: gpio
id: relay_cooling
pin:
number: 9
mode: OUTPUT
- platform: gpio
id: relay_fan
pin:
number: 21
mode: OUTPUT
binary_sensor:
- platform: gpio
id: tempup
pin:
number: 8
mode: INPUT_PULLUP
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
then:
- lambda: |-
if (id(ecostat_control_heat).mode == esphome::climate::CLIMATE_MODE_HEAT) {
auto current_target_temp = id(ecostat_control_heat).target_temperature_low;
id(ecostat_control_heat).target_temperature_low = current_target_temp + 0.56;
auto current_target_temp_high = id(ecostat_control_heat).target_temperature_high;
id(ecostat_control_heat).target_temperature_high = current_target_temp_high + 0.56;
} else if (id(ecostat_control_cooling).mode == esphome::climate::CLIMATE_MODE_COOL) {
auto current_target_temp = id(ecostat_control_cooling).target_temperature_low;
id(ecostat_control_cooling).target_temperature_low = current_target_temp + 0.56;
auto current_target_temp_high = id(ecostat_control_cooling).target_temperature_high;
id(ecostat_control_cooling).target_temperature_high = current_target_temp_high + 0.56;
}
- platform: gpio
id: tempdown
pin:
number: 2
mode: INPUT_PULLUP
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
then:
- lambda: |-
if (id(ecostat_control_heat).mode == esphome::climate::CLIMATE_MODE_HEAT) {
auto current_target_temp = id(ecostat_control_heat).target_temperature_low;
id(ecostat_control_heat).target_temperature_low = current_target_temp - 0.56;
auto current_target_temp_high = id(ecostat_control_heat).target_temperature_high;
id(ecostat_control_heat).target_temperature_high = current_target_temp_high - 0.56;
} else if (id(ecostat_control_cooling).mode == esphome::climate::CLIMATE_MODE_COOL) {
auto current_target_temp = id(ecostat_control_cooling).target_temperature_low;
id(ecostat_control_cooling).target_temperature_low = current_target_temp - 0.56;
auto current_target_temp_high = id(ecostat_control_cooling).target_temperature_high;
id(ecostat_control_cooling).target_temperature_high = current_target_temp_high - 0.56;
}
- platform: gpio
id: modeswitch
pin:
number: 3
mode: INPUT_PULLUP
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
then:
- lambda: |-
auto current_mode = id(ecostat_control_heat).mode;
if (current_mode == esphome::climate::CLIMATE_MODE_OFF) {
id(ecostat_control_heat).mode = esphome::climate::CLIMATE_MODE_HEAT;
} else if (current_mode == esphome::climate::CLIMATE_MODE_HEAT) {
id(ecostat_control_heat).mode = esphome::climate::CLIMATE_MODE_COOL;
} else if (current_mode == esphome::climate::CLIMATE_MODE_COOL) {
id(ecostat_control_heat).mode = esphome::climate::CLIMATE_MODE_OFF;
}
- platform: gpio
id: momentaryswitch0
pin:
number: 4
mode: INPUT_PULLUP
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
then:
- if:
condition:
switch.is_off: relay_fan
then:
- climate.control:
id: ecostat_control_cooling
fan_mode: "on"
else:
- climate.control:
id: ecostat_control_cooling
fan_mode: "off"
3. 组装选择的外壳(可选)
这是我为这个项目使用的外壳的 STL 文件:
随意使用或修改这些文件。如果你没有 3D 打印机,网上有很多服务可以打印这些文件,并使用你想要的任何材料。
4. 安装组件
步骤 1:将所有列出的组件安装到外壳中
使用 M2x4 和 M2x6 螺钉,将所有之前列出的组件安装到外壳中的对应位置。
(DHT22 传感器直接压入固定位置)。
步骤 2:将所有传感器和外设连接到上述 YAML 文件中对应的引脚
这是我在连接过程中使用的方法:
- DHT22/SSD1315 - 使用 JST 连接器: 对 DHT22 和 SSD1315 连接器进行去焊并将其翻转至 PCB 的另一侧,以确保合适的安装。
两种类型的继电器 - 使用 JST/DuPont 连接器: 对于继电器,我在一侧使用了 JST 连接器,另一侧则使用杜邦连接器用于扩展板上的 GPIO 引脚。
电池连接: 我还将一个 3.7V 锂电池连接到扩展板的电池接口,用作主电源丢失时的备用电池。
步骤 3:将所需样式的短时按钮连接到外壳的前面
我通过使用一些热熔胶将按钮固定在外壳前面,然后将线缆焊接到短时按钮的对角引脚上,并将杜邦连接器连接到线缆的另一端,以连接到扩展板上的正确 GPIO 引脚。
步骤 4:将显示屏装入前盖的后部
将显示屏装入前盖的后部(用少量热熔胶固定)。然后使用 3 个 M4x6 螺钉将前盖固定到外壳上,如下图所示。
5. 将电缆连接到 EcoStat 上对应的继电器
智能温控器完成!只需将现有的家庭温控器拆除,使用下图连接正确的电缆至 EcoStat 上的对应继电器即可!
✨ 贡献者项目
技术支持与产品讨论
感谢您选择我们的产品!我们在此提供多种支持,以确保您使用我们的产品时能有顺利的体验。我们提供多种沟通渠道,以满足不同的需求和偏好。