mmWave Presence Detection - ESPHome style

https://github.com/crlogic/esphome-hs2xx3a-custom-component/blob/1ecc4a88fcea8bbd788c7543bfaf996013853ed2/docs/V1.3:HS2xx3A%20Datasheet%20CH.pdf

Works exactly the same as the other LD2410 variants, basically a different form factor (IMO a better one). Used the same code for both sensors, but have not tested side by side, since I ran out of ESP dev boards :slight_smile:
Dont know if it supports BT, as I can’t install the app on my phone.

1 Like

Yup! Got mine too

Sadly, there is no ReadConfig, see here:

Each get command “reads” that specific part of the config.

[edit] I think there may have been some confusion here between read literal and read the verb/action/intention.

You can, “read the config” using the provided get commands.

You cannot readConfig as that is not the literal command to type in order to do so.

It does support BT too, I just connected to my sensor



1 Like

I recently got a DFRobot mmWave and noticed it’s detecting me on the back of the sensor too (at a shorter distance) but this doesn’t seem to happen with my mmWave sensors from LeapmmWave (the original manufacturer)… do you guys have same experience or is my sensor defective?

hello! i have very specific question to ask , i was watching everything smart home (this video Building My Perfect Smart Home Presence Detection Sensor! - YouTube) and he used this code and stuff to get his mmwave sensor working and im trying to do the same but im confused, the pin-out of the board and the way he soldered it out shouldn’t work but his does, he put the sensor in i022, i021, i017, i016, and of course GND and VCC (5v) but on the df robot page it says you need the rx and tx to be plugged in, im wondering how i can do the same as him and get my sensor working, i hope someone can help because im at a loss, i wish he could have shown the install of the code :frowning:

The ESP32 can do serial RX/TX on other pins as well. In fact the pins RX/TX are normally connected to the USB to serial chip and used to flash the ESP32 via USB

1 Like

So how would I put it in the code? Would I put it as i022 and i021?

Yes just put the PIN number, if it doesn’t work switch them

yeah i posted about it on a different thread and got some help but i get this after the install and i get no detection data

nvm i fixed it had to change the gpio pin to 17 and that did the trick

looks like a perfect case. What are the dimensions inside? would a esp32 d1 mini fit inside? also is the base hollow? it its hollow I´m thinking I could add a temp sensor there, perfect spot, below the esp32 so the heat from the board would not affect it.

Hi, I have a little problem with the esp8266 mini d1 and the SEN0395. it works fine, but after few updates, the blue light on the d1 turn on and will not boot, its like is stuck in boot-loader. If I re-flash it ad remove the code from number then works fine, but I cant configure it. If I flash the code to a new esp8266 then it works fine, but again, because I’m trying different sensors and configurations, after few flashes, again. I also included a bme680 and bh1750.
My code is bellow. any help how I can get around this problem, I have 2 boards that I can only use if I remove the code from number to bme680_bsec.

esphome:
  name: $name
  platform: ESP8266
  board: d1_mini

# Insert your SSID and Your PWD after inital setup
wifi:
  ssid: "WIFI SSID"  
  password: "WIFI PASSWORD"  
  manual_ip:
    static_ip: 192.168.0.106
    gateway: 192.168.0.1
    subnet: 255.255.255.0
  
  ap:
    ssid: ${name}
    password: "12345678"
  
# Enable logging
logger:

# Enable Home Assistant API
api:

# Enable Home Assistant OTA Updates
ota:
  password: ""  

# Enable the captive portal for inital WiFi setup
captive_portal:

substitutions:
  name: eli-room
  friendly_name: Sensors Eli Room
  room: "Eli"

uart:
  id: uart_bus
  tx_pin: GPIO3
  rx_pin: GPIO1
  baud_rate: 115200
  debug:
    direction: BOTH
    dummy_receiver: true
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_string(direction, bytes);      

i2c:
  - id: bus_a
    sda: D2
    scl: D1
    scan: True

web_server:
  port: 80
  version: 2
  include_internal: true

http_request:
  useragent: esphome/$name
  timeout: 2s

binary_sensor:
- platform: gpio
  name: "mmwave ${name}"
  id: mmwave
  device_class: occupancy
  pin:
    number: GPIO16
    mode: INPUT_PULLDOWN 
- platform: status
  name: "Status"

