Skip to main content

Xiao ESP32C3 ESPHome 智能恒温器

pir

本教程将逐步介绍如何制作一个 Xiao ESP32C3 ESPHome 智能恒温器。现在让我们开始吧!

硬件准备

如果您想完整地跟随本教程,您需要准备以下物品。

Seeed Studio XIAO ESP32C3Seeed Studio 扩展板Home Assistant 设备
例如 Seeed Studio Home assistant Yellow

Grove 传感器

Grove - 温湿度传感器 Pro (DHT22/AM2302)Grove - 2通道 SPDT 继电器Grove - 大电流继电器 5V/10AGrove - OLED 显示屏 0.96" (SSD1315)瞬时按钮(任何类型都可以)

pir

pir

pir

pir

pir

软件准备

安装 Home Assistant

确保您已经安装并运行了 Home Assistant。这里有多个介绍如何将 Home Assistant 刷入产品的 wiki。我使用的是由 Raspberry Pi CM4 供电的 Home Assistant Yellow,所以我可以直接使用官方方法将操作系统刷入 Home Assistant Yellow

在 Home Assistant 上安装 ESPHome

ESPHome 作为 Home Assistant 插件提供,可以通过插件商店简单安装。

pir

  • 步骤 1. 点击 INSTALL
  • 步骤 2. 启用所有选项并点击 START

如果 ESPHome 成功加载,您将看到以下窗口

开始使用

一旦所有软件和硬件都准备就绪,我们现在就可以开始了。

1. 将 Seeed Studio XIAO ESP32C3 添加到 ESPHome

  • 步骤 1. 点击 + NEW DEVICE
  • 步骤 2. 点击 CONTINUE
  • 步骤 3. 为设备输入名称,并输入 WiFi 凭据,如网络名称密码。然后点击 NEXT
  • 步骤 4. 选择 ESP32-C3 并点击
  • 步骤 5. 点击 SKIP,因为我们将手动配置此板

2. 创建并上传 YAML 配置

  • 步骤 1. 点击新创建板下的 EDIT
  • 步骤 7. 创建并上传 YAML 配置

    下面代码的说明:

    • 名称: "thermostat"

    • 板配置:
      闪存模式设置为 DIO。
      板指定为"seeed_xiao_esp32c3",使用 Arduino 框架。

    • 启动时操作:
      显示日志消息:"Booting thermostat."
      关闭三个继电器:加热、制冷和风扇。
      延迟 500 毫秒。
      执行名为"boot_beep"的脚本。

    • 脚本配置:
      启动蜂鸣脚本:
      打开蜂鸣器,设置其频率以产生蜂鸣声,并在 300 毫秒后关闭。

    • API 和 OTA 配置:
      API:
      指定加密密钥。
      OTA:
      为无线更新设置密码为"13371337"。

    • 蜂鸣器输出:
      使用 LEDC 平台配置,引脚为 5。

    • WiFi 配置:
      指定连接到 Wi-Fi 的 SSID 和密码。
      配置后备热点(强制门户),SSID 为"Xiao-Esp32C3",密码为"13371337"。

  • I2C 配置:
    配置 I2C 通信,SDA 引脚为 6,SCL 引脚为 7。

    • 字体配置:
      为显示屏定义两种不同大小的字体。

    • 显示屏配置:
      使用 SSD1315 I2C 显示屏,通过 lambda 函数格式化和显示信息。
      显示华氏温度、湿度、Wi-Fi 信号强度和 IP 地址。

    • 传感器配置:
      使用 DHT22 传感器读取温度和湿度,更新间隔为 10 秒。
      包含 Wi-Fi 信号传感器,更新间隔为 20 秒。

    • 文本传感器配置:
      显示恒温器的 IP 地址和 ESPHome 版本。

    • 开关配置:
      为 relay_heat、relay_cooling 和 relay_fan 配置三个 GPIO 开关。

    • 二进制传感器配置:
      为循环风扇按钮按压配置二进制传感器。
      按下时,控制气候系统的风扇模式。

    • 气候配置:
      使用指定的温度传感器实现恒温器控制。
      定义加热、制冷、风扇模式和空闲的动作。
      设置温度限制、步长和默认预设。

    将此内容粘贴到您的 ESPHome 设备配置 yaml 文件中。您也可以在这里下载完整的 .yaml 文件

esphome:
name: ecostat
platformio_options:
board_build.flash_mode: dio
on_boot:
priority: 750
then:
- logger.log: "启动 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:
# level: 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]; // 温度字符串缓冲区
dtostrf(temp_celsius, 4, 1, temp_str); // 将摄氏度转换为字符串,保留1位小数

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 加热"
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 制冷"
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 温度"
id: temp
humidity:
name: "EcoStat 湿度"
id: humidity
- platform: wifi_signal
name: "Wi-Fi 信号强度"
id: rssi
update_interval: 20s

text_sensor:
- platform: wifi_info
ip_address:
name: "EcoStat IP 地址"
id: ip_address
- platform: version
name: "EcoStat ESPHome 版本"

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文件。

EcoStatV2 ecostatcase

EcoStatV2 ecostatlid

请随意使用或修改它们。如果您个人没有3D打印机,网上有很多服务可以用您想要的任何材料打印这些文件。

pir

4. 安装组件

步骤1 将所有列出的组件安装到外壳中

使用M2x4和M2x6螺丝,将所有之前列出的组件安装到外壳内相应的位置。
(DHT22传感器只需压入到位即可)。

pir

步骤2. 将所有传感器和外设连接到前述YAML中相应的引脚

以下是我在连接过程中使用的方法:

  • DHT22/SSD1315 - 使用JST连接器: 将DHT22和SSD1315的连接器拆焊并翻转到其PCB的另一面,以便正确安装。
  • 两种类型的继电器 - 使用JST/DuPont连接器: 对于继电器,我在一侧使用JST,另一侧使用DuPont连接器连接到扩展板上的GPIO分线头。

  • 电池连接: 我还将一个3.7V锂电池插入扩展板的电池连接器,用作主电源断电时的备用电池。

pir

步骤3. 将所需样式的瞬时按钮连接到外壳前面的内侧

我通过用一点热熔胶固定按钮来完成这项工作。然后我将导线焊接到瞬时按钮的对角相对引脚上,并在导线的另一端放置DuPont连接器,以连接到扩展板上正确的GPIO分线头。

pir

步骤4. 将屏幕组装到前盖的后面

将屏幕组装到前盖的后面(用少量热熔胶固定到位)。然后用3个M4x6螺丝将前盖固定到外壳上,如下所示。

pir

5. 将导线连接到EcoStat上相应的继电器

智能恒温器完成!只需拆除您家中现有的恒温器,并使用下图将正确的导线连接到EcoStat上相应的继电器!

pir

✨ 贡献者项目

技术支持与产品讨论

感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。

Loading Comments...