Scaler addon for a variety of instruments -rough draft
Posted: 03 Aug 2024, 02:43
A while ago, I discovered that my trusty Bicron Surveyor M had blown three ICs during an unfortunate incident involving a damaged mono audio cable. This cable outputs a positive TTL signal directly from an MC14538BCP, which can be used to drive an external ratemeter or scaler. After replacing the ICs and fixing the device, I decided to create a scaler for it, as I felt something was "missing."
For fun, I developed a scaler that uses only the serial output to print results. Time intervals are set using A0-A5 (1s, 10s, 60s (1 min), 600s (10 minutes), 3600s (1 hour)). The timer counts down, and after the elapsed time, the scaler prints the total pulses collected, then displays the average number of pulses per second based on the time interval on the line below. This is great for observing small changes in background radiation. This code is the first step in a larger open project. If anyone wants to modify or use it, please feel free to do so.
Phase 2 will involve cleaning up this code and having it display the counts on either a large 8-digit 7-segment display or a large 20x4 or 128x64 LCD screen. The current sketch runs fine on an Arduino Uno but may benefit from being run on an Arduino Mega 2560 or Uno R4 (ARM-based), as these have more memory for use with a large segment display. The pulses are processed using Timer1, which can handle just over 65KCPS, more than enough for our purposes.
For fun, I developed a scaler that uses only the serial output to print results. Time intervals are set using A0-A5 (1s, 10s, 60s (1 min), 600s (10 minutes), 3600s (1 hour)). The timer counts down, and after the elapsed time, the scaler prints the total pulses collected, then displays the average number of pulses per second based on the time interval on the line below. This is great for observing small changes in background radiation. This code is the first step in a larger open project. If anyone wants to modify or use it, please feel free to do so.
Phase 2 will involve cleaning up this code and having it display the counts on either a large 8-digit 7-segment display or a large 20x4 or 128x64 LCD screen. The current sketch runs fine on an Arduino Uno but may benefit from being run on an Arduino Mega 2560 or Uno R4 (ARM-based), as these have more memory for use with a large segment display. The pulses are processed using Timer1, which can handle just over 65KCPS, more than enough for our purposes.
Code: Select all
#include <Arduino.h>
volatile unsigned long pulseCount = 0;
unsigned long previousMillis = 0;
unsigned long interval = 1000; // default interval of 1 second
unsigned long intervals[] = {1000, 10000, 60000, 100000, 360000, 3600000}; // 1s, 10s, 60s, 100s, 360s, 3600s
unsigned int selectedInterval = 0; // default to 1s interval
void setup() {
Serial.begin(9600);
// Initialize the analog pins for interval selection
for (int i = 0; i < 6; i++) {
pinMode(A0 + i, INPUT_PULLUP); // Use internal pull-up resistors
}
// Setup Timer1 to count external pulses on T1 (pin 5)
pinMode(5, INPUT);
// Clear Timer1 control and count registers
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
// Set Timer1 to normal mode (WGM12:0 = 0)
// Set the clock source to external pin T1 (rising edge)
// CS12:10 = 111 (external clock source on T1 pin, rising edge)
TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);
// Enable overflow interrupt for Timer1
TIMSK1 |= (1 << TOIE1);
Serial.println("Select interval using A0 to A5:");
Serial.println("A0: 1s");
Serial.println("A1: 10s");
Serial.println("A2: 60s");
Serial.println("A3: 100s");
Serial.println("A4: 360s");
Serial.println("A5: 3600s");
}
ISR(TIMER1_OVF_vect) {
// Timer1 overflow interrupt service routine
pulseCount += 65536; // Add the maximum value of Timer1 (16-bit)
}
void loop() {
// Check for interval selection from analog pins
for (int i = 0; i < 6; i++) {
if (analogRead(A0 + i) < 512) { // Button pressed (low)
selectedInterval = i;
interval = intervals[selectedInterval];
Serial.print("Selected interval: ");
Serial.print(interval / 1000);
Serial.println(" seconds");
delay(1000); // Debounce delay
}
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
noInterrupts();
unsigned long count = pulseCount + TCNT1;
pulseCount = 0;
TCNT1 = 0;
interrupts();
Serial.print("Elapsed time: ");
Serial.print(interval / 1000);
Serial.println(" seconds");
Serial.print("Total raw counts: ");
Serial.println(count);
Serial.print("Average counts per second: ");
Serial.println((float)count / (interval / 1000.0), 2);
// Reset count after 5 seconds
delay(5000);
}
}