Trinket powered geiger counter

Lately I have been messing around a bit with microprocessor powered geiger counters. One smart guy came up with the idea of generating high voltage using PWM signals from the microprocessor itself. With some additional external parts a HV supply and negative going pulse suitable for microprocessors is easy to make. Here is a schematic I came up with:

gm counter interface

The circuit works as follows: A ~1 Khz squarewave turns the MPSA44 high voltage transistor on and off, generating high voltage when the  inductors current is shut off. The voltage depends on the pulse width of the square wave which can be tweaked in software. The 1N4007 diode rectifies this voltage, and the HV cap removes most of the ripple on this voltage. The resistor limits current to the GM tube. The current pulses from the tube generate a voltage drop over the 100K resistor which turns on the BC546. When this happens the voltage through the 10K resistor is pulled to ground, generating a negative going pulse each time the GM tube detects an ionizing ray or particle.

To drive this circuit I used my new Adafruit Trinket, a small board with a Attiny85 microprocessor. Using the tutorials on the Adafruit website it is easy to work with from the Arduino environment. Here is the code:

void setup() {
 analogWrite(0, 30); //starts PWM on pin 0, generates about 400V
 analogWrite(1, 255); // needed to get LED to full brightness
 attachInterrupt(0,countPulse,FALLING); // attach interrupt to pin 2
void loop() {
 //nothing much really
void countPulse(){
 //pulse led
 digitalWrite(1, HIGH);

And here is a video of the setup in use:


Of course it is rather wasteful to only use the microprocessor to generate PWM and flash a LED. I plan on implementing counting and serial output in software later. Unfortunately the Trinket does not have native serial USB capability but bit banging a serial signal on one of the pins should work fine according to several sites. Then it is just a matter of adding a cheap PL2303 serial to USB adapter.

Update 18/4/2014

Added serial logging capability. Using a tx only software serial library, the Trinket outputs the measurements in CPM each 10 seconds on pin 4. New code:

// Trinket GM counter by Johan/

//counting vars
long count = 0;
long countPerMinute = 0;

// init softserial only tx on pin 4
#include <SendOnlySoftwareSerial.h>
SendOnlySoftwareSerial mySerial (4);

void setup() {
  mySerial.begin(9600); // init serial 9k6
  analogWrite(0, 30); //starts PWM on pin 0, generates about 400V
  analogWrite(1, 255); // needed to get LED to full brightness
  attachInterrupt(0,countPulse,FALLING); // attach interrupt to pin 2
  mySerial.println ("Trinket GM counter starting..."); 

void loop() {
  delay(10000); //the count is incrementing during this delay
  countPerMinute = 6 *count;
  mySerial.println (countPerMinute);
  count=0; //reset the count

void countPulse(){
    //pulse led when count is increased
    digitalWrite(1, HIGH);

Example serial output using cheap eBay USB<>TTL serial adapter:

Trinket GM counter starting...
402        <--- thorium bearing mantle held next to GM tube

There still need to be some tweaking done, the circuit is quite susceptible to electromagnetic interference which causes erroneous counts.

4 Responses to Trinket powered geiger counter

  1. This is seriously impressive. I like the way how you simplified the code, great stuff!

  2. Pingback:This geiger counter is powered by Adafruit & Atmel | Bits & Pieces from the Embedded Design World

  3. Avatar CBGoodBuddy
    CBGoodBuddy says:

    Huh, I didn’t think delay() worked inside of an interrupt handler.
    attachInterrupt documentation says, “Inside the attached function, delay() won’t work and the value returned by millis() will not increment.” So kudos to you for defying convention. 🙂

  4. HERE is a fucntion wqhich – as name states – eats time

    char k_eat_time(unsigned int eatTime)
    76 {
    77 unsigned long l;
    78 // tested on uno for 5 msec and 500 msec
    79 // quants in milli seconds
    80 l = eatTime;
    81 l *=1323;
    82 while (l–) {
    83 asm(“nop \n\t nop \n\t nop \n\t nop \n\t nop \n\t nop”);
    84 }
    85 }