14 Jun 2025 - tsp
Last update 14 Jun 2025
14 mins
Recently, I acquired a fascinating scientific instrument: the Radiacode 102 (note: This is an Amazon affiliate link, this pages author profits from qualified purchases) pocket gamma spectrometer featuring an Cesium Iodine (CsI(Tl)) scintillator with digital readout. Note that at the time of writing, a new version—the Radiacode 103 (note: This is an Amazon affiliate link, this pages author profits from qualified purchases) — is already available, offering better spectral resolution at $8.4% \pm 0.3%$ FWHM compared to $9.4% \pm 0.4%$ FWHM of the 102. Additionally, a high-resolution variant exists: the Radiacode 103G, which achieves an impressive $7.4% \pm 0.3%$ FWHM. Despite this, the Radiacode 102 remains a compact and affordable gamma spectrometer designed for both amateur and professional radiation detection. Unlike typical Geiger counters, which only measure radiation levels, this device provides detailed spectral information, allowing users to identify specific radioactive isotopes in their environment.
In this post, I want to walk you through what makes this device so useful, the key differences between gamma spectrometry and Geiger counting, and how it performs in real-world scenarios—from mapping radiation levels in the field to analyzing fixed radioactive sources in a lab. I will also cover its mobile integration and show how it can be controlled programmatically using Python via USB and Bluetooth connection.
Geiger counters are widely known for their simplicity and affordability. They provide a basic count rate (in counts per second or microsieverts/hour) without distinguishing between the types or energies of the detected radiation. While useful for identifying the presence of radiation, they fall short when it comes to identification.
Gamma spectrometers like the Radiacode 102 go much further. They measure the energy spectrum of incoming gamma rays, allowing one to identify characteristic emission lines from specific isotopes such as Potassium-40, Cesium-137, or isotopes in the uranium and thorium decay chains. This makes them vastly superior when the goal is isotope identification, environmental monitoring, or educational demonstrations.
Gamma spectrometers like the RadiaCode 102 are based on scintillation detectors - specifically, a thallium-doped cesium iodide crystal, or CsI(Tl). When a gamma ray enters the detector, it interacts with the crystal material . These interactions deposit energy in the crystal, which is then re-emitted as visible light (scintillation photons). Gamma photons interact with matter primarily through three mechanisms, depending on their energy: the photoelectric effect, Compton scattering, and pair production.
For charged particles like electrons, protons or positrons on the other side the energy loss in matter is governed by the Bethe-Bloch equation, which describes how much energy they lose per unit distance through ionization:
[ \begin{aligned} -\frac{dE}{dx} &= \frac{4 \pi n z^2}{m_e c^2 \beta^2} \left(\frac{e^2}{4 \pi \epsilon_0}\right)^2 \left(\ln\left(\frac{2 m_e c^2 \beta^2}{I(1-\beta^2)}\right) - \beta^2\right) \end{aligned} ]For a gamma spectrometer the effects that are relevant are the Photoelectric effect and Compton Scattering. The emitted light is then collected by a photodetector, usually a silicon photomultiplier (SiPM) or photodiode, and converted into an electrical pulse. The pulse height (amplitude) is proportional to the energy of the incident gamma photon. By digitizing and sorting these pulses into a histogram of counts versus pulse amplitude, the spectrometer reconstructs a gamma energy spectrum.
The energy resolution of such a detector - the ability to distinguish closely spaced spectral lines - is limited by several physical and electronic factors:
In practice, CsI(Tl) is chosen for its robustness, low cost, and non-hygroscopic behavior, even though its resolution is inferior to high-end materials. A typical CsI(Tl)-based detector like the RadiaCode 102 achieves energy resolutions around 7–10% FWHM at the 662 keV line of Cesium-137.
There actualls exists a Geant4 digital twin model on GitHub for the crystal used in the Radiacode devices.
This method enables the identification of specific isotopes based on their characteristic gamma emission energies, giving spectrometers an advantage over simpler detectors like Geiger counters. Other detectors that are actually capable of doing spatial and energy resolved detection of particles would be semiconductor particle detector like the ones used during my diploma thesis.
The Radiacode 102 excels in two very different use cases:
Note that of course the mobile use case is very limited to more active radiating samples since one needs to perform proper background compensation and long term integration for low activity samples.
One of the key strengths of the Radiacode 102 is its Bluetooth connectivity. In addition, the device fits every pocket—and is usually delivered with a bag for runners and bikers. The Android app allows you to view radiation levels in real-time, access the spectral data, and even visualize radiation maps by combining GPS data with the measured gamma spectrum. It takes a while to get used to the app though since it exposes about every feature simply accessible - one has to play for a few days to really get all features.
Here’s an example screenshot of the mapping mode, showing a survey route with overlaid dose rates and spectral features.
To demonstrate its capabilities, here are a few spectrum images acquired from common sources. Note that this section will (hopefully) grow over time as I get access to and enough integration time with different samples (for obvious reasons dangerous resources cannot be measured at home or at an arbitrary location).
The first experiment was to gather data using the Android App and measure Potassium-40 decay.This is actually a background measurement - Potassium-40 offers a single 1460.8 keV gamma photon peak. Since potassium was created during the creation of the early solar system and exists in soil, concrete, bricks, humans and somewhat enriched in bananas with a $\tau_{\frac{1}{2}} \approx 1.248 * 10^{9}$ years it offers a very prominent decay line to check functionality of the gamma spectrometer since one expects it to be present.
Even after short integration time of around 20 hours one can easily spot the K-40 line in the above screenshot of the Android Application.
Beyond the mobile app, the Radiacode 102 can also be remotely controlled using a Python library. This works reliably via USB, and on supported operating systems even wirelessly via Bluetooth LE, enabling flexible integration into mobile or automated platforms. This opens up the possibility for programmatic control and data analysis. An open-source Python library allows access to raw spectral data, real-time measurements, and even configuration of the device.
The library is available via PyPi and can simply be installed via
pip install radiacode
It’s source code is available on GitHub.
After attaching the device to the USB port it should be recognized as USB device with vendor ID 0x0483
and product ID 0xF123
. Unfortunately all RadiaCode devices have like many cheaper devices the same serial number for all devices - it’s not simply possible to distinguish multiple attached spectrometers and assign unique symlinks for them. The following shows the dump of the USB descriptors by usbconfig
:
ugen5.2: <RadiaCode RadiaCode-102> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (400mA)
bLength = 0x0012
bDescriptorType = 0x0001
bcdUSB = 0x0201
bDeviceClass = 0x0000 <Probed by interface class>
bDeviceSubClass = 0x0000
bDeviceProtocol = 0x0000
bMaxPacketSize0 = 0x0040
idVendor = 0x0483
idProduct = 0xf123
bcdDevice = 0x0200
iManufacturer = 0x0001 <RadiaCode>
iProduct = 0x0002 <RadiaCode-102>
iSerialNumber = 0x0003 <RC-102-009455>
bNumConfigurations = 0x0001
Configuration index 0
bLength = 0x0009
bDescriptorType = 0x0002
wTotalLength = 0x0020
bNumInterfaces = 0x0001
bConfigurationValue = 0x0001
iConfiguration = 0x0004 <Custom Config>
bmAttributes = 0x00c0
bMaxPower = 0x00c8
Interface 0
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0000
bNumEndpoints = 0x0002
bInterfaceClass = 0x00ff <Vendor specific>
bInterfaceSubClass = 0x00ff
bInterfaceProtocol = 0x00ff
iInterface = 0x0005 <Custom Interface>
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0081 <IN>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0040
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0001 <OUT>
bmAttributes = 0x0002 <BULK>
wMaxPacketSize = 0x0040
bInterval = 0x0000
bRefresh = 0x0000
bSynchAddress = 0x0000
On FreeBSD one can use devd
to assign proper permissions to all radiacode devices though as usual via a custom devd
rule in /usr/local/etc/devd/radiacode.conf
after creating a new group and adding your user to it:
notify 1000 {
match "system" "USB";
match "subsystem" "INTERFACE";
match "type" "ATTACH";
match "vendor" "0x0483";
match "product" "0xf123";
action "chgrp radiacode /dev/$cdev && chgrp -h radiacode /dev/$cdev";
};
To crete the group and add a user to it on FreeBSD:
sudo pw groupadd radiacode
sudo pw usermod ${USER} -G radiacode
The first thing to try is of course to dump the spectrum. Here is a simple snippet showing how to do this and display it as a matplotlib
plot:
from radiacode import RadiaCode
import matplotlib.pyplot as plt
# Connect to device using USB connection
device = RadiaCode()
# Fetch current spectrum from the device
spectrum = device.spectrum()
# Plot using matplotlib
fig, ax = plt.subplots()
ax.plot(spectrum.counts)
ax.set_title(f"Gamma spectrum ({spectrum.duration})")
ax.set_xlabel("Channel")
ax.set_ylabel("Counts")
ax.grid()
plt.show()
The example script should fetch the current spectrum from the device:
By switching the scale to logarithmic one can get more insight about the peaks:
ax.set_yscale('log')
This capability enables long-term monitoring, automated isotope identification, and integration with other systems or research software. It also allows simple integration of the Radiacode into mobile platforms like drones or robots.
While the Radiacode 102 does feature a built-in display capable of showing basic dose rate information and local alarms, its standalone usability is limited. Although it logs data even without a smartphone connection - except GPS position - and includes a rudimentary spectrum view, meaningful use truly begins when paired with a mobile or desktop application for full-spectrum analysis and interpretation. In addition the use of background subtraction in the Android application at time of writing this blog article is pretty limited since it lacks normalization from counts to dose rates.
A noteworthy issue is the lack of any authentication mechanism for the Bluetooth interface. This means that, in principle, any nearby device with the Radiacode app could connect to your spectrometer without prior pairing or permission, which may raise privacy or data integrity concerns in shared or public environments.
Another practical limitation arises not from the spectrometer itself but from the Android ecosystem. On some devices, particularly older or budget models, aggressive power management can terminate the app—even when explicitly excluded from optimization. Situations such as running out of memory during photography or phone calls may also cause the app to be killed, interrupting data acquisition unexpectedly.
The Radiacode 102 is an exceptional tool for anyone interested in radiation science, environmental monitoring, or amateur radioactivity exploration. Its combination of spectral detail, portability, Bluetooth connectivity, and open USB interface makes it one of the most versatile and user-friendly gamma spectrometers in its class.
In future posts, I might dive deeper into automatic isotope identification or custom logging and mapping software. But for now, this device is already an impressive bridge between citizen science and professional-grade instrumentation.
This article is tagged:
Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)
This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/