Help with some YAML please, for a geiger counter interface on zigbee

Hello Hive Mind. I know I might be trying to get a little ahead of the curve with zigbee on ESPHome but I’m hoping someone can help me get over a small hurdle with my geiger counter interface.

I have interfaced a geiger counter to an EPS32-C6 so I can put radiation counts on a dashboard somewhere, just for fun. I have had the hardware working on a WiFi device, but I really want this on Zigbee.

With a lot of fluffing around I have some code that actually compiles ok, and attaches to the ZHA network. My main problem is that the counts don’t update :roll_eyes:

I was a software engineer at some stage of my career and have lots of knowledge across many high-level and low level languages. This YAML messes with my head. Anyway, here is the code so far:

esphome:
  name: radiation-detector
  platformio_options:
    board_build.f_cpu: 160000000L

esp32:
  board: esp32-c6-devkitc-1
  variant: esp32c6
  framework:
    type: esp-idf
  partitions: partitions_zb.csv

external_components:
  - source: github://luar123/zigbee_esphome
    components: [ zigbee ]

zigbee:
  id: zb_node
#  wipe_on_boot: once
  power_supply: 1
  endpoints:
    - id: radiation_ep
      num: 1
      device_type: TEMPERATURE_SENSOR
      clusters:
        - id: TEMP_MEASUREMENT
          attributes:
            - id: radiation_attr
              attribute_id: 0
              type: S16
              report: true
              device: radiation_sensor

sensor:
  - platform: pulse_counter
    pin:
      number: GPIO20
      mode:
        input: true
        pullup: false
      inverted: true
    name: "Radiation Level"
    id: radiation_sensor
    unit_of_measurement: "CPM" # Changed to Counts Per Minute
    accuracy_decimals: 0
    update_interval: 60s # Count pulses over 60 seconds
    
    # Optional: Filter out noise (pulses shorter than 100us)
    internal_filter: 13us

    
    # To pass the raw 60s count to zigbee
    on_value:
      then:
        - lambda: |-
            // Publishes total counts over the last 60s
            id(radiation_sensor).publish_state(x);

I know I am really getting on at the ground floor on this stuff. The paint is still fresh. If you could point me at a strategy that will get the code going with the clusters, or whatever, that is available now it would be appreciated.

Once this is going I’ll write up the project in a blog so it can be replicated by other HA community members.

You likely need:

        - zigbee.setAttr:
            id: radiation_attr
            value: !lambda "return x;"
1 Like

Thanks for your assistance. I will give this a try tomorrow :slightly_smiling_face:.

OK. I added the setAttr lines to the YAML. Still no joy. I am not convinced that the device has been updated. It is making all the right signs on the compile and install, but the device doesn’t seem to be updating to anything different. I have cleared the compile files for a fresh rebuild, removed the device from the ZHA integration, then reinstalled. Device seems to interview properly, but the number doesn’t increment at all. Shows 0.0 (since it is using a temperature reporting function).

Code as it currently is:

esphome:
  name: radiation-detector
  friendly_name: Geiger pulse_counter
  project:
    name: SRC.GeigerCounter
    version: '1.0.0'
  platformio_options:
    board_build.f_cpu: 160000000L

esp32:
  board: esp32-c6-devkitc-1
  variant: esp32c6
  framework:
    type: esp-idf
  partitions: partitions_zb.csv

external_components:
  - source: github://luar123/zigbee_esphome
    components: [ zigbee ]

zigbee:
  id: zb_node
#  wipe_on_boot: once
  power_supply: 1
  endpoints:
    - id: radiation_attr
      num: 1
      device_type: TEMPERATURE_SENSOR
      clusters:
        - id: TEMP_MEASUREMENT
          attributes:
            - id: radiation_attr
              attribute_id: 0
              type: S16
              report: true
              device: radiation_sensor
    
sensor:
  - platform: pulse_counter
    pin:
      number: GPIO20
      mode:
        input: true
        pullup: false
      inverted: true
    name: "Radiation Level"
    id: radiation_sensor
    unit_of_measurement: "CPM" # Changed to Counts Per Minute
    accuracy_decimals: 0
    update_interval: 60s # Count pulses over 60 seconds
    
    # Optional: Filter out noise (pulses shorter than 100us)
    internal_filter: 13us

    
    # To pass the raw 60s count to zigbee
    on_value:
      then:
        - lambda: |-
            // Publishes total counts over the last 60s
            id(radiation_sensor).publish_state(x);
        - zigbee.setAttr:
            id: radiation_attr
            value: !lambda "return x;"

#light:
#  - platform: esp32_rmt_led_strip
#    name: Status LED
#    pin: GPIO8
#    rgb_order: RGB
#    num_leds: 1
#    rmt_channel: 0
#    chipset: ws2812
#    entity_category: config

I have also tried erasing the flash memory with the relevant python command, then reprogramming.

I also started adding some LED functionality but have left that our for now for simplicity.

I did add a couple of extra lines to put in a project and version number. When I can see them in the attached device on the Zigbee network I will be happy.

Any clues where I should start digging from here please?

That part will definitely not work and you have to remove it.
At worse, it creates an endless loop (you publish the state on itself each time the state changes).

Generally speaking, no clue on the quality / working status of the component you are using…

Thanks for the possible clue. As it stands it seems to communicate with HA when first connected but then there are no further updates to the data. Will keep digging around that.

The device I am using is an ESP32-C6. I did have this working successfully on the WiFi network, but would like it to be on Zigbee. So the hardware is good I think.

Ok. I have this working well. Next time I am at a PC I will provide working code.

I will eventually put the entire functionality, hardware and YAML, in a single post.

OK. Here is my working code, with the counts coming across as a temperature measurement.

esphome:
  name: radiation-detector
  friendly_name: Geiger

  platformio_options:
    board_build.f_cpu: 160000000L

esp32:
  board: esp32-c6-devkitc-1
  variant: esp32c6
  framework:
    type: esp-idf
  partitions: partitions_zb.csv

external_components:
  - source: github://luar123/zigbee_esphome
    components: [zigbee]

zigbee:
  id: zb_node
  power_supply: 1
  endpoints:
    - id: radiation_attr
      num: 1
      device_type: TEMPERATURE_SENSOR
      clusters:
        - id: TEMP_MEASUREMENT
          attributes:
            - id: radiation_attr
              attribute_id: 0
              type: S16
              report: true
              device: radiation_sensor
              scale: 100 # multiplies CPM x 100

sensor:
  - platform: pulse_counter
    pin:
      number: GPIO20
      mode:
        input: true
        pullup: false
      inverted: true
    name: "Radiation Level"
    id: radiation_sensor
    unit_of_measurement: "CPM" # Changed to Counts Per Minute
    accuracy_decimals: 0
    update_interval: 60s # Count pulses over 60 seconds
    # Optional: Filter out noise (pulses shorter than 5us)
    internal_filter: 5us
    on_value:
      then:
        - zigbee.setAttr:
            id: radiation_attr
            value: !lambda "return int(x);"
        - zigbee.report: zb_node # Explicitely push update to HA 

# Enable logging for debugging
#logger:
#  level: DEBUG

This is with HA 2026.4.4, and all the latest updates related to this.

Share and Enjoy :slight_smile:

1 Like