switch:
  - platform: gpio
    pin: GPIO2
    name: "LED ${name}"
    inverted: true
    icon: "mdi:lightbulb"

  - platform: template
    name: "mmWave Sensor ${name}"
    id: "mmwave_sensor"
    optimistic: true
    restore_state: true
    turn_on_action:
      - uart.write: "sensorStart"
      - delay: 1s
    turn_off_action:
      - uart.write: "sensorStop"
      - delay: 1s  
  
  - platform: template
    name: "mmWave LED ${name}"
    id: "mmwave_led"
    optimistic: true
    restore_state: true
    assumed_state: false
    turn_on_action:
      - switch.turn_off: mmwave_sensor
      - delay: 1s
      - uart.write: "setLedMode 1 0"
      - delay: 1s
      - uart.write: "saveConfig"
      - delay: 3s
      - switch.turn_on: mmwave_sensor
    turn_off_action:
      - switch.turn_off: mmwave_sensor
      - delay: 1s
      - uart.write: "setLedMode 1 1"
      - delay: 1s
      - uart.write: "saveConfig"
      - delay: 3s
      - switch.turn_on: mmwave_sensor
number:
  - platform: template
    name: mmWave Distance
    id: mmwave_distance
    min_value: 0
    max_value: 800
    initial_value: 315
    optimistic: true
    step: 15
    restore_value: true
    unit_of_measurement: cm
    mode: box
    set_action:
      - switch.turn_off: mmwave_sensor
      - delay: 1s
      - uart.write: !lambda int cm = (int)ceil(x / 15.0);
                      std::string cms = "detRangeCfg -1 0 " + to_string(cm);
                      return std::vector<unsigned char>(cms.begin(), cms.end());
      - delay: 1s
      - uart.write: "saveCfg 0x45670123 0xCDEF89AB 0x956128C6 0xDF54AC89"
      - delay: 1s
      - switch.turn_on: mmwave_sensor

  - platform: template
    name: mmWave Off Latency
    id: mmwave_latency
    min_value: 0
    max_value: 65000
    initial_value: 12500
    optimistic: true
    step: 25
    restore_value: true
    unit_of_measurement: ms
    mode: box
    set_action:
      - switch.turn_off: mmwave_sensor
      - delay: 1s
      - uart.write: !lambda
                      int ms = (int)ceil(x / 25.0);
                      std::string mss = "outputLatency -1 0 " + to_string(ms);
                      return std::vector<unsigned char>(mss.begin(), mss.end());
      - delay: 1s
      - uart.write: "saveCfg 0x45670123 0xCDEF89AB 0x956128C6 0xDF54AC89"
      - delay: 1s
      - switch.turn_on: mmwave_sensor

  - platform: template
    name: mmWave Sensitivity
    id: mmwave_sensitivity
    min_value: 0
    max_value: 9
    initial_value: 7
    optimistic: true
    step: 1
    restore_value: false
    set_action:
      - switch.turn_off: mmwave_sensor
      - delay: 1s
      - uart.write:
          !lambda std::string mss = "setSensitivity " + to_string((int)x);
            return std::vector<unsigned char>(mss.begin(), mss.end());
      - delay: 1s
      - uart.write: "saveConfig"
      - delay: 1s
      - switch.turn_on: mmwave_sensor
  

bme680_bsec:
    # i2c address override (default is 0x76)
    address: 0x77

    # Temperature offset
    # ------------------
    # Useful if device is in enclosure and reads too high
    # For example if it reads 5C too high, set this to 5
    # This also corrects the relative humidity readings
    # Default: 0
    temperature_offset: 2.0
    
    # IAQ calculation mode
    # --------------------
    # Available options:
    # - static (for fixed position devices)
    # - mobile (for on person or other moveable devices)
    # Default: static
    iaq_mode: static

    # Interval at which to save BSEC state (default is 6 hours)
    state_save_interval: 6h

    # Sample rate
    # -----------
    # Available options:
    # - lp (low power - samples every 3 seconds)
    # - ulp (ultra low power - samples every 5 minutes)
    # Default: lp
    sample_rate: lp


