/*
* This code accompanies the article "Gamma Spectroscopy with Arduino UNO" by C.M. Lavelle and published in the American Journal of Physics.
* The Digilent Analog Shield (DAS) is used, and is compatable with UNO and DUE and chipkit products.
* If using with DUE, the SPI must be called.
* The DAS libraries must be included.
*
* This program outputs the pulse spectrum recorded on the peak and hold circuit (PKD01, PHIC in paper) to the serial port.
* The user is intended to cut and paste the data from the serial port to a text file for processing and plotting.
* The format is the spectrum on a single line, followed by the total milliseconds of measurement time since the device was reset.
* This is followed by several lines of "-1" to separate repeated data prints.
* The date will export at regular intervals as the spectrum accumulates.
*
* The user will note several delays and serial flush commands, these were found by the author to help ensure performance over long periods.
* The author has also found arduino uno pin 11 to be experiencing pickup, and should be avoided for selection of the logic pins.
*
* Initially, the HV is set to ~27 V and the cutoff to ~35 mV.
* Increasing the HV can increase signal intensity from the SiPM, but also may increase noise, and CUTOFF may need to be raised.
*
*
* The code functions by
* 1. Initialize (setup)
* a. Setup serial port
* b. Set PHIC to "off"
* c. Set HV to ~27 V if using a SENSL product (+2.5V over breakdown)
* HV Output = (ADC-32768)/32768*5*(100/2.5) = (ADC-32768)*0.006103515625
* 2. Measurement (loop)
* a. Set PHIC to tracking state
* b. Repeatedly measure the PHIC output on the DAS (analog.read)
* c. If the PHIC is storing a pulse >cutoff, put the PHIC into a hold state and set tracking to off
* d. Determine which element of the array the pulse belongs to (Eqn. 1 in the paper) and increment the count by 1
* e. reset the PHIC
* f. Check to see if it is time to export data (every 1000 events or 10 seconds)
*/
#include <SPI.h> // required for ChipKIT and Arduino DUE
#include <ADC.h>
#include <ADC_util.h> // Include to use analog shield.
int resetPin = 8; // this pin resets the track/hold state
int detPin = 9; // track/hold pin
const int readPin = A9; // ADC0
const int readPin2 = A2; // ADC1
ADC *adc = new ADC(); // adc object;
void setup()
{
Serial.begin(115200); // Serial port setup
pinMode(resetPin, OUTPUT); // Logic Setup for PHIC control
pinMode(detPin, OUTPUT);
digitalWrite(resetPin,HIGH); // Set PHIC to non-track/non-hold state
digitalWrite(detPin,HIGH);
delay(1);
}
/* data - variable to hold the measurement
* totalcnts - total number of events counted.
* Asize - spectrum number of channels. 512 points or less due to memory restrictions on the UNO.
* scale - makes the ADC maximum values no more than the array size
* spec - array variable holding the spectrum
* cutoff - the lower level noise floor. Peaks with ADC values above this are recorded.
*
* currentmillis,previousmillis, cntr - sets up the output timer to determine when to print to serial port
*
*/
unsigned int data = 0;
long totalcnts = 0;
int Asize = 512;
int scale = 32768/Asize;
int spec[512] = {};
int cutoff = 32850; // nominal lower level cutoff.
long currentmillis = 0;
long previousmillis = 0;
long cntr = 0;
void loop() {
// set pins to low to set PHIC to tracking
digitalWrite(resetPin,LOW);
digitalWrite(detPin,LOW);
delayMicroseconds(1);
// DAS analog read the peak and hold
const int readPin = 14; // ADC0 data = analog.read(0);
// if its above cutoff, indicating a peak is present, measure the peak
if (data > cutoff){
// Set tracking to off to avoid a later event distorting the current event's measurement.
digitalWrite(detPin,HIGH);
// wait 45 us (settling time)
delayMicroseconds(45);
// Average 5 measurements
pinMode(0)/5+analog.read(0)/5+analog.read(0)/5+analog.read(0)/5+analog.read(0)/5;
delayMicroseconds(5);
// Begin reset of the PHIC
// this will continue while other things are happening,
// reducing the total mount of time to wait for the reset.
digitalWrite(resetPin,HIGH);
// find out where in the pulse height diagram to put it (Eqn 1)
// The "2" is essenitally a software adjustable gain.
// Make sure the array index chosen is >=0 and <512, if so record the event and increment the counter.
int loc = floor(((data - 32768)*2/scale));
if (loc >= 0 & loc <512){
spec[loc] = spec[loc]+1;
cntr = cntr+1;
totalcnts = totalcnts+1;
}
// wait 10 us more to ensure the PHIC is fully reset.
delayMicroseconds(10);
// after event, decide if its time to write data.
// It is placed in the event recording IF statement to speed up the number of DAS reads on the PHIC per second.
currentmillis = millis();
if (currentmillis - previousmillis > 10000 || cntr > 1000){
for (int i = 0; i < Asize; i++){
// use serial.println for the serial plotter
Serial.print(((spec[i])));
Serial.print(" ");
};
// Wait for the 512 points to finish printing to the serial port.
Serial.flush();
// Print ancillary data followed by a delimiter of -1, then wait again for it to complete the operation.
// This is a good place to print things like the temperature, GPS coordinates, or the exposure time.
Serial.println();
Serial.println(currentmillis);
for (int i=0;i<3;i++){Serial.println(-1);}
Serial.flush();
// reset counters and timer
cntr = 0;
previousmillis = millis();
}
}
}