ESPCAM doorbell with mmwave sensor

Here is my ongoing fully local doorbell.

Just got my 3d printer and made my first 3d design.



3D file: https://makerworld.com/en/models/588787

The model’s front part is flat but I heated it a bit up and bent the button just a bit to give it a button-ish feel. The design is made for that bent.

Still need to hook up those IR led’s for night vision tho.

With the mmwave sensor I take a snapshot and save it. After someone pushes the button I get an announcement upstairs and my entrance media player plays a dreamy bell. Also I send myself and my wife critical notifications for our iphones.

ESPHome yml code:

substitutions:
  name: esp32-cam
  friendly_name: Doorbell
  uart_tx_pin: GPIO3
  uart_rx_pin: GPIO1

esphome:
  name: ${name}
  platform: ESP32
  board: esp32dev
  includes:
    - LD2411s.h
  on_boot:
    priority: 250
    then:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x73, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]

# Enable logging
logger:

# Enable Home Assistant API
api:
    reboot_timeout: 0s

ota:
  - platform: esphome

web_server:
  port: 80

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp32-Cam Fallback Hotspot"
    password: "XXXXXX"

captive_portal:

# Example configuration entry
esp32_camera:
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  power_down_pin: GPIO32
  max_framerate: 20 fps
  vertical_flip: false
  horizontal_mirror: false
  resolution: 1024x768

  # Image settings
  name: My ESP32-CAM 

esp32_camera_web_server:
  - port: 8080
    mode: stream
  - port: 8081
    mode: snapshot

# Flashlight
output:
  - platform: gpio
    pin: GPIO4
    id: gpio_4

## GPIO_4 is the flash light pin
light:
  - platform: binary
    output: gpio_4
    name: flashlight
    id: led_flash

uart:
  id: uart_bus
  tx_pin: ${uart_tx_pin}
  rx_pin: ${uart_rx_pin}
  baud_rate: 256000
  parity: NONE
  stop_bits: 1

number:
  - platform: template
    name: "${name} Min Motion Distance"
    id: minmotion
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 717
    step: 1
  - platform: template
    name: "${name} Max Motion Distance"
    id: maxmotion
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 717
    step: 1
  - platform: template
    name: "${name} Min Presence Distance"
    id: minpresence
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 425
    step: 1
  - platform: template
    name: "${name} Max Presence Distance"
    id: maxpresence
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 425
    step: 1
  - platform: template
    name: "${name} Unoccupied Time"
    id: unocc_time
    optimistic: true
    unit_of_measurement: sec
    min_value: 0
    max_value: 6553
    step: 1

sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 3s
  - platform: custom
    lambda: |-
      auto my_sensor = new UARTSensor(id(uart_bus)); 
      App.register_component(my_sensor);
      return {my_sensor->distance_sensor, my_sensor->presence_sensor, my_sensor->motion_sensor, my_sensor->max_motion_sensor, my_sensor->min_motion_sensor, my_sensor->max_presence_sensor, my_sensor->min_presence_sensor, my_sensor->unocc_time_sensor};
    sensors:
      - name: "${name} Distance"
        state_class: measurement
        id: distance_sensor
        unit_of_measurement: cm
      - id: presence_sensor
        name: "internal_presense_sensor_to_binary_template"
        internal: true
        on_value:
          - binary_sensor.template.publish:
              id: presence_template
              state: !lambda return x > 0;
      - id: motion_sensor
        name: "internal_motion_sensor_to_binary_template"
        internal: true
        on_value:
          - binary_sensor.template.publish:
              id: motion_template
              state: !lambda return x > 0;
      - name: "internal_max_motion"
        id: max_motion_sensor
        internal: true
        on_value:
          - number.set:
              id: maxmotion
              value: !lambda return x;
      - name: "internal_min_motion"
        id: min_motion_sensor
        internal: true
        on_value:
          - number.set:
              id: minmotion
              value: !lambda return x;
      - name: "internal_max_presence"
        id: max_presence_sensor
        internal: true
        on_value:
          - number.set:
              id: maxpresence
              value: !lambda return x;
      - name: "internal_min_presence"
        id: min_presence_sensor
        internal: true
        on_value:
          - number.set:
              id: minpresence
              value: !lambda return x;
      - name: "internal_unocc"
        id: unocc_time_sensor
        internal: true
        on_value:
          - number.set:
              id: unocc_time
              value: !lambda return x;
    
binary_sensor:
  - platform: template
    id: presence_template
    name: "${name} Presence"
    device_class: occupancy
    filters:
      - delayed_off: 1s
  - platform: template
    id: motion_template
    name: "${name} Motion"
    device_class: motion
    filters:
      - delayed_off: 1s
  - platform: gpio
    name: "Ring Ring"
    pin: 
      number: GPIO14
      mode:
          input: true
          pulldown: true

script:
  - id: statepublish
    then:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write:
          id: uart_bus 
          data: !lambda
                  int minmot = id(minmotion).state;
                  int maxmot = id(maxmotion).state;
                  int minpr = id(minpresence).state;
                  int maxpr = id(maxpresence).state;
                  int unocctm = id(unocc_time).state;
                  uint16_t minmvalue = static_cast<uint16_t>(minmot);
                  uint8_t minmhighByte = static_cast<uint8_t>(minmvalue >> 8);
                  uint8_t minmlowByte = static_cast<uint8_t>(minmvalue & 0xFF);
                  uint16_t maxmvalue = static_cast<uint16_t>(maxmot);
                  uint8_t maxmhighByte = static_cast<uint8_t>(maxmvalue >> 8);
                  uint8_t maxmlowByte = static_cast<uint8_t>(maxmvalue & 0xFF);
                  uint16_t minpvalue = static_cast<uint16_t>(minpr);
                  uint8_t minphighByte = static_cast<uint8_t>(minpvalue >> 8);
                  uint8_t minplowByte = static_cast<uint8_t>(minpvalue & 0xFF);
                  uint16_t maxpvalue = static_cast<uint16_t>(maxpr);
                  uint8_t maxphighByte = static_cast<uint8_t>(maxpvalue >> 8);
                  uint8_t maxplowByte = static_cast<uint8_t>(maxpvalue & 0xFF);
                  uint16_t unoccvalue = static_cast<uint16_t>(unocctm * 10);
                  uint8_t unocchighByte = static_cast<uint8_t>(unoccvalue >> 8);
                  uint8_t unocclowByte = static_cast<uint8_t>(unoccvalue & 0xFF);
                  std::vector<uint8_t> data = {0xFD, 0xFC, 0xFB, 0xFA, 0x20, 0x00, 0x67, 0x00, 0x00, 0x00, maxmlowByte, maxmhighByte, 0x00, 0x00, 0x01, 0x00, minmlowByte, minmhighByte, 0x00, 0x00, 0x02, 0x00, maxplowByte, maxphighByte, 0x00, 0x00, 0x03, 0x00, minplowByte, minphighByte, 0x00, 0x00, 0x04, 0x00, unocclowByte, unocchighByte, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
                  return data;
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
6 Likes