Solved - Undefined reference to `vtable for esphome::adc::ADCSensor'

Can anyone tell me what’s going wrong here (trying to add a TEMT6000). I guess it has something to do with the “external_components”.

Error log:
INFO ESPHome 2024.4.2

INFO Reading configuration /config/esphome/esp-radar.yaml...
WARNING GPIO2 is a strapping PIN and should only be used for I/O with care.
Attaching external pullup/down resistors to strapping pins can cause unexpected failures.
See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins
INFO Generating C++ source...
INFO Compiling app...
Processing esp-radar (board: nodemcu-32s; framework: espidf; platform: platformio/[email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
 - framework-espidf @ 3.40406.240122 (4.4.6) 
 - tool-cmake @ 3.16.4 
 - tool-ninja @ 1.7.1 
 - toolchain-esp32ulp @ 2.35.0-20220830 
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
Reading CMake configuration...
Dependency Graph
|-- noise-c @ 0.1.4
Compiling .pioenvs/esp-radar/src/main.o
Linking .pioenvs/esp-radar/firmware.elf
/data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/esp-radar/src/main.o:(.literal._Z5setupv+0x1a4): undefined reference to `vtable for esphome::adc::ADCSensor'
/data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/esp-radar/src/main.o:(.literal._Z5setupv+0x1a8): undefined reference to `vtable for esphome::adc::ADCSensor'
/data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/esp-radar/src/main.o:(.literal._Z5setupv+0x1ac): undefined reference to `vtable for esphome::adc::ADCSensor'
collect2: error: ld returned 1 exit status
*** [.pioenvs/esp-radar/firmware.elf] Error 1
========================= [FAILED] Took 30.54 seconds =========================

My yaml file:

#Source: https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome
substitutions:
  devicename: "esp-radar" #Rename the device what you want.
  upper_devicename: ESP Radar #Rename the device what you want.
esphome:
  name: $devicename
  on_boot:    #LD1125H Initial Setting
    priority: -200
    then:
      - uart.write:
          id: LD1125H_UART_BUS
          data: !lambda |-
            std::string th1st = "mth1=" + str_sprintf("%.0f",id(LD1125H_mth1).state) +"\r\n";
            return std::vector<uint8_t>(th1st.begin(), th1st.end());
      - uart.write:
          id: LD1125H_UART_BUS
          data: !lambda |-
            std::string th2st = "mth2=" + str_sprintf("%.0f",id(LD1125H_mth2).state) +"\r\n";
            return std::vector<uint8_t>(th2st.begin(), th2st.end());
      - uart.write:
          id: LD1125H_UART_BUS
          data: !lambda |-
            std::string th3st = "mth3=" + str_sprintf("%.0f",id(LD1125H_mth3).state) +"\r\n";
            return std::vector<uint8_t>(th3st.begin(), th3st.end());
      - uart.write:
          id: LD1125H_UART_BUS
          data: !lambda |-
            std::string rmaxst = "rmax=" + str_sprintf("%.1f",id(LD1125H_rmax).state) +"\r\n";
            return std::vector<uint8_t>(rmaxst.begin(), rmaxst.end());
esp32:
  board: nodemcu-32s
  framework:
    type: esp-idf  #Suggest Use ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. 
    version: recommended
external_components:
  - source:
      type: git
      url: https://github.com/ssieb/custom_components #Thanks for @ssieb components.
    components: [ serial ]
logger:
  level: DEBUG  #You Can Use "INFO" Level
  baud_rate: 0
api:
  encryption:
    key: "Long_key"
ota:
  password: "secret_password"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  power_save_mode: LIGHT

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

captive_portal:

uart:
  id: LD1125H_UART_BUS
  rx_pin: GPIO16  #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang
  tx_pin: GPIO17  #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang
  baud_rate: 115200
  data_bits: 8
  stop_bits: 1
  parity: NONE
