Gamma spectrometer possible?

Status
Not open for further replies.

MakerV

Member
I am a Educator looking to do a DIY gamma spectroscopy project with students (grade 10-12), and recently acquired a soundcard based gamma spectrometer (gamma spectacular) which has been amazing to use, however,
It was brought up that the ADCs used in sound cards are quite susceptible to pulse pileup at higher count rates. This had me thinking.. Seeing as the ADC capability on the Teensy 3.6 is capable of fast sampling in the Mhz range would it not be possible to make out own gamma spectrometer from such a board?

We recently acquired a Teensy 3.6 and I am just researching more about its capabilities.


From what I am reading, correct me if I am wrong that the ADC can sample in the Mhz range.



This has me rather excited.



Anyone chime in ?
 
I had a look at ADC library. I am still unsure what the maximum sample rate is using the ADC.
What I'd like to do is use the Teensy like an external audio card, only sampling at 1Mhz if possible.

or another alternative option would be use the teensy to do all the processing and binning of incoming pulses directly on board
sort of like this https://www.instructables.com/id/Multi-Channel-Analyzer-for-Gamma-Spectroscopy-With/
except the pulse stretching and conditioning circuit is not needed.
 
Here is the code I was playing with today. This an for an Arduino based spectrometer.
The result was that 2 of the libraries shot back errors. Lots of code in here that seems not to work with the Teensy platform.

Still investigating.






Code:
#include <U8glib.h>
U8GLIB_ST7920_128X64 u8g(13, 11, 12, U8G_PIN_NONE);

// Einstellungs-Tabelle für die Erhöhung der Taktfrequenz
// ======================================================

//  ADPS2     ADPS1    ADPS0     Division factor
//    0         0        0              2
//    0         0        1              2
//    0         1        0              4
//    0         1        1              8
//    1         0        0             16
//    1         0        1             32
//    1         1        0             64
//    1         1        1            128   (Standard)

#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


// Variablendeklaration
// ====================

const int analogInPin = A0;       // Analog input pin für die Pulshöhe
const int pin_verzoegerung = A1;  // Analog input pin für die über ein Poti einstellbare variable Verzögerung
const int pin_entleeren = 3;      // Digital output pin für das Entleeren des Speicherkondensators
const int pin_treffer = 4;        // Digital input pin für vom Monoflop kommenden treffer
const int pin_switch = 5;         // Digital output pin für switch
const int pin_test = 7;           // Digital output pin um zu überprüfen, in welcher Phase der Entladekurve von C die Spannungsmessung erfolgt
const int pin_reset = 8;          // Digital input pin für das Leeren des Pulshöhenarrays um eine neue Messung zu starten


int U_puls = 0;              // aktuelle gemessene Pulshöhe
float Spannung;              // aktuelle gemessene Pulsspannung
int Index = 0;               // Index der gemessenen Pulshöhe im Intervall [0,127]
float Faktor = 1;            // Vergrößerungs- bzw. Verkleinerungsfaktor
int Pulshoehen[128];         // array mit der Anzahl der jeweils 128 verschiedenen Pulshöhen
int reset_time;              // Zeitdauer in ms der U-Max-Speicherentleerung
int j;                       // Zählvariable als Maß für die Schnelligkeit der Pulsabfrage

int time_alt, time_neu;      // Variablen zur Ermittlung der Schleifendauer
int Verzoegerung;            // Verzögerungszeit in µs


// ===========================
// ========== SETUP ==========
// ===========================

void setup(void)
   {
    Serial.begin(9600);
    
    pinMode(pin_entleeren, OUTPUT);      // U-Speicher-Entleer-pin als output deklariert
    pinMode(pin_switch, OUTPUT);         // switch-pin als output deklariert
    pinMode(pin_test, OUTPUT);           // test-pin als output deklariert
        
    pinMode(pin_treffer, INPUT);         // treffer-pin als input deklariert
    pinMode(pin_reset, INPUT);           // reset-pin für die Anzeige als input deklariert
    
    
    digitalWrite(pin_entleeren, HIGH);   // U_max-Speicher entleeren
    digitalWrite(pin_switch, HIGH);      // Schalter für U-Zuleitung
    digitalWrite(pin_test, LOW);         // Test-pin auf 0 setzen
    
    
    for (int i = 0; i < 128; i++)
       {
        Pulshoehen[i] = 0;           // alle Pulshöhentreffer auf 0 setzen
       }
       
    Faktor = 1;         // Startvergrößerung für die graphische Darstellung
    
    reset_time = 5;     // Zeitdauer in ms der U-Max-Speicherentleerung
    
    
    
    #if FASTADC
    
    // set prescale to 16
    
    sbi(ADCSRA,ADPS2) ;      // ADPS2  auf  1  gesetzt
    cbi(ADCSRA,ADPS1) ;      // ADPS1  auf  0  gesetzt
    cbi(ADCSRA,ADPS0) ;      // ADPS0  auf  0  gesetzt
    
    // cbi = 0; sbi = 1
    
    #endif
    
    
    // Zeichnen der Achsen
    // ===================
    
    u8g.firstPage();
      
    do
       {
        u8g.drawLine(0, 63, 127, 63);
        u8g.drawLine(0, 0, 0, 63);          
       }
    while( u8g.nextPage() );
           
   }
   
   
   

// ===================================
// ========== HAUPTSCHLEIFE ==========
// ===================================

void loop(void)
   {
     /*
     Verzoegerung = analogRead(pin_verzoegerung);
     
     Verzoegerung = Verzoegerung * 10;   // Verzögerungsintervall 0 bis 1023 * 10 µs
     
     Serial.print("Verzoegerung im µs = ");
     Serial.println(Verzoegerung);
     */
            
     digitalWrite(pin_entleeren, HIGH);    // U_max-Speicher gelöscht
     delay(reset_time);                    // reset_time ms Wartezeit zum ausreichenden Löschen des U_max-Speichers
     digitalWrite(pin_entleeren, LOW);     // U_max-Speicher bereit
     
     digitalWrite(pin_switch, HIGH);       // Schalter für U-Zuleitung geschlossen; Messung startet... eigentlich unnötig, da ja eh der Kondensator gelöscht wird und auf den ersten Puls gewartet wird
         
     
     // Warte bis ein vom Monoflop verlängerter Puls über DIGITAL-IN registriert wird!
     // ==============================================================================
          
     while(digitalRead(pin_treffer) == LOW)
        {
        }
     
     
     
     //delayMicroseconds(Verzoegerung);    // übers Poti variable Verzögerung, damit der Zuleitungsschalter nicht schon schließt obwohl der Spannungspuls noch nicht sein Maximum erreicht hat!
     delayMicroseconds(10);                // fixe Verzögerung, damit der Zuleitungsschalter nicht zu früh schließt und der Spannungspuls auch zu seinem Maximum anwachsen kann!
     
     digitalWrite(pin_switch, LOW);      // Puls wurde registriert --> Schalter für U-Zuleitung offen; Messung gestoppt
          
     
     // Pulshöhe wird eingelesen
     // ========================     
     
     U_puls = analogRead(analogInPin);             // Einlesen der Pulshöhe 0-5V
     
     
     
     // digitale Ausgabe über den Test-Pin unmittelbar nach Einlesen der Spannung um festzustellen, "wo" in der Entladekurve die Spannung gemessen wird. Soll ja genau im Maximum erfolgen!
     // -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     /*
     digitalWrite(pin_test, HIGH);      // Test-pin auf 1 setzen
     delay(5);                          // Verzögerung
     digitalWrite(pin_test, LOW);       // Test-pin auf 0 setzen     
     */
     
       
     
     // graphische und Speicher-Verarbeitung der registrierten Pulshöhe
     // ---------------------------------------------------------------
     
     Index = map(U_puls, 0, 1023, 0, 127);         // Index der aktuell gemessenen Pulshöhe im Intervall [0,127]
     
     Pulshoehen[Index] = Pulshoehen[Index] + 1;    // aktuelle Pulshöhe erhält einen Treffer

     //Spannung = U_puls * 5.0 / 1023;
     //Serial.print("Pulshoehe = ");                 // serielle Ausgabe der aktuellen Pulshöhe 0-5V
     //Serial.println(Spannung,2);      



     // ==============================================
     // ============ graphische Ausgabe ==============
     // ==============================================
      
     u8g.firstPage();
      
     if (int(Faktor * Pulshoehen[Index]) > 63)    // Zuviele Treffer für die ausreichende y-Darstellung --->  Stauchung um Faktor 2
        {
         Faktor = Faktor / 2; 
        }
    
     do
        {
         u8g.drawLine(0, 63, 127, 63);
         u8g.drawLine(0, 0, 0, 63);
        
         for (int i = 0; i < 128; i++)
            {
             u8g.drawLine(0+i, 63, 0+i, 63 - int(Faktor * Pulshoehen[i]));     // zeichnen aller Treffer
            }        
        }
     while( u8g.nextPage() );
     
     
         
     // Abfrage, ob der Reset-Knopf betätigt wurde
     // ------------------------------------------
     
     if (digitalRead(pin_reset) == HIGH)
        {
         // Spektrum an den Computer senden
         // ===============================
          
         for (int i = 0; i < 128; i++)
            {
             Serial.println(Pulshoehen[i]);
            }

        
         // Spektrum löschen
         // ================
         
         for (int i = 0; i < 128; i++)
            {
             Pulshoehen[i] = 0;           // alle Pulshöhentreffer auf 0 setzen
            }
       
         Faktor = 1;         // Startvergrößerung für die graphische Darstellung 
        }
     
   
   
   //delay(2);   // optionale Zeitverzögerung
     
   }
 
Status
Not open for further replies.
Back
Top