Raspberry Pi Pico Ionising Radiation Sensor

, updated 13 August 2024 🔖 iot ⏲️ 2 minutes to read

I'm recording CO2 levels, motion, temperature, humidity and atmospheric pressure, so what's left to detect? Ambient ionising radiation, of course! ☢️ As with the other Raspberry Pi Pico sensors, this one will report back to Home Assistant to allow plotting the radiation over time in μSv/h (microsieverts per hour).

To contextualise this value, the EU has a radiological map which includes the UK. At the time of writing, the monitoring station closest to me was reporting an average of around 110 nSv/h (nanosieverts per hour). My measurement above shows 150 nSv/h, which is slightly above this value. This discrepancy is probably due to the sensor not being calibrated.

⚠️ This project is for hobby use only, it is not accurate enough for safety applications ☢️

Components

I'm using the Gravity Geiger Counter Module, which includes the M4011 Geiger Tube. The approach to measuring in this post should work for any tube though; after all the code just needs to measure pulses on a GPIO pin. The M4011 tube is compared against similar tubes here, which discusses its sensitivity to direct sunlight (also noted on the product documentation). I'm also using a Raspberry Pi Pico W with MicroPython to process the data and respond to pulses from the geiger tube.

Code

The code needs to do a few things:

  1. Process clicks as they're coming in from the Geiger tube
  2. Sample the clicks every so often, and convert them to a μSv/h value
  3. Report this value to Home Assistant

Processing Clicks via GPIO

from machine import Pin

clicks = 0
pin = Pin(0, Pin.IN)

def click(pin):
    clicks += 1
    
pin.irq(trigger=Pin.IRQ_RISING, handler=click, hard=True)

The above code uses a hardware interrupt on GPIO pin 0 to increment the clicks variable, in response to a pulse from the geiger tube. See Writing interrupt handlers for more information about hardware interrupts and the limitations of them.

Sampling Microsieverts

I created geiger.py to wrap the above logic, and deal with the sampling of the clicks on a regular basis. To use the code, see the below example:

import utime
from machine import Pin
from geiger import Geiger

pin = Pin(0, Pin.IN)
geiger = Geiger(153.8, pin, Pin.IRQ_RISING, 60_000)

while True:
   geiger.update()

   if geiger.datapoint.get_needs_update():
      print(geiger.datapoint.get_value(), "μSv/h")
      geiger.datapoint.set_value_updated()

   utime.sleep(1)

This code will print the μSv/h value every 60_000 milliseconds. You can increase or decrease this value depending on how frequently you want to sample the clicks (but less frequent samples mean more variability).

Reporting Results to Home Assistant

For the previous sensor projects, I created hass.py which wraps the POST /api/states/<entity_id> API. Putting it all together, the logic looks like this:

import utime
from machine import Pin
from geiger import Geiger
from hass import Hass

pin = Pin(0, Pin.IN)
geiger = Geiger(153.8, pin, Pin.IRQ_RISING, 60_000)
hass = Hass("http://assistant.home", "ey....")

while True:
   geiger.update()

   if geiger.datapoint.get_needs_update():
      hass.send_update(geiger.datapoint.get_value(), "μSv/h", None, "Radiation Sensor", "sensor.radiation")
      geiger.datapoint.set_value_updated()

   utime.sleep(1)

This logic is available in the main.py code, which includes configurable support for all of the other sensors, and WiFi connection handling.

🏷️ code value geiger tube sensor clicks sample raspberry pi pico radiation assistant μsv gpio logic

⬅️ Previous post: Loki and Grafana for Logs

➡️ Next post: Raspberry Pi Pico HTTP Admin Dashboard

🎲 Random post: Recording Camera Animations for UE4 with a Phone

Comments

Please click here to load comments.