#  debug:
#    direction: BOTH
#    dummy_receiver: false
#    after:
#      delimiter: "\n"
#    sequence:
#      - lambda: UARTDebug::log_string(direction, bytes);
globals:
  - id: LD1125H_Last_Time
    type: time_t
    restore_value: no
    initial_value: time(NULL)
  - id: LD1125H_Last_Mov_Time
    type: time_t
    restore_value: no
    initial_value: time(NULL)
  - id: LD1125H_Clearence_Status
    type: bool
    restore_value: no
    initial_value: "false"
status_led:
  pin:
    number: GPIO2 #ESP32 OnBroad LED
    inverted: false
#web_server:   #Avoid Using Web Server To Prevent Hang
#  port: 80
interval:
  - interval: 1s #Clearance Scan Time
    setup_priority: -200
    then:
      lambda: |-
        if ((time(NULL)-id(LD1125H_Last_Time))>id(LD1125H_Clear_Time).state) {
          if ((id(LD1125H_Clearence_Status) == false) || (id(LD1125H_Occupancy).state != "Clearance")) {
            id(LD1125H_Occupancy).publish_state("Clearance");
            id(LD1125H_Clearence_Status) = true;
          }
          if (id(LD1125H_MovOcc_Binary).state == true) {
            id(LD1125H_MovOcc_Binary).publish_state(false);
          }
          if (id(LD1125H_Mov_Binary).state == true) {
            id(LD1125H_Mov_Binary).publish_state(false);
          }
        }
number:
  - platform: template
    name: ${upper_devicename} 0~2.8m Sensitivity #LD1125H mth1 #mth1 is 0~2.8m Sensitivity.
    id: LD1125H_mth1
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "60.0" #Default mth1 Setting
    min_value: 10.0
    max_value: 600.0
    step: 5.0
    set_action:
      then:
        - uart.write:
            id: LD1125H_UART_BUS
            data: !lambda |-
              std::string th1st = "mth1=" + str_sprintf("%.0f",x) +"\r\n";
              return std::vector<uint8_t>(th1st.begin(), th1st.end());
  - platform: template
    name: ${upper_devicename} 2.8~8m Sensitivity #LD1125H mth2 #mth2 is 2.8~8m Sensitivity.
    id: LD1125H_mth2
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "30" #Default mth2 Setting
    min_value: 5
    max_value: 300
    step: 5
    set_action:
      then:
        - uart.write:
            id: LD1125H_UART_BUS
            data: !lambda |-
              std::string th2st = "mth2=" + str_sprintf("%.0f",x) +"\r\n";
              return std::vector<uint8_t>(th2st.begin(), th2st.end());
  - platform: template
    name: ${upper_devicename} above 8m Sensitivity #LD1125H mth3 #mth3 is above 8m Sensitivity.
    id: LD1125H_mth3
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "20" #Default mth3 Setting
    min_value: 5
    max_value: 200
    step: 5
    set_action:
      then:
        - uart.write:
            id: LD1125H_UART_BUS
            data: !lambda |-
              std::string th3st = "mth3=" + str_sprintf("%.0f",x) +"\r\n";
              return std::vector<uint8_t>(th3st.begin(), th3st.end());
  - platform: template
    name: ${upper_devicename} max detection distance #LD1125H rmax #rmax is max detection distance.
    id: LD1125H_rmax
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "8" #Default rmax Setting
    min_value: 0.4
    max_value: 12
    step: 0.2
    set_action:
      then:
        - uart.write:
            id: LD1125H_UART_BUS
            data: !lambda |-
              std::string rmaxst = "rmax=" + str_sprintf("%.1f",x) +"\r\n";
              return std::vector<uint8_t>(rmaxst.begin(), rmaxst.end());
  - platform: template
    name: ${upper_devicename} Clearence Time
    id: LD1125H_Clear_Time
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "5" #LD1125H Mov/Occ > Clearence Time Here
    min_value: 0.5
    max_value: 20
    step: 0.5
  - platform: template
    name: ${upper_devicename} LD1125H Movement Time
    id: LD1125H_Mov_Time
    icon: "mdi:cogs"
    optimistic: true
    restore_value: true #If you don't want to store the setting at ESP, set it to false.
    initial_value: "1" #LD1125H Mov > Occ Time Here
    min_value: 0.5
    max_value: 10
    step: 0.5