sensor:
  - platform: bh1750
     # Illuminance level in lux from BH1750
    name: "Illuminance ${name}"
    address: 0x23
    update_interval: 30s
    
  - platform: bme680_bsec
    temperature:
       # Temperature in °C from BME680
      name: "Temperature ${name}"
      id: temp
      sample_rate: lp
      filters:
        - median
        - offset: -1.6

    pressure:
       # Pressure in hPa from BME680
      name: "Air Pressure ${name}"
      id: pressure
      sample_rate: lp
      unit_of_measurement: "hPa"
      filters:
        - lambda: >-
            return x / powf(1.0 - (415 / 44330.0), 5.255);
    humidity:
       # Relative humidity % from BME680
      name: "Humidity ${name}"
      id: humidity
      sample_rate: lp
      filters:
        - median
        - offset: 13.0
    gas_resistance:
       # Gas resistance in Ω from BME680
      name: "CO2 resistance ${name}"
      id: gas
      filters:
        - median
    iaq:
      # Indoor air quality value from BME680
      name: "IAQ ${name}"
      id: iaq_range
      filters:
        - median
    co2_equivalent:
      # CO2 equivalent estimate in ppm from BME680
      name: "CO2 Equivalent ${name}"
      filters:
        - median
    breath_voc_equivalent:
      # Volatile organic compounds equivalent estimate in ppm from BME680
      name: "Breath VOC Equivalent ${name}"
      filters:
        - median
    iaq_accuracy:
      # IAQ accuracy as a numeric value of 0, 1, 2, 3 from BME680
      name: "Numeric IAQ Accuracy ${name}"
  
  - platform: uptime
    name: Uptime sec
    id: uptime_sec
    update_interval: 60s
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s

 
  - platform: template
    # Absolute humidity in g/m³ based on himidity from BME680
    name: "Absolute humidity ${name}"
    lambda: |-
      const float mw = 18.01534;    // molar mass of water g/mol
      const float r = 8.31447215;   // Universal gas constant J/mol/K
      return (6.112 * powf(2.718281828, (17.67 * id(temp).state) /
        (id(temp).state + 243.5)) * id(humidity).state * mw) /
        ((273.15 + id(temp).state) * r); // in grams/m^3
    accuracy_decimals: 2
    update_interval: 60s
    icon: 'mdi:water'
    unit_of_measurement: 'g/m³'
    
  - platform: template
    name: "Air pressure at sea level ${name}"
    lambda: |-
      const float STANDARD_ALTITUDE = 415; // in meters, see note
      return id(pressure).state / powf(1 - ((0.0065 * STANDARD_ALTITUDE) /
        (id(temp).state + (0.0065 * STANDARD_ALTITUDE) + 273.15)), 5.257); // in hPa
    update_interval: 60s
    unit_of_measurement: 'hPa'

  - platform: template
    name: "Dew point ${name}"
    lambda: return (243.5*(log(id(humidity).state/100)+((17.67*id(temp).state)/
     (243.5+id(temp).state)))/(17.67-log(id(humidity).state/100)-
     ((17.67*id(temp).state)/(243.5+id(temp).state))));
    update_interval: 60s
    unit_of_measurement: '°C'
    
# bme680_sec      
  - platform: bme680_bsec
    iaq_accuracy:
      name: "IAQ Accuracy ${name}"
      
text_sensor:

  - platform: template
    name: "Air quality ${name}"
    icon: "mdi:air-filter"
    lambda: |-
   
      ESP_LOGD("main", "Current value %d", id(iaq_range));
      
      if ((id(iaq_range).state <= 50.0 )) {
        return {"Very good"};
      }
      else if ((id(iaq_range).state > 50.00)  && (id(iaq_range).state <= 100.0)) {
        return {"Good"};
      }
      else if ((id(iaq_range).state > 100.0) && (id(iaq_range).state <= 150.0)) {
        return {"A little dirty"};
      }
      else if ((id(iaq_range).state > 150.0) && (id(iaq_range).state <= 200.0)) {
        return {"Moderately dirty"};
      }
      else if ((id(iaq_range).state > 200.0) && (id(iaq_range).state <= 250.0)) {
        return {"Very dirty"};
      }
      else if ((id(iaq_range).state > 250.0) && (id(iaq_range).state <= 350.0)) {
        return {"Extremely dirty"};
      }
      else if ((id(iaq_range).state > 350.00)) {
        return {"Dangerously polluted"};
      }
      return {};
    update_interval: 30s
 
  - platform: wifi_info
    ip_address:
      name: IP Address
    ssid:
      name: Connected SSID
    bssid:
      name: Router BSSID
    mac_address:
      id: mac_address
      name: ESP Board Mac Address    

time:
  - platform: homeassistant
    id: homeassistant_time

Standard troubleshooting procedures apply; use a systematic approach.

I would personally remove everything, add one thing at a time and run for a week to prove that in isolation, all things before it work.

The 8266 is pretty underpowered compared to a 32 and the webserver & debug can add quite a bit of load/memory_consumption based on my experience. Don’t add what isn’t 100% necessary.

I tried, even if I remove everything but the mmwave still the same unless I delete the latency, sensibility and distance.

Have you tested restore_value: false ?

I tried with optimistic: true, optimistic: false, restore_value: true, restore_value: false also removing the 2 values

Have you tested with nothing but a ‘dummy’ number: configuration?

Eg.

number:
  - platform: template
    name: does_nothing_number
    id: does_nothing_number
    min_value: 0
    max_value: 800
    initial_value: 315
    optimistic: true
    step: 15
    restore_value: true
    unit_of_measurement: cm
    mode: box

with one dummy number works, thank you for the idea. I then created 4 dummy numbers, works fine, I then remove all and added only one, tried the 3 numbers mmwave_latency, mmwave_sensitivity and then the mmWave Distance, with any of the 3 fails. if I remove the code then doesn’t get stuck

      - delay: 1s
      - uart.write: "saveCfg 0x45670123 0xCDEF89AB 0x956128C6 0xDF54AC89"
      - delay: 1s
      - switch.turn_on: mmwave_sensor