I think i’ve got zout working now after some trial and error.
With zout enabled, it doesn’t detect the fan however presence would consistently shift between available or not available the more static your position is. I added 30- 45 seconds delay before switching any device off when presence is not detected. If i fall asleep it would probably just stop detecting
I think this has something to do with sensor that prioritise the more active target (fan) when the other target is static/not moving. Hopefully this gets fixed on the next hlk sensor update.
athua
(Gus)
August 31, 2023, 2:27am
114
That is the same thing I am experiencing which makes this sensor problematic for use with multiple zones with the current HiLink firmware. I have setup 3 zones and if there is a person in Zone 1 and another person in Zone 2, the sensor will lose track of the one moving less and so will clear the presence of one of the Zones and if that is setup for the lights, then the lights will turn off.
Hopefully the next firmware release from HiLink will enable the proper 3 target tracking that has been promoted about the LD2450 sensor.
1 Like
athua
(Gus)
August 31, 2023, 5:07am
115
I noticed that the LD2450 clears the Zone Presence immediately when it doesn’t detect a target. When there is little movement, it seems to clear the presence and then detect it again in a few seconds. Adding a configurable delay to when the presence is cleared could resolve this issue.
The following code should allow the timeout for each zone to be configured and set:
number:
- 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
binary_sensor:
- 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;
1 Like
It’s a cool feature, Gus, and we’ll try to incorporate it into the firmware.
1 Like
I was doing this just now, but your solution is way better than mine.
2 Likes
I’m not a developer, but here’s my setup based on the work of screek-workshop and Gus.
I added direction, position, angle (not very accurate but can be useful in some cases) and a general threshold for presence.
esphome:
name: ld2450b
friendly_name: ld2450b
platformio_options:
board_build.flash_mode: dio
on_boot:
- priority: 2000
then:
lambda: |-
id(any_target_exsits).publish_state(false);
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);
external_components:
- source:
type: git
url: https://github.com/screekworkshop/custom_components_support_for_screek_2a
ref: main
components: [esp32, uart]
globals:
- 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"
improv_serial:
debug:
update_interval: 30s
text_sensor:
- 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
- platform: template
name: "Target1 Direction"
id: target1_direction
icon: mdi:arrow-up-down
- platform: template
name: "Target2 Direction"
id: target2_direction
icon: mdi:arrow-up-down
- platform: template
name: "Target3 Direction"
id: target3_direction
icon: mdi:arrow-up-down
- platform: template
name: "Target1 Position"
id: target1_position
icon: mdi:arrow-left-right
- platform: template
name: "Target2 Position"
id: target2_position
icon: mdi:arrow-left-right
- platform: template
name: "Target3 Position"
id: target3_position
icon: mdi:arrow-left-right
number:
- platform: template
name: Area X-Begin
id: area_x_begin
min_value: -4000
max_value: 4000
initial_value: -4000
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Area X-End
id: area_x_end
mode: box
min_value: -4000
max_value: 4000
initial_value: 4000
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Area Y-Begin
id: area_y_begin
mode: box
min_value: 0
max_value: 6000
initial_value: 0
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- platform: template
name: Area Y-End
id: area_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
initial_value: 6000
entity_category: config
device_class: distance
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- platform: template
name: Area Angle-Begin
id: area_angle_begin
icon: mdi:angle-acute
mode: box
min_value: -130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
max_value: 130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
initial_value: -130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
entity_category: config
# device_class: distance
unit_of_measurement: 'º'
step: 1
optimistic: True
restore_value: True
- platform: template
name: Area Angle-End
id: area_angle_end
icon: mdi:angle-acute
# mode: box
min_value: -130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
max_value: 130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
initial_value: 130 # In the readings, I obtained values of approximately 120º when passing behind the sensor
entity_category: config
# device_class: distance
unit_of_measurement: 'º'
step: 1
optimistic: True
restore_value: True
- platform: template
name: Zone1 X-Begin
id: zone1_x_begin
min_value: -4000
max_value: 4000
initial_value: 0
# mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone1 X-End
id: zone1_x_end
mode: box
min_value: -4000
max_value: 4000
initial_value: 0
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone1 Y-Begin
id: zone1_y_begin
mode: box
min_value: 0
max_value: 6000
initial_value: 0
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- 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
- platform: template
name: Zone2 X-Begin
id: zone2_x_begin
min_value: -4000
max_value: 4000
initial_value: 0
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone2 X-End
id: zone2_x_end
mode: box
min_value: -4000
max_value: 4000
initial_value: 0
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone2 Y-Begin
id: zone2_y_begin
mode: box
min_value: 0
max_value: 6000
initial_value: 0
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- 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
- platform: template
name: Zone3 X-Begin
id: zone3_x_begin
min_value: -4000
max_value: 4000
initial_value: 0
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone3 X-End
id: zone3_x_end
mode: box
min_value: -4000
max_value: 4000
initial_value: 0
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zone3 Y-Begin
id: zone3_y_begin
mode: box
min_value: 0
max_value: 6000
initial_value: 0
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- 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
- platform: template
name: Zout1 X-Begin
id: zone_ex1_x_begin
min_value: -4000
max_value: 4000
initial_value: 0
mode: box
device_class: distance
entity_category: config
unit_of_measurement: mm
icon: mdi:arrow-left-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zout1 X-End
id: zone_ex1_x_end
mode: box
min_value: -4000
max_value: 4000
initial_value: 0
device_class: distance
unit_of_measurement: mm
entity_category: config
icon: mdi:arrow-right-bold
step: 10
optimistic: True
restore_value: True
- platform: template
name: Zout1 Y-Begin
id: zone_ex1_y_begin
mode: box
min_value: 0
max_value: 6000
initial_value: 0
device_class: distance
entity_category: config
icon: mdi:arrow-up-bold
unit_of_measurement: mm
step: 10
optimistic: True
restore_value: True
- 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
- platform: template
name: "Zone Any Timeout"
id: zoneany_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: "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
binary_sensor:
- platform: template
name: "Any Presence"
id: any_target_exsits
device_class: occupancy
filters:
- delayed_off: !lambda |-
return id(zoneany_x_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
sensor:
- 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"
- 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"
icon: mdi:arrow-up-down
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
- platform: template
name: "Target2 X"
id: target2_x
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
# update_interval: 1s
- platform: template
name: "Target2 Y"
icon: mdi:arrow-up-down
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
- 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"
icon: mdi:arrow-up-down
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
# update_interval: 1s
- platform: template
name: "Target3 Resolution"
id: target3_resolution
accuracy_decimals: 0
unit_of_measurement: 'mm'
state_class: measurement
device_class: distance
- platform: template
name: "Target1 Angle"
id: target1_angle
unit_of_measurement: 'º'
icon: mdi:angle-acute
- platform: template
name: "Target2 Angle"
id: target2_angle
unit_of_measurement: 'º'
icon: mdi:angle-acute
- platform: template
name: "Target3 Angle"
id: target3_angle
unit_of_measurement: 'º'
icon: mdi:angle-acute
output:
- platform: ledc
pin: GPIO2
id: led
switch:
- platform: template
name: Zout1 Enable
id: zone_ex1_enable
optimistic: True
icon: mdi:account-cancel
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
button:
- platform: restart
icon: mdi:power-cycle
name: "ESP Reboot"
entity_category: diagnostic
- platform: factory_reset
name: Factory Reset
disabled_by_default: false
icon: mdi:heart-broken
uart:
id: uart_bus
tx_pin:
number: GPIO25
mode:
input: true
pullup: true
rx_pin:
number: GPIO32
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();
// Calc X, Y, Speed and Resolution //
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] ));
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] ));
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] ));
// Calc X, Y, Speed and Resolution //
float p1_a = (p1_x);
float p1_b = (p1_y);
float p1_c = ((p1_a / p1_b) * 180 / 3.14159265359);
if (p1_x == 0) {
id(target1_angle).publish_state(0);
} else {
id(target1_angle).publish_state(p1_c);
}
float p2_a = (p2_x);
float p2_b = (p2_y);
float p2_c = ((p2_a / p2_b) * 180 / 3.14159265359);
if (p2_x == 0) {
id(target2_angle).publish_state(0);
} else {
id(target2_angle).publish_state(p2_c);
}
float p3_a = (p3_x);
float p3_b = (p3_y);
float p3_c = ((p3_a / p3_b) * 180 / 3.14159265359);
if (p3_x == 0) {
id(target3_angle).publish_state(0);
} else {
id(target3_angle).publish_state(p3_c);
}
int16_t area_x_min = id(area_x_begin).state; // - x_tolerance;
int16_t area_x_max = id(area_x_end).state; // + x_tolerance;
int16_t area_y_min = id(area_y_begin).state; // - y_tolerance;
int16_t area_y_max = id(area_y_end).state; // + y_tolerance;
int16_t area_angle_min = id(area_angle_begin).state; // + y_tolerance;
int16_t area_angle_max = id(area_angle_end).state; // + y_tolerance;
bool p1_valid = ((p1_x != 0 || p1_y > 0) && p1_x >= area_x_min && p1_x <= area_x_max && p1_y >= area_y_min && p1_y <= area_y_max && p1_c >= area_angle_min && p1_c <= area_angle_max);
bool p2_valid = ((p2_x != 0 || p2_y > 0) && p2_x >= area_x_min && p2_x <= area_x_max && p2_y >= area_y_min && p2_y <= area_y_max && p2_c >= area_angle_min && p2_c <= area_angle_max);
bool p3_valid = ((p3_x != 0 || p3_y > 0) && p3_x >= area_x_min && p3_x <= area_x_max && p3_y >= area_y_min && p3_y <= area_y_max && p3_c >= area_angle_min && p3_c <= area_angle_max);
int16_t target_count_in_zone_ex1 = 0;
int16_t zone_ex1_x_min = id(zone_ex1_x_begin).state; // - x_ex_tolerance;
int16_t zone_ex1_x_max = id(zone_ex1_x_end).state; // + x_ex_tolerance;
int16_t zone_ex1_y_min = id(zone_ex1_y_begin).state; // - y_ex_tolerance;
int16_t zone_ex1_y_max = id(zone_ex1_y_end).state; // + y_ex_tolerance;
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_valid) {
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_valid) {
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_valid) {
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_valid && !p1_zone_ex_enter) {
all_target_counts ++;
}
if (p2_valid && !p2_zone_ex_enter) {
all_target_counts ++;
}
if (p3_valid && !p3_zone_ex_enter) {
all_target_counts ++;
}
bool has_target_in_zone_all = (all_target_counts > 0);
int16_t target_count_in_zone1 = 0;
int16_t zone1_x_min = id(zone1_x_begin).state; // - x_tolerance;
int16_t zone1_x_max = id(zone1_x_end).state; // + x_tolerance;
int16_t zone1_y_min = id(zone1_y_begin).state; // - y_tolerance;
int16_t zone1_y_max = id(zone1_y_end).state; // + y_tolerance;
if (p1_valid && !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_valid && !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_valid && !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);
int16_t target_count_in_zone2 = 0;
int16_t zone2_x_min = id(zone2_x_begin).state; // - x_tolerance;
int16_t zone2_x_max = id(zone2_x_end).state; // + x_tolerance;
int16_t zone2_y_min = id(zone2_y_begin).state; // - y_tolerance;
int16_t zone2_y_max = id(zone2_y_end).state; // + y_tolerance;
if (p1_valid && !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_valid && !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_valid && !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);
int16_t target_count_in_zone3 = 0;
int16_t zone3_x_min = id(zone3_x_begin).state; // - x_tolerance;
int16_t zone3_x_max = id(zone3_x_end).state; // + x_tolerance;
int16_t zone3_y_min = id(zone3_y_begin).state; // - y_tolerance;
int16_t zone3_y_max = id(zone3_y_end).state; // + y_tolerance;
if (p1_valid && !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_valid && !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_valid && !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);
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);
}
if (id(all_target_count).state != all_target_counts) {
id(all_target_count).publish_state(all_target_counts);
}
if (id(any_target_exsits).state != has_target_in_zone_all) {
id(any_target_exsits).publish_state(has_target_in_zone_all);
}
if (id(all_target_count).state != all_target_counts) {
id(all_target_count).publish_state(all_target_counts);
}
if (id(any_target_exsits).state != has_target_in_zone_all) {
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);
}
if (id(zone1_target_exsits).state != has_target_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);
}
if (id(zone2_target_exsits).state != has_target_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);
}
if (id(zone3_target_exsits).state != has_target_in_zone3) {
id(zone3_target_exsits).publish_state(has_target_in_zone3);
}
if (id(zone_ex1_target_count).state != target_count_in_zone_ex1) {
id(zone_ex1_target_count).publish_state(target_count_in_zone_ex1);
}
if (id(zone_ex1_target_exsits).state != has_target_in_zone_ex1) {
id(zone_ex1_target_exsits).publish_state(has_target_in_zone_ex1);
}
id(init_zone_publish) = true;
// Angle, Position and Direction //
if (p1_speed == 0) {
id(target1_direction).publish_state("Static");
} else if (p1_speed > 0) {
id(target1_direction).publish_state("Moving away");
} else if (p1_speed < 0) {
id(target1_direction).publish_state("Approaching");
}
if (p2_speed == 0) {
id(target2_direction).publish_state("Static");
} else if (p2_speed > 0) {
id(target2_direction).publish_state("Moving away");
} else if (p2_speed < 0) {
id(target2_direction).publish_state("Approaching");
}
if (p3_speed == 0) {
id(target3_direction).publish_state("Static");
} else if (p3_speed > 0) {
id(target3_direction).publish_state("Moving away");
} else if (p3_speed < 0) {
id(target3_direction).publish_state("Approaching");
}
if (p1_x == 0) {
id(target1_position).publish_state("Static");
} else if (p1_x > 0) {
id(target1_position).publish_state("Right");
} else if (p1_x < 0) {
id(target1_position).publish_state("Left");
}
if (p2_x == 0) {
id(target2_position).publish_state("Static");
} else if (p2_x > 0) {
id(target2_position).publish_state("Right");
} else if (p2_x < 0) {
id(target2_position).publish_state("Left");
}
if (p3_x == 0) {
id(target3_position).publish_state("Static");
} else if (p3_x > 0) {
id(target3_position).publish_state("Right");
} else if (p3_x < 0) {
id(target3_position).publish_state("Left");
}
if ((p1_valid) || (p2_valid) || (p3_valid)) {
id(led).set_level(0.0);
} else {
id(led).set_level(1.0);
}
// Angle, Position and Direction //
2 Likes
I just saw @screek-workshop post on static detection with different mmwave sensor on the facebook group.
Apparently LD2450 doesn’t have full static detection?
That would explain why i still have to move around a bit when i was testing in a room with no interference (no fans etc)
1 Like
Luke5500
(Luke Draper)
September 1, 2023, 3:20am
120
Hi there, I have looked all over and even asked Hi-Link with no luck. Could you tell me which connecter type you used here?
1 Like
It is a 1.5mm 4pin connector.
1 Like
When it comes to decimals, I think the conversion to float is necessary and good.
On the esp32-c3, the processing resources are powerful, and the power supply is stable, and the memory is plentiful, so I don’t think these small calculations are too much of a strain on it at all.
I think I can merge this cool code next.
Great job, and putting the angle calculations into it is a great idea!
Combined with these features from athua, this firmware becomes much more versatile.
But the final code for the angle aspect seems to be truncated, unfortunately.
thank you.
Yes, we have also changed the pronouncement of sharing diy products in ebay, this radar is only suitable as a moving or micro-motion target tracking radar, it has no static detection.
This is one of the more important facts that we have discovered together recently that explains a lot of situations.
The comments are wrong, but the code is there. I needed to move the code up because I ended up using it to validate that the target is within the boundary area.
Starts here:
float p1_a = (p1_x);
1 Like
Thanks, this is a great idea.
I also see the property of separating people into left and right based on the x-axis is handy.
I couldn’t do the math using int16, so I converted it to a float. Maybe it’s possible to improve the code.
1 Like
ferbulous
(Shaq)
September 1, 2023, 2:34pm
129
Does the LD1151H also has multi target and possible to add exclusion zones?
1 Like
Luke5500
(Luke Draper)
September 1, 2023, 3:33pm
130
Thank you for confirming. It looked like that would be the right one but there customer support told me it was not.
ferbulous:
LD1151H
The LD1151H is not a tracking radar, it’s just a longer range ld2410-like radar with what appear to be certain algorithmic improvements.
But I can’t get any useful information from the documentation, unfortunately, the specific internals of this radar all seem like secrets.
The 2450 has two sets of interfaces, the simplest of which is for the ZH1.5, and the other, more complex (lots of pins, some of which are obviously intended for customized functionality). are of a different specification.
Generally speaking, ZH1.5 is the best for DIY connections.
We can be relatively sure of this because we’ve used over 600 of them.
We have merged athua’s delayed off code to make this delayed shutdown feature easily available to everyone.
https://www.reddit.com/r/screekworkshop/comments/167tjxf/2a_beta_firmware_update_v230902_beta/
Next we would like to merge walberjunior’s angle and movement direction description code.
The code has also been updated to a beta version on github.
As a movement tracking radar the LD2450 offers new possibilities. It’s great that for once DIY is ahead of commercial products.
1 Like