sensor:  
  - platform: template
    name: ${upper_devicename} Distance
    id: LD1125H_Distance
    icon: "mdi:signal-distance-variant"
    unit_of_measurement: "m"
    accuracy_decimals: 2
    filters:    # Use Fliter To Debounce
    - sliding_window_moving_average:
        window_size: 8
        send_every: 2
    - heartbeat: 0.2s

  - platform: adc
    pin: 36
    name: "TEMT6000 Illuminance Gang"
    device_class: illuminance
    unit_of_measurement: lx
    update_interval: 20s
    filters:
      - lambda: |-
          return (x / 10000.0) * 2000000.0;
text_sensor:
  - platform: serial
    uart_id: LD1125H_UART_BUS
    name: ${upper_devicename} LD1125H UART Text
    id: LD1125H_UART_Text
    icon: "mdi:format-text"
    internal: False #If Don't Want to See UART Receive Data, Set To True
    on_value:
      lambda: |-
        if (id(LD1125H_UART_Text).state.substr(0,3) == "occ") {
          id(LD1125H_Distance).publish_state(atof(id(LD1125H_UART_Text).state.substr(9).c_str()));
          if ((time(NULL)-id(LD1125H_Last_Mov_Time))>id(LD1125H_Mov_Time).state) {
            id(LD1125H_Occupancy).publish_state("Occupancy");
            if (id(LD1125H_MovOcc_Binary).state == false) {
              id(LD1125H_MovOcc_Binary).publish_state(true);
            }
            if (id(LD1125H_Mov_Binary).state == true) {
              id(LD1125H_Mov_Binary).publish_state(false);
            }
          }
          if (id(LD1125H_MovOcc_Binary).state == false) {
            id(LD1125H_MovOcc_Binary).publish_state(true);
          }
          id(LD1125H_Last_Time) = time(NULL);
          if (id(LD1125H_Clearence_Status) == true) {
            id(LD1125H_Clearence_Status) = false;
          }
        }
        else if (id(LD1125H_UART_Text).state.substr(0,3) == "mov") {
          id(LD1125H_Distance).publish_state(atof(id(LD1125H_UART_Text).state.substr(9).c_str()));
          id(LD1125H_Occupancy).publish_state("Movement");
          if (id(LD1125H_MovOcc_Binary).state == false) {
            id(LD1125H_MovOcc_Binary).publish_state(true);
          }
          if (id(LD1125H_Mov_Binary).state == false) {
            id(LD1125H_Mov_Binary).publish_state(true);
          }
          id(LD1125H_Last_Mov_Time) = time(NULL);
          id(LD1125H_Last_Time) = time(NULL);
          if (id(LD1125H_Clearence_Status) == true) {
            id(LD1125H_Clearence_Status) = false;
          }
        }
  - platform: template
    name: ${upper_devicename} Occupancy Status
    id: LD1125H_Occupancy
    icon: "mdi:motion-sensor"
binary_sensor:
  - platform: template
    name: ${upper_devicename} Occupancy or Movement
    id: LD1125H_MovOcc_Binary
    device_class: occupancy
  - platform: template
    name: ${upper_devicename} Movement
    id: LD1125H_Mov_Binary
    device_class: motion

Solution was to change this in my code.

From:

esp32:
  board: nodemcu-32s
  framework:
    type: esp-idf

To:

esp32:
  board: nodemcu-32s
  framework:
    type: arduino

Great that you solved it but why are you making the CPU do resource intensive calculations like this (especially division)?

Simplify it to:

    filters:
      - lambda: |-
          return x * 200;