I thought it would be best to share our progress with the LD2450 here, as of right now, we’ve made about 500+ DIY sensors for the LD2450.
It took us two months from the release of this module, to testing and designing the enclosure.
We are happy that in the recent test firmware, after getting feedback and suggestions from users, we have initially added three area detection and one exclusion area detection.
I don’t think this is a new thing, but still, we would like to have it here as a post to facilitate the exchange and discussion of this LD2450 radar module.
We have organized the documentation and information we have gathered at: Human Sensor 2A - Screek Workshop
Human Sensor 2A Zone Function Demo - YouTube
After getting a lot of feedback from users, we embarked on a lot of improvements to the original firmware, and now, judging by the feedback from the recent test firmware V230810_2_Beta, it’s working pretty well in general with the zone feature.
But there is still some room for improvement:For example, support for multiplayer mode in the official ld2450 firmware, and the demo mode, which we’ve heard from the hilink developers will be available this month. At least the multiplayer mode is already in their internal testing.
The display in HomeAssistant still doesn’t take full advantage of the intuitive function of coordinates, and we are still looking forward to working with you all to refine a lovelace display that shows a room area with a few dots moving around, which would be a lot cooler than the primitive ID display that shows a simple occupied state.
Likewise, the current setup area requires manual number entry, which isn’t intuitive enough, and would definitely be nice to have in some sort of drawing-like interface. We’re currently told that the folks at hilink are also envisioning a zoning feature from their app, presumably like the LD2410, which seems like a nice addition.
To give you a better experience of this groundbreaking cost-effective body tracking radar module, we’ve prepared more Sensor 2A to share with you, and in the meantime, we’re offering a 10% discount on all SCREEK sensors for the next 24 hours.
7 Likes
I’m looking forward to trying this out!
2 Likes
rongten
(Raimondo Giammanco)
September 24, 2023, 12:22pm
3
I have purchased 2, I have installed one in the kitchen to turn on the kitchen main light (zone 1), the sink light (zone 2), and the fires light (zone 3). Planning the second for the far side of the living room.
Seems to work reasonably well, need to optimize the timings and maybe put the sensor elsewhere (European kitchen, no central island big enough to dissect a dolphin) and need to light the main light better according to existing light level.
What is interesting is that the kitchen is open, and I could use a fourth zone to control the light in the living room just outside the kitchen area.
Maybe a template sensor to use the targets distance instead would be the solution, to check.
Thanks to this sensor I am finally starting to explore the real meaning of smart, autonomous home. Having HA control lights via tablet and buttons is fine but not really the idea of smart home and energy saving (i.e more comfort and sell wasted energy when the kids forget the lights on…).
2 Likes
hellagame
(Hellagame)
September 25, 2023, 2:40pm
4
After having countless issues with Aqara motion sensors in Smartthings I made the switch to Home assistant with a used thin client. I went on to purchase (5) esp32-c3s and (5) LD2450s thinking they were already supported by ESPHome. I have tried loading the 2A firmware onto my esp32-c3s since I saw images of the c3 being used in what I guess were earlier models of the 2A via ESPHome. However, I am not able to get the config to install on the c3s. Is there a barebones version of the config available for just the mmwave sensor without the light sensor? Or perhaps can someone point out what lines to remove to accomplish this? Is it possible to simply add the config to a esp32-c3 that is already connected to Home Assistant and local wifi without needing to install the screek firmware and connect to the AP created by the esp32? If this is not the correct place to ask could someone point me in the right direction? Any assistance is greatly appreciated.
Which pins on the ESP are you using for TX/RX?
hellagame
(Hellagame)
September 25, 2023, 3:16pm
6
I am at work away from the device but if I recall correctly it is RX GPIO05(I2C_SCL) and TX GPIO04(I2C_SDA).
hellagame
(Hellagame)
September 25, 2023, 3:29pm
8
Looks like they forgot to update the board in the YAML posted in the Github. It’s set to the the c3 mini.
I’m guessing you’d need to update the board:
esp32-c3-devkitm-1
hellagame
(Hellagame)
September 25, 2023, 3:51pm
10
I previously noticed that and updated the yaml with esp32-c3-devkitm-1 but the install failed. However, in hindsight I tried to install wirelessly instead of directly connected to thin client running HA and also may have tinkered with other settings as well. So, when I get home I will grab the yaml from the github again and only change the board to be sure.
This config is working for me:
substitutions:
# Set the device name
name: 2a-test
# Set the friendly name
friendly_name: 2A Sensor Test
# Provide the wifi SSID
wifi: !secret wifi_ssid
#Provide the wifi password
wifi_pass: !secret wifi_password
#Provide an OTA password:
ota_pass: "trustbutverifywalkingwithabigstick"
esp32:
board: esp32-c3-devkitm-1
framework:
type: arduino
# This is a custom firmware for Human Presence Sensor 2A
# https://docs.screek.io/2a
esphome:
name: $name
friendly_name: $friendly_name
name_add_mac_suffix: false
on_boot:
- priority: 100
then:
lambda: |-
id(cpu_speed) = ESP.getCpuFreqMHz();
- priority: -200
then:
lambda: |-
id(zone1_target_exsits).publish_state(false);
id(zone2_target_exsits).publish_state(false);
id(zone3_target_exsits).publish_state(false);
id(zone_ex1_target_exsits).publish_state(false);
platformio_options:
board_build.flash_mode: dio
preferences:
flash_write_interval: 5s
external_components:
- source:
type: git
url: https://github.com/screekworkshop/custom_components_support_for_screek_2a
ref: main
components: [esp32, uart]
globals:
- id: cpu_speed
type: int
restore_value: no
initial_value: '0'
- id: last_update_ld2450
type: unsigned long
restore_value: no
initial_value: '0'
- id: init_zone_publish
type: bool
restore_value: no
initial_value: "false"
- id: last_illuminance
type: float
restore_value: no
initial_value: "-1"
improv_serial:
logger:
debug:
update_interval: 30s
api:
ota:
password: $ota_pass
wifi:
ssid: $wifi
password: $wifi_pass
power_save_mode: LIGHT
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
captive_portal:
web_server:
port: 80
text_sensor:
- platform: debug
reset_reason:
name: "ESP Reset Reason"
icon: mdi:anchor
disabled_by_default: True
- platform: wifi_info
ip_address:
name: ESP IP Address
entity_category: "diagnostic"
disabled_by_default: True
icon: mdi:ip-network
mac_address:
name: ESP MAC
entity_category: "diagnostic"
icon: mdi:ip-network
disabled_by_default: True
- platform: template
name: "Zone1 Info"
id: tips_zone1_conf
icon: mdi:information-outline
entity_category: config
lambda: |-
return {"Configure below" };
update_interval: 1000s
- platform: template
name: "Zone2 Info"
id: tips_zone2_conf
icon: mdi:information-outline
entity_category: config
lambda: |-
return {"Configure below" };
update_interval: 1000s
- platform: template
name: "Zone3 Info"
id: tips_zone3_conf
icon: mdi:information-outline
entity_category: config
lambda: |-
return {"Configure below" };
update_interval: 1000s
- platform: template
name: "Zout1 Info"
id: tips_zone_ex1_conf
icon: mdi:information-outline
entity_category: config
lambda: |-
return {"Zone Exclusion 1" };
update_interval: 1000s
number:
- platform: template
name: "Any Presence Timeout"
id: any_presence_timeout
min_value: 0
max_value: 600
mode: box
device_class: duration
entity_category: config
unit_of_measurement: s
icon: mdi:timer-off
step: 1
optimistic: True
initial_value: 0
restore_value: True
- platform: template
name: "Zone1 Timeout"
id: zone1_x_timeout
min_value: 0
max_value: 600
mode: box
device_class: duration
entity_category: config
unit_of_measurement: s
icon: mdi:timer-off
step: 1
optimistic: True
initial_value: 0
restore_value: True
- platform: template
name: "Zone2 Timeout"
id: zone2_x_timeout
min_value: 0
max_value: 600
mode: box
device_class: duration
entity_category: config
unit_of_measurement: s
icon: mdi:timer-off
step: 1
optimistic: True
initial_value: 0
restore_value: True
- platform: template
name: "Zone3 Timeout"
id: zone3_x_timeout
min_value: 0
max_value: 600
mode: box
device_class: duration
entity_category: config
unit_of_measurement: s
icon: mdi:timer-off
step: 1
optimistic: True
initial_value: 0
restore_value: True
# Zone 1
- platform: template
name: Zone1 X-Begin
id: zone1_x_begin
min_value: -4000
max_value: 4000
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
initial_value: 0
restore_value: True
on_value:
then:
- script.execute: check_zone1_vaild
- platform: template
name: Zone1 X-End
id: zone1_x_end
mode: box
min_value: -4000
max_value: 4000
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone1_vaild
- platform: template
name: Zone1 Y-Begin
id: zone1_y_begin
mode: box
min_value: 0
max_value: 6000
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone1_vaild
- platform: template
name: Zone1 Y-End
id: zone1_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
initial_value: 0
entity_category: config
device_class: distance
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone1_vaild
# Zone 2
- platform: template
name: Zone2 X-Begin
id: zone2_x_begin
min_value: -4000
max_value: 4000
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
initial_value: 0
restore_value: True
on_value:
then:
- script.execute: check_zone2_vaild
- platform: template
name: Zone2 X-End
id: zone2_x_end
mode: box
min_value: -4000
max_value: 4000
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone2_vaild
- platform: template
name: Zone2 Y-Begin
id: zone2_y_begin
mode: box
min_value: 0
max_value: 6000
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone2_vaild
- platform: template
name: Zone2 Y-End
id: zone2_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
initial_value: 0
entity_category: config
device_class: distance
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone2_vaild
# Zone 3
- platform: template
name: Zone3 X-Begin
id: zone3_x_begin
min_value: -4000
max_value: 4000
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
initial_value: 0
restore_value: True
on_value:
then:
- script.execute: check_zone3_vaild
- platform: template
name: Zone3 X-End
id: zone3_x_end
mode: box
min_value: -4000
max_value: 4000
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone3_vaild
- platform: template
name: Zone3 Y-Begin
id: zone3_y_begin
mode: box
min_value: 0
max_value: 6000
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone3_vaild
- platform: template
name: Zone3 Y-End
id: zone3_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
initial_value: 0
entity_category: config
device_class: distance
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zone3_vaild
# Zout1
- platform: template
name: Zout1 X-Begin
id: zone_ex1_x_begin
min_value: -4000
max_value: 4000
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
initial_value: 0
restore_value: True
on_value:
then:
- script.execute: check_zout1_vaild
- platform: template
name: Zout1 X-End
id: zone_ex1_x_end
mode: box
min_value: -4000
max_value: 4000
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zout1_vaild
- platform: template
name: Zout1 Y-Begin
id: zone_ex1_y_begin
mode: box
min_value: 0
max_value: 6000
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
initial_value: 0
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zout1_vaild
- platform: template
name: Zout1 Y-End
id: zone_ex1_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
initial_value: 0
entity_category: config
device_class: distance
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
on_value:
then:
- script.execute: check_zout1_vaild
binary_sensor:
- platform: status
name: Online
id: ink_ha_connected
- platform: template
name: "Any Presence"
id: any_target_exsits
device_class: occupancy
filters:
- delayed_off: !lambda |-
return id(any_presence_timeout).state * 1000.0;
- platform: template
name: "Zone1 Presence"
id: zone1_target_exsits
device_class: occupancy
filters:
- delayed_off: !lambda |-
return id(zone1_x_timeout).state * 1000.0;
- platform: template
name: "Zone2 Presence"
id: zone2_target_exsits
device_class: occupancy
filters:
- delayed_off: !lambda |-
return id(zone2_x_timeout).state * 1000.0;
- platform: template
name: "Zone3 Presence"
id: zone3_target_exsits
device_class: occupancy
filters:
- delayed_off: !lambda |-
return id(zone3_x_timeout).state * 1000.0;
- platform: template
name: "Zout1 Presence"
id: zone_ex1_target_exsits
icon: mdi:account-multiple-remove
device_class: occupancy
i2c:
sda: GPIO7
scl: GPIO11
scan: true
id: bus_a
script:
- id: check_zone1_vaild
then:
- lambda: |-
if (id(zone1_x_begin).state > id(zone1_x_end).state){
id(tips_zone1_conf).publish_state("Err: X-Begin > X-End");
return;
}
if (id(zone1_y_begin).state > id(zone1_y_end).state){
id(tips_zone1_conf).publish_state("Err: Y-Begin > Y-End");
return;
}
if (id(zone1_x_begin).state == 0, id(zone1_x_end).state == 0, id(zone1_y_begin).state == 0, id(zone1_y_end).state == 0){
id(tips_zone1_conf).publish_state("Configure below");
return;
}
int x_size = id(zone1_x_end).state - id(zone1_x_begin).state;
int y_size = id(zone1_y_end).state - id(zone1_y_begin).state;
char combined[80];
sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
id(tips_zone1_conf).publish_state(combined);
- id: check_zone2_vaild
then:
- lambda: |-
if (id(zone2_x_begin).state > id(zone2_x_end).state){
id(tips_zone2_conf).publish_state("Err: X-Begin > X-End");
return;
}
if (id(zone2_y_begin).state > id(zone2_y_end).state){
id(tips_zone2_conf).publish_state("Err: Y-Begin > Y-End");
return;
}
if (id(zone2_x_begin).state == 0, id(zone2_x_end).state == 0, id(zone2_y_begin).state == 0, id(zone2_y_end).state == 0){
id(tips_zone2_conf).publish_state("Configure below");
return;
}
int x_size = id(zone2_x_end).state - id(zone2_x_begin).state;
int y_size = id(zone2_y_end).state - id(zone2_y_begin).state;
char combined[80];
sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
id(tips_zone2_conf).publish_state(combined);
- id: check_zone3_vaild
then:
- lambda: |-
if (id(zone3_x_begin).state > id(zone3_x_end).state){
id(tips_zone3_conf).publish_state("Err: X-Begin > X-End");
return;
}
if (id(zone3_y_begin).state > id(zone3_y_end).state){
id(tips_zone3_conf).publish_state("Err: Y-Begin > Y-End");
return;
}
if (id(zone3_x_begin).state == 0, id(zone3_x_end).state == 0, id(zone3_y_begin).state == 0, id(zone3_y_end).state == 0){
id(tips_zone3_conf).publish_state("Configure below");
return;
}
int x_size = id(zone3_x_end).state - id(zone3_x_begin).state;
int y_size = id(zone3_y_end).state - id(zone3_y_begin).state;
char combined[80];
sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
id(tips_zone3_conf).publish_state(combined);
- id: check_zout1_vaild
then:
- lambda: |-
if (id(zone_ex1_x_begin).state > id(zone_ex1_x_end).state){
id(tips_zone_ex1_conf).publish_state("Err: X-Begin > X-End");
return;
}
if (id(zone_ex1_y_begin).state > id(zone_ex1_y_end).state){
id(tips_zone_ex1_conf).publish_state("Err: Y-Begin > Y-End");
return;
}
id(tips_zone_ex1_conf).publish_state("Zone Exclusion 1");
sensor:
- platform: template
name: "ESP CPU Speed"
accuracy_decimals: 0
icon: mdi:cpu-32-bit
unit_of_measurement: Mhz
disabled_by_default: True
lambda: |-
return (id(cpu_speed));
entity_category: "diagnostic"
update_interval: 600s
- platform: template
id: sys_esp_temperature
name: ESP Temperature
lambda: return temperatureRead();
unit_of_measurement: °C
device_class: TEMPERATURE
update_interval: 45s
entity_category: "diagnostic"
- platform: uptime
name: ESP Uptime
id: sys_uptime
update_interval: 60s
- platform: wifi_signal
name: RSSI
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: template
id: esp_memory
icon: mdi:memory
name: ESP Free Memory
lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;
unit_of_measurement: 'kB'
state_class: measurement
entity_category: "diagnostic"
update_interval: 60s
- platform: bh1750
name: "Illuminance"
accuracy_decimals: 1
id: bh1750_light
update_interval: 1s
filters:
- lambda: !lambda |-
if (id(last_illuminance) == x){
return {};
}
if (id(bh1750_fast_update).state){
id(last_illuminance) = x;
// ESP_LOGD("custom", "Fast Update BH1850");
return x;
}
if (abs(id(last_illuminance) - x) > 1){
id(last_illuminance) = x;
return x;
}
return {};
#-------------------------------------#
# 高级雷达数据
- platform: template
name: "All Target Counts"
id: all_target_count
accuracy_decimals: 0
icon: "mdi:counter"
unit_of_measurement: "targets"
- platform: template
name: "Zone1 Target Counts"
id: zone1_target_count
accuracy_decimals: 0
icon: "mdi:counter"
unit_of_measurement: "targets"
- platform: template
name: "Zone2 Target Counts"
id: zone2_target_count
accuracy_decimals: 0
icon: "mdi:counter"
unit_of_measurement: "targets"
- platform: template
name: "Zone3 Target Counts"
id: zone3_target_count
accuracy_decimals: 0
icon: "mdi:counter"
unit_of_measurement: "targets"
- platform: template
name: "Zout1 Target Counts"
id: zone_ex1_target_count
accuracy_decimals: 0
icon: mdi:account-multiple-minus-outline
unit_of_measurement: "targets"
# Target 1
- platform: template
name: "Target1 X"
id: target1_x
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target1 Y"
id: target1_y
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target1 Speed"
id: target1_speed
accuracy_decimals: 2
unit_of_measurement: 'm/s'
state_class: measurement
device_class: speed
- platform: template
name: "Target1 Resolution"
id: target1_resolution
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
# Target 2
- platform: template
name: "Target2 X"
id: target2_x
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target2 Y"
id: target2_y
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target2 Speed"
id: target2_speed
accuracy_decimals: 0
unit_of_measurement: 'm/s'
state_class: measurement
device_class: speed
- platform: template
name: "Target2 Resolution"
id: target2_resolution
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
# Target 3
- platform: template
name: "Target3 X"
id: target3_x
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target3 Y"
id: target3_y
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target3 Speed"
id: target3_speed
accuracy_decimals: 0
unit_of_measurement: 'm/s'
state_class: measurement
device_class: speed
- platform: template
name: "Target3 Resolution"
id: target3_resolution
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
light:
- platform: status_led
name: sys_status
pin: GPIO13
internal: True
restore_mode: ALWAYS_OFF
- platform: binary
name: "Red Info Light"
output: board_info_ed
entity_category: "config"
restore_mode: ALWAYS_OFF
time:
- platform: sntp
id: time_now
output:
- platform: gpio
id: board_info_ed
pin: GPIO12
switch:
- platform: factory_reset
name: Factory Reset
disabled_by_default: True
icon: mdi:heart-broken
- platform: template
name: Zout1 Enable
id: zone_ex1_enable
optimistic: True
icon: mdi:account-cancel
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
- platform: template
name: Illuminance Fast-Update
id: bh1750_fast_update
optimistic: True
entity_category: diagnostic
restore_mode: RESTORE_DEFAULT_OFF
icon: mdi:run-fast
button:
- platform: restart
icon: mdi:power-cycle
name: "ESP Reboot"
entity_category: diagnostic
uart:
id: uart_bus
tx_pin:
number: GPIO5
mode:
input: true
pullup: true
rx_pin:
number: GPIO4
mode:
input: true
pullup: true
baud_rate: 256000
parity: NONE
stop_bits: 1
data_bits: 8
debug:
direction: BOTH
dummy_receiver: True
after:
delimiter: [0X55, 0XCC]
sequence:
- lambda: |-
if ((millis() - id(last_update_ld2450)) <= 500) {
return;
};
id(last_update_ld2450) = millis();
// p1
int16_t p1_x = (uint16_t((bytes[5] << 8) | bytes[4] ));
if ((bytes[5] & 0x80) >> 7){
p1_x -= pow(2, 15);
}else{
p1_x = 0 - p1_x;
}
int16_t p1_y = (uint16_t((bytes[7] << 8) | bytes[6] ));
if ((bytes[7] & 0x80) >> 7){
p1_y -= pow(2, 15);
}else{
p1_y = 0 - p1_y;
}
int p1_speed = (bytes[9] << 8 | bytes[8] );
if ((bytes[9] & 0x80) >> 7){
p1_speed -= pow(2, 15);
}else{
p1_speed = 0 - p1_speed;
}
int16_t p1_distance_resolution = (uint16_t((bytes[11] << 8) | bytes[10] ));
// p2
int16_t p2_x = (uint16_t((bytes[13] << 8) | bytes[12] ));
if ((bytes[13] & 0x80) >> 7){
p2_x -= pow(2, 15);
}else{
p2_x = 0 - p2_x;
}
int16_t p2_y = (uint16_t((bytes[15] << 8) | bytes[14] ));
if ((bytes[15] & 0x80) >> 7){
p2_y -= pow(2, 15);
}else{
p2_y = 0 - p2_y;
}
int p2_speed = (bytes[17] << 8 | bytes[16] );
if ((bytes[17] & 0x80) >> 7){
p2_speed -= pow(2, 15);
}else{
p2_speed = 0 - p2_speed;
}
int16_t p2_distance_resolution = (uint16_t((bytes[19] << 8) | bytes[18] ));
// p3
int16_t p3_x = (uint16_t((bytes[21] << 8) | bytes[20] ));
if ((bytes[21] & 0x80) >> 7){
p3_x -= pow(2, 15);
}else{
p3_x = 0 - p3_x;
}
int16_t p3_y = (uint16_t((bytes[23] << 8) | bytes[22] ));
if ((bytes[23] & 0x80) >> 7){
p3_y -= pow(2, 15);
}else{
p3_y = 0 - p3_y;
}
int p3_speed = (bytes[25] << 8 | bytes[24] );
if ((bytes[25] & 0x80) >> 7){
p3_speed -= pow(2, 15);
}else{
p3_speed = 0 - p3_speed;
}
int16_t p3_distance_resolution = (uint16_t((bytes[27] << 8) | bytes[26] ));
bool p1_vaild = (p1_x != 0 || p1_y > 0);
bool p2_vaild = (p2_x != 0 || p2_y > 0);
bool p3_vaild = (p3_x != 0 || p3_y > 0);
// zone exlude 1
int16_t target_count_in_zone_ex1 = 0;
int16_t zone_ex1_x_min = id(zone_ex1_x_begin).state;
int16_t zone_ex1_x_max = id(zone_ex1_x_end).state;
int16_t zone_ex1_y_min = id(zone_ex1_y_begin).state;
int16_t zone_ex1_y_max = id(zone_ex1_y_end).state;
bool p1_zone_ex_enter = false;
bool p2_zone_ex_enter = false;
bool p3_zone_ex_enter = false;
if (id(zone_ex1_enable).state){
if (p1_vaild){
if (p1_x >= zone_ex1_x_min && p1_x <= zone_ex1_x_max && p1_y >= zone_ex1_y_min && p1_y <= zone_ex1_y_max){
p1_zone_ex_enter = true;
target_count_in_zone_ex1 ++;
}
}
if (p2_vaild){
if (p2_x >= zone_ex1_x_min && p2_x <= zone_ex1_x_max && p2_y >= zone_ex1_y_min && p2_y <= zone_ex1_y_max){
p2_zone_ex_enter = true;
target_count_in_zone_ex1 ++;
}
}
if (p3_vaild){
if (p3_x >= zone_ex1_x_min && p3_x <= zone_ex1_x_max && p3_y >= zone_ex1_y_min && p3_y <= zone_ex1_y_max){
p3_zone_ex_enter = true;
target_count_in_zone_ex1 ++;
}
}
}
bool has_target_in_zone_ex1 = (target_count_in_zone_ex1 > 0);
int16_t all_target_counts = 0;
if (p1_vaild && !p1_zone_ex_enter){
all_target_counts ++;
}
if (p2_vaild && !p2_zone_ex_enter){
all_target_counts ++;
}
if (p3_vaild && !p3_zone_ex_enter){
all_target_counts ++;
}
bool has_target_in_zone_all = (all_target_counts > 0);
// zone 1 check
int16_t target_count_in_zone1 = 0;
int16_t zone1_x_min = id(zone1_x_begin).state;
int16_t zone1_x_max = id(zone1_x_end).state;
int16_t zone1_y_min = id(zone1_y_begin).state;
int16_t zone1_y_max = id(zone1_y_end).state;
if (p1_vaild && !p1_zone_ex_enter){
if (p1_x >= zone1_x_min && p1_x <= zone1_x_max && p1_y >= zone1_y_min && p1_y <= zone1_y_max){
target_count_in_zone1 ++;
}
}
if (p2_vaild && !p2_zone_ex_enter){
if (p2_x >= zone1_x_min && p2_x <= zone1_x_max && p2_y >= zone1_y_min && p2_y <= zone1_y_max){
target_count_in_zone1 ++;
}
}
if (p3_vaild && !p3_zone_ex_enter){
if (p3_x >= zone1_x_min && p3_x <= zone1_x_max && p3_y >= zone1_y_min && p3_y <= zone1_y_max){
target_count_in_zone1 ++;
}
}
bool has_target_in_zone1 = (target_count_in_zone1 > 0);
// zone 2 check
int16_t target_count_in_zone2 = 0;
int16_t zone2_x_min = id(zone2_x_begin).state;
int16_t zone2_x_max = id(zone2_x_end).state;
int16_t zone2_y_min = id(zone2_y_begin).state;
int16_t zone2_y_max = id(zone2_y_end).state;
if (p1_vaild && !p1_zone_ex_enter){
if (p1_x >= zone2_x_min && p1_x <= zone2_x_max && p1_y >= zone2_y_min && p1_y <= zone2_y_max){
target_count_in_zone2 ++;
}
}
if (p2_vaild && !p2_zone_ex_enter){
if (p2_x >= zone2_x_min && p2_x <= zone2_x_max && p2_y >= zone2_y_min && p2_y <= zone2_y_max){
target_count_in_zone2 ++;
}
}
if (p3_vaild && !p3_zone_ex_enter){
if (p3_x >= zone2_x_min && p3_x <= zone2_x_max && p3_y >= zone2_y_min && p3_y <= zone2_y_max){
target_count_in_zone2 ++;
}
}
bool has_target_in_zone2 = (target_count_in_zone2 > 0);
// zone 3 check
int16_t target_count_in_zone3 = 0;
int16_t zone3_x_min = id(zone3_x_begin).state;
int16_t zone3_x_max = id(zone3_x_end).state;
int16_t zone3_y_min = id(zone3_y_begin).state;
int16_t zone3_y_max = id(zone3_y_end).state;
if (p1_vaild && !p1_zone_ex_enter){
if (p1_x >= zone3_x_min && p1_x <= zone3_x_max && p1_y >= zone3_y_min && p1_y <= zone3_y_max){
target_count_in_zone3 ++;
}
}
if (p2_vaild && !p2_zone_ex_enter){
if (p2_x >= zone3_x_min && p2_x <= zone3_x_max && p2_y >= zone3_y_min && p2_y <= zone3_y_max){
target_count_in_zone3 ++;
}
}
if (p3_vaild && !p3_zone_ex_enter){
if (p3_x >= zone3_x_min && p3_x <= zone3_x_max && p3_y >= zone3_y_min && p3_y <= zone3_y_max){
target_count_in_zone3 ++;
}
}
bool has_target_in_zone3 = (target_count_in_zone3 > 0);
// public all info
if (id(target1_x).state != p1_x){
id(target1_x).publish_state(p1_x);
}
if (id(target1_y).state != p1_y){
id(target1_y).publish_state(p1_y);
}
float p1_m_speed = float(p1_speed) / 100.0;
if (id(target1_speed).state != p1_m_speed){
id(target1_speed).publish_state(p1_m_speed);
}
if (id(target1_resolution).state != p1_distance_resolution){
id(target1_resolution).publish_state(p1_distance_resolution);
}
if (id(target2_x).state != p2_x){
id(target2_x).publish_state(p2_x);
}
if (id(target2_y).state != p2_y){
id(target2_y).publish_state(p2_y);
}
if (id(target2_speed).state != p2_speed){
id(target2_speed).publish_state(p2_speed);
}
if (id(target2_resolution).state != p2_distance_resolution){
id(target2_resolution).publish_state(p2_distance_resolution);
}
if (id(target3_x).state != p3_x){
id(target3_x).publish_state(p3_x);
}
if (id(target3_y).state != p3_y){
id(target3_y).publish_state(p3_y);
}
if (id(target3_speed).state != p3_speed){
id(target3_speed).publish_state(p3_speed);
}
if (id(target3_resolution).state != p3_distance_resolution){
id(target3_resolution).publish_state(p3_distance_resolution);
}
// publish target info
if (id(all_target_count).state != all_target_counts){
id(all_target_count).publish_state(all_target_counts);
id(any_target_exsits).publish_state(has_target_in_zone_all);
}
if (id(zone1_target_count).state != target_count_in_zone1){
id(zone1_target_count).publish_state(target_count_in_zone1);
id(zone1_target_exsits).publish_state(has_target_in_zone1);
}
if (id(zone2_target_count).state != target_count_in_zone2){
id(zone2_target_count).publish_state(target_count_in_zone2);
id(zone2_target_exsits).publish_state(has_target_in_zone2);
}
if (id(zone3_target_count).state != target_count_in_zone3){
id(zone3_target_count).publish_state(target_count_in_zone3);
id(zone3_target_exsits).publish_state(has_target_in_zone3);
}
// zout
if (id(zone_ex1_target_count).state != target_count_in_zone_ex1){
id(zone_ex1_target_count).publish_state(target_count_in_zone_ex1);
id(zone_ex1_target_exsits).publish_state(has_target_in_zone_ex1);
}
if (!id(init_zone_publish)){
id(init_zone_publish) = true;
}
hellagame
(Hellagame)
September 26, 2023, 11:08am
12
The config you provided installs but in logs I am seeing NO OTA attempt made, restarting. Eventually it show, “There have been 10 suspected unsuccessful boot attempts.” “Boot loop detected. Proceeding to safe mode.” The esp32-c3 connects to my wifi and shows connected in ESPHome addon. However, there is no notification for new device detected and in Integration it doesn’t show up under Discovered. Should I be installing factory-human-sensor-2a-V230908_1_stable.bin or maybe the OTA firmware?
I’m not sure then. I just tested again using the YAML I posted above.
Created device in ESPhome.
Edited config and did a direct paste of the YAML above.
Selected install, manual, modern format.
Use ESPHome Web to flash.
The board reset, connected to wifi, and showed up in device discovery. Added it and can see all the sensor data.
1 Like
Telk0
(Telk0)
December 2, 2023, 8:34am
15
Any got a neat diy 3d print case file for this?
anhnvme
(anhnv)
December 3, 2023, 6:22am
16
i don’t understand why i’m on zone 3. but zone 3 not show detect
stevemann
(Stephen Mann (YAML-challenged))
December 3, 2023, 6:33am
17
Zones? From one sensor? Where is this documented?
Haldi
(Haldi)
December 3, 2023, 8:52am
18
here:
and here:
After a very long testing period, and also with the feedback and support from the first users, we had the opportunity to refine it to a much better height, and this is the current 2A, where we support 3 zone settings on the firmware, as well as an...
Zone Support : Based on the current firmware, three recognized zones (Zone1, Zone2, Zone3) are supported, as well as one excluded zone (Zout1), which can be switched on and off individually. Enabling the exclusion zone will disregard excluded targets in all recognition judgments.
Target Coordinate detection : Compared to LD2410, now you can support X coordinate reading! And Y coordinates are more accurate! They are accurate up to 36cm.
One reason why the LD2450 with this Firmware is such an Awesome sensor!
Especially now with Multiple Target support.
1 Like
Hi, we haven’t received any such bug feedback yet, so our initial guess is that there may be some setup hurdles.
If possible, please provide a recording or screenshot that shows all the relevant settings and we can make an initial attempt to understand what’s happening.
A general and unexpected understanding might be that x-begin and x-end are reversed, i.e. in the case of a negative number, it might be that the former has a bigger number.
For example, think - 200 > -100, which would cause the judgment logic to fail.
1 Like
This is a feature of the ld2450, a new sensor that was discussed more extensively in our other thread and is now supported by more open source libraries.
It is a ld2410 similar to the 24g radar sensor but with support for area characterization.