@bryanw Since 2024.5.4 (May 28th release) OTA is fixed for me!
I needed to retry the OTA installation several times, but it then worked.
See release notes ESPHome 2024.5.0 - 15th May 2024 — ESPHome
with the fix “Also reduces fw size.”
[helpers] Move Base64 string to cpp by gabest11 · Pull Request #6819 · esphome/esphome · GitHub
Still, if the latest OTA really doesn’t work for you, then do a 2-step OTA procedure:
First, install a minimal version with OTA.
Second, install the full version with OTA.
Don’t forget to change your friendly_name, name and key.
Note: sometimes i had to retry the update several times until it went through.
Step 1 - Minimal OTA config
substitutions:
name: athom-presence-sensor-my-id
friendly_name: My Nice Athom
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
esp8266:
board: esp8285
ota:
logger:
api:
encryption:
key: XYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZ
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
Step 2 - Full OTA config
substitutions:
name: athom-presence-sensor-my-id
friendly_name: My Nice Athom
packages:
Athom_Technology.Presence_Sensor: github://athom-tech/athom-configs/athom-presence-sensor.yaml
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
api:
encryption:
key: XYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZ
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
1 Like
bryanw
June 8, 2024, 3:23pm
122
@Hell255 - Thank you for sharing this information! I noticed my Athom sensors updated fine now. Glad it was fixed.
1 Like
DeLorean
(Loryan Strant)
June 29, 2024, 10:57pm
123
Thanks for sharing this, but even with the base config and trying it a BUNCH of times including resetting the device - I didn’t have any luck.
I think I’m going to have to factory reset my two units, adopt them, and then update their configs.
1 Like
I have 2 of these. One in my living room and one in my basement media area. Main purpose is to turn off the lights/tv when no one is there and they are left on. I am overall very happy with the devices. using blakadder’s config.
I have several different esp based presence sensors (screek, athom, apollo, seeedstudio kit). The best in my opinion on accuracy/true positives/false positives are the screeks. I haven’t played much with the apollo one yet. The athoms are good enough and reliable enough that I put them to use right away with minimal tweaking to get the result I was looking for. I would recommend also looking into the screek products (I am using two 2A’s and one 1U). They don’t however have a PIR if that is something you specifically are wanting.
bryanw
September 10, 2024, 2:54am
125
Thanks for sharing your experience! I was considering the screek devices for a time, then decided to just build the rest of my presence sensors using ESP32 boards and sensors from Ali Express.
The “homemade” presence sensors work well now, but required a LOT more tuning that the Athom sensor. Athom sensors work really well and require minimal setup. Glad to hear the screek are pretty good too. I believe the Apollo is highly rated & you’ll find that works very well too.
sparkydave
(🇦🇺 Dave)
November 28, 2024, 6:32am
126
I’m thinking a nice upgrade to these sensors would be a temperature sensor. Has anyone else tried doing this? It looks like there’s a few free I/O’s which could possibly make this work with a DS18B20 or something.
bryanw
January 12, 2025, 6:37pm
127
I haven’t tried a temperature sensor yet. If anyone has please share your experience.
alex.hubery
(Alex Hubery)
February 19, 2025, 9:00am
128
thanks for this info. I too had had the PS01 working fine for 7 days and then for some reason the presence sensor stopped clearing. After making the adjustments you suggested this now appears to be back to normal again
funky1
(funky1)
February 22, 2025, 9:43am
129
Yes. Had it today. Just a cold soldering. Mine was started to be stable after i resoldered with 320 degrees C the dupont pin headers with some extra flux.
I have two of these devices that have their mmWave sensors stuck on “Detected”. Tried different ESPHome configs to no avail.
cemara
May 11, 2025, 4:39am
131
Does anyone have yaml / bin config that allows static IP input?
tried giving wifi address like this but after flashing the device seems to brick, serial logging wont work… the led just stays solid
substitutions:
name: athom-presence-34987ad939ad
friendly_name: athom-presence-34987ad939ad
esphome:
name: athomps-smokingtengah1
name_add_mac_suffix: False
friendly_name: athomps-smokingtengah1
packages:
Athom_Technology.Athom_PS01C3_Presence_Sensor: github://athom-tech/esp32-configs/athom-presence-sensor-v3.yaml
#esp8266:
# board: esp8285
#logger:
# Enable Home Assistant API
api:
encryption:
key: "REi5jjC0XhoMiWPme8Hwsf0edtZAi607/UNdVHmq5Pk="
ota:
- platform: esphome
password: "dd38ef4b97286d5c0df15f04700302db"
wifi:
ssid: "cemara_tool"
password: ""
manual_ip:
static_ip: 192.168.88.178
gateway: 192.168.88.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
This is mine:
wifi:
ssid: !secret wifi_ssid_not_1
password: !secret wifi_password_not_1
manual_ip:
static_ip: 192.168.30.181
gateway: 192.168.30.1
subnet: 255.255.255.0
Works fine.
cemara
May 12, 2025, 12:00am
133
Could you share the complete yaml? For some reason the web flasher says flash is successful but it bricks the sensor…
Yeah, no problem.
substitutions:
name: "alfresco-presence-sensor"
friendly_name: "Alfresco Presence Sensor"
# room: ""
device_description: "mmwave radar human presence sensor"
project_name: "Athom Technology.Presence Sensor"
project_version: "1.0-blak"
pir_delay_off: "1s" # set the PIR no occupancy delay here, it also influences delay for Occupancy sensor
esphome:
name: "${name}"
friendly_name: "${friendly_name}"
name_add_mac_suffix: true
project:
name: "${project_name}"
version: "${project_version}"
esp8266:
board: esp8285
restore_from_flash: True
logger:
api:
ota:
platform: esphome
mdns:
disabled: false
web_server:
port: 80
wifi:
ssid: !secret wifi_ssid_not_1
password: !secret wifi_password_not_1
manual_ip:
static_ip: 192.168.30.181
gateway: 192.168.30.1
subnet: 255.255.255.0
captive_portal:
dashboard_import:
package_import_url: github://blakadder/esphome-configs/athom_ps01.yaml
light:
- platform: status_led
name: "Status LED"
id: led
pin: GPIO16
disabled_by_default: true
entity_category: config
i2c:
sda: GPIO4
scl: GPIO5
scan: true
uart:
tx_pin: GPIO15
rx_pin: GPIO13
baud_rate: 115200
# debug:
# direction: BOTH
# dummy_receiver: true
# after:
# delimiter: "\n"
# sequence:
# - lambda: UARTDebug::log_string(direction, bytes);
binary_sensor:
- platform: status
name: "Status"
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: true
name: "Button"
disabled_by_default: true
internal: true
on_multi_click:
- timing:
- ON for at least 10s
then:
- button.press: factory_reset_device
- platform: gpio
pin:
number: GPIO14
mode:
input: true
pullup: true
name: "Pir Sensor"
id: pir
filters:
# - delayed_on: 50ms
# - delayed_off: 500ms
- delayed_off: ${pir_delay_off}
device_class: motion
# on_press:
# then:
# - light.turn_on: led
- platform: gpio
pin:
number: GPIO12
mode:
input: true
pullup: true
name: "mmWave Sensor"
id: mmwave
# filters:
# - delayed_on: 50ms
device_class: occupancy
on_press:
then:
- light.turn_on: led
on_release:
then:
- light.turn_off: led
- platform: template
name: "Occupancy"
id: occupancy
device_class: occupancy
lambda: |-
if ( id(mmwave).state or id(pir).state) {
return true;
}
else if (id(mmwave).state == 0 and id(pir).state == 0) {
return false;
}
else {
return id(occupancy).state;
}
sensor:
- platform: uptime
name: "Uptime Sensor"
- platform: wifi_signal
name: "WiFi Signal Sensor"
update_interval: 60s
- platform: bh1750
name: "Light Sensor"
address: 0x23
update_interval: 5s
switch:
- platform: template
name: "mmWave Status"
id: "mmwave_sensor"
internal: true
entity_category: config
optimistic: true
restore_mode: DISABLED
turn_on_action:
- uart.write: "sensorStart\r\n"
turn_off_action:
- uart.write: "sensorStop\r\n"
number:
- platform: template
name: Farthest Detection #Value range: 1.9 ~ 12m Default: 6
id: Farthest_Detection
entity_category: config
min_value: 1.9
max_value: 12
initial_value: 6
optimistic: true
step: 0.1
restore_value: true
unit_of_measurement: m
mode: box
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda
std::string ranges = "setRange 1.8 " + str_sprintf("%.1f",id(Farthest_Detection).state) + "\r\n";
return std::vector<uint8_t>(ranges.begin(), ranges.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
- platform: template
name: Maintain Sensitivity #Value range: 0 ~ 9 Default Maintain sensitivity: 7
id: Maintain_Sensitivity
entity_category: config
min_value: 0
max_value: 9
initial_value: 7
optimistic: true
step: 1
restore_value: true
mode: slider
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda
std::string sensitivitys = "setSensitivity " + str_sprintf("%.0f",id(Maintain_Sensitivity).state) + " " + str_sprintf("%.0f",id(Trigger_Sensitivity).state) + "\r\n";
return std::vector<uint8_t>(sensitivitys.begin(), sensitivitys.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
- platform: template
name: Trigger Sensitivity #Value range: 0 ~ 9 Default Trigger sensitivity: 5
id: Trigger_Sensitivity
entity_category: config
min_value: 0
max_value: 9
initial_value: 5
optimistic: true
step: 1
restore_value: true
mode: slider
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda
std::string sensitivityss = "setSensitivity " + str_sprintf("%.0f",id(Maintain_Sensitivity).state) + " " + str_sprintf("%.0f",id(Trigger_Sensitivity).state) + "\r\n";
return std::vector<uint8_t>(sensitivityss.begin(), sensitivityss.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
- platform: template
name: Detection Delay #Confirmation delay Value range: 0 ~ 100 default 0.050 seconds.
id: Detection_Delay
entity_category: config
min_value: 0.05
max_value: 60
initial_value: 0.05
optimistic: true
step: 0.05
mode: box
restore_value: true
unit_of_measurement: seconds
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda |-
std::string detections = "setLatency " + str_sprintf("%.1f",id(Detection_Delay).state) + " " + str_sprintf("%.0f",id(Fading_Time).state) + "\r\n";
return std::vector<uint8_t>(detections.begin(),detections.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
- platform: template
name: Fading Time #Fade-out delay Value range: 0.5 ~ 1500, default 15 seconds.
id: Fading_Time
entity_category: config
min_value: 0.5
max_value: 300
initial_value: 15
optimistic: true
step: 0.5
restore_value: true
unit_of_measurement: seconds
mode: auto
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda |-
std::string fadings = "setLatency " + str_sprintf("%.1f",id(Detection_Delay).state) + " " + str_sprintf("%.0f",id(Fading_Time).state) + "\r\n";
return std::vector<uint8_t>(fadings.begin(), fadings.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
- platform: template
name: Blockade Time #Configure block time Value range: 1 ~ 255, default 1 seconds.
id: Blockade_Time
entity_category: config
min_value: 1
max_value: 255
initial_value: 1
optimistic: true
step: 1
restore_value: true
unit_of_measurement: seconds
mode: box
set_action:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: !lambda
std::string blockades = "setInhibit " + str_sprintf("%.0f",x) + "\r\n";
return std::vector<uint8_t>(blockades.begin(), blockades.end());
- delay: 500ms
- uart.write: "saveConfig\r\n"
- delay: 500ms
- switch.turn_on: mmwave_sensor
button:
- platform: factory_reset
name: Restart with Factory Default Settings
id: Reset
entity_category: config
internal: true
- platform: template
name: "Reset device"
id: "factory_reset_device"
entity_category: config
internal: true
on_press:
- switch.turn_off: mmwave_sensor
- delay: 500ms
- uart.write: "resetCfg\r\n"
- delay: 1s
- switch.turn_on: mmwave_sensor
- button.press: Reset
- platform: restart
name: Restart_esp
id: restart_esp
entity_category: config
internal: true
- platform: template
name: "Restart_mmWave"
id: "restart_mmwave"
entity_category: config
internal: true
on_press:
- uart.write: "resetSystem\r\n"
- platform: template
name: Restart device
entity_category: config
on_press:
- button.press: restart_mmwave
- delay: 1s
- button.press: restart_esp
text_sensor:
- platform: wifi_info
ip_address:
name: "IP Address"
ssid:
name: "Connected SSID"
disabled_by_default: true
mac_address:
name: "Mac Address"
disabled_by_default: true
# - platform: version
# name: ${name} ESPHome Version
time:
- platform: sntp
id: my_time
1 Like
cemara
May 12, 2025, 1:30am
135
Awesome it works! Why didn’t I think of using blakadder’s yaml before…
But would there be any difference performance/accuracy wise compared to the original code? Or is it the same thing?
I’ve been using his code for a long time now and the 2 devices I have are working well. From memory it mainly improved the settings adjustability.
1 Like
cemara
May 13, 2025, 4:37am
137
I figured out my problem, apparently there are 2 types of chip, C3 and 8285, you can look at the back of the sensor, C3 has PS01C3 and 8285 should only have PS01, no wonder it bricked cause i used wrong yaml.
This is the ESP8285
substitutions:
# Default name
name: "athom-presence-sensor"
# Default friendly name
friendly_name: "Athom Presence Sensor"
# Allows ESP device to be automatically linked to an 'Area' in Home Assistant. Typically used for areas such as 'Lounge Room', 'Kitchen' etc
room: ""
# Description as appears in ESPHome & top of webserver page
device_description: "athom mmwave radar human presence sensor"
# Project Name
project_name: "Athom Technology.Athom Presence Sensor"
# Projection version denotes the release version of the yaml file, allowing checking of deployed vs latest version
project_version: "v1.0.3"
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
dns_domain: ".local"
# Set timezone of the smart plug. Useful if the plug is in a location different to the HA server. Can be entered in unix Country/Area format (i.e. "Australia/Sydney")
timezone: ""
# Set the duration between the sntp service polling ntp.org servers for an update
sntp_update_interval: 6h
# Network time servers for your region, enter from lowest to highest priority. To use local servers update as per zones or countries at: https://www.ntppool.org/zone/@
This file has been truncated. show original
This is the ESP32C3
substitutions:
# Default name
name: "athom-presence-sensor-v3"
# Default friendly name
friendly_name: "Athom Presence Sensor"
# Allows ESP device to be automatically linked to an 'Area' in Home Assistant. Typically used for areas such as 'Lounge Room', 'Kitchen' etc
room: ""
# Description as appears in ESPHome & top of webserver page
device_description: "athom esp32-c3 mmwave radar human presence sensor"
# Project Name
project_name: "Athom Technology.Athom PS01C3 Presence Sensor"
# Projection version denotes the release version of the yaml file, allowing checking of deployed vs latest version
project_version: "v3.0.3"
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
dns_domain: ".local"
# Set timezone of the smart plug. Useful if the plug is in a location different to the HA server. Can be entered in unix Country/Area format (i.e. "Australia/Sydney")
timezone: ""
# Set the duration between the sntp service polling ntp.org servers for an update
sntp_update_interval: 6h
# Network time servers for your region, enter from lowest to highest priority. To use local servers update as per zones or countries at: https://www.ntppool.org/zone/@
This file has been truncated. show original
2 Likes
Greminn
(Simon)
July 15, 2025, 9:47pm
138
Good spotting @cemara . Was having the same issues as you and this as sorted it. I see @blakadder has not updated his config for the new C3/PS01C3 model, so I did some mucking around here to update his old athom_ps01.yaml config .
Note I have very little knowledge on how to contribute to a GitHub project, so I muddled my way thru this process
substitutions:
name: "athom-presence-sensor-c3"
friendly_name: "Athom Presence Sensor C3"
device_description: "mmwave radar human presence sensor"
project_name: "Athom Technology.Presence Sensor"
project_version: "1.0-blak-v3"
timezone: "Pacific/Auckland" #set to your timezone
sntp_server_1: "0.pool.ntp.org"
sntp_server_2: "1.pool.ntp.org"
sntp_server_3: "2.pool.ntp.org"
pir_delay_off: "1s" # set the PIR no occupancy delay here, it also influences delay for Occupancy sensor
esphome:
name: "${name}"
friendly_name: "${friendly_name}"
project:
name: "${project_name}"
version: "${project_version}"
platformio_options:
board_build.flash_mode: dio
This file has been truncated. show original
1 Like
pOpY
September 26, 2025, 6:20am
139
Hi guys.
I have several ESP32-C3 versions and noticed that the lux meassurement differs to my old hue motion sensors.
The difference is about:
~20 lux diff in the lows < 100
~60 lux diff in higher values >= 200
Anyone of you noticed that?
Do you just adopt your automations on switching from other sensors like hue compensate it with an modification of the yaml like this:
or an helper sensor in HA?