Created
July 16, 2019 17:54
-
-
Save goebish/e18ce331e43442a6719751304b8905b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SPI.h> | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_PCD8544.h> | |
#include <CircularBuffer.h> // https://github.com/abouvier/CircularBuffer/archive/master.zip | |
#include <MovingAverage.h> // https://github.com/abouvier/MovingAverage/archive/master.zip | |
#include <TinyTimer.h> // https://github.com/abouvier/TinyTimer/archive/master.zip | |
#define LED_PIN 4 | |
#define BUZZER_PIN 9 // do not change, driven by hardware counter | |
#define GEIGER_PIN 2 // must be D2 or D3 | |
#define VBAT_PIN A7 | |
#define VTUBE_PIN A6 // HV+ --> 10M ohm --> VTUBE_PIN --> 47k ohm --> GND | |
#define VTUBE_MULT 192 | |
// SPI PCD8544 | |
#define PCD8544_CLK 13 // do not change, hardware SPI SCK | |
#define PCD8544_DIN 11 // do not change, hardware SPI MOSI | |
#define PCD8544_DC 6 | |
#define PCD8544_CE 7 | |
#define PCD8544_RST 8 | |
#define PCD8544_BL 5 // backlight, must be D5 or D6 to use PWM (TIMER1 & TIMER2 are reused for other stuffs) | |
#define CYCLE_SIZE 60 | |
#define BAT_AVERAGE 10 | |
#define PRINT_DELAY 250 | |
volatile uint16_t cps; | |
uint16_t last_cps; | |
MovingAverage<volatile uint16_t, CYCLE_SIZE> cpm; | |
MovingAverage<uint16_t, BAT_AVERAGE> vsense[3]; | |
TinyTimer<millis> timers[2]; | |
Adafruit_PCD8544 display(PCD8544_DC, PCD8544_CE, PCD8544_RST); | |
enum { | |
VBATTERY, | |
VTUBE, | |
VCC | |
}; | |
//// | |
// setup one-shot pulse generator for buzzer, use TIMER1 | |
void osp_setup() | |
{ | |
cli(); | |
TCCR1B = 0; // halt counter | |
TCNT1 = 0; // start counting at bottom | |
ICR1 = 0; // TOP = 0 | |
TCCR1A = (1 << COM1A0) | (1 << COM1A1) | (1 << WGM11); // OC1A=Set on Match, clear on BOTTOM. Mode 14 Fast PWM | |
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10); // prescaler = 1 (Max ~4mS); Start counting now | |
OCR1A = 64000; // 0x7fff = 2ms pulse @16MHz, larger = shorter | |
DDRB = (1 << 1); // Set pin to output (OC1A = PB1 = Arduino D9) | |
sei(); | |
} | |
// Test if there is a pulse still in progress | |
#define OSP_INPROGRESS() (TCNT1>0) | |
// trigger one-shot pulse | |
#define OSP_FIRE() (TCNT1 = OCR1A - 1) | |
// GM tube tick interrupt | |
void geiger_isr() | |
{ | |
cps++; | |
// tick buzzer | |
if (!OSP_INPROGRESS()) { | |
OSP_FIRE(); | |
} | |
} | |
void buffer() | |
{ | |
cli(); | |
last_cps = cps; | |
cps = 0; | |
sei(); | |
cpm.push(last_cps); | |
vsense[VBATTERY].push(analogRead(VBAT_PIN)); | |
vsense[VTUBE].push(analogRead(VTUBE_PIN)); | |
vsense[VCC].push(readVcc()); | |
} | |
void printdigit(uint8_t val) | |
{ | |
if(val<10) | |
display.print("0"); | |
display.print(val); | |
} | |
long readVcc() | |
{ | |
long voltage = 0; | |
uint16_t wADC; | |
// Read 1.1V reference against AVcc | |
// set the reference to Vcc and the measurement to the internal 1.1V reference | |
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
ADCSRA |= _BV(ADEN); // enable the ADC | |
delay(20); // Wait for Vref to settle | |
ADCSRA |= _BV(ADSC); // Start conversion | |
while (bit_is_set(ADCSRA, ADSC)); // measuring | |
wADC = ADCW; // Reading register "ADCW" takes care of how to read ADCL first and ADCH then. | |
voltage = 1127000L / wADC; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 | |
return voltage; // Vcc in millivolts | |
} | |
#define AVG_VCC (vsense[VCC].average()/1000.0f) | |
void refresh_header() | |
{ | |
display.setTextSize(1); | |
// main battery | |
display.setCursor(0, 0); | |
display.print(vsense[VBATTERY].average() * AVG_VCC / 1023.0f); | |
display.print("V"); | |
// tube voltage | |
display.setCursor(84 - 6 * 4, 0); | |
display.print((uint16_t)floor((vsense[VTUBE].average() * AVG_VCC / 1023.0f) * VTUBE_MULT)); | |
display.print("V"); | |
} | |
void refresh() | |
{ | |
display.clearDisplay(); | |
refresh_header(); | |
// CPM | |
display.setTextSize(2); | |
display.setCursor(0, 16); | |
uint32_t count = cpm.sum() * (60 / cpm.capacity()); | |
display.print(count); | |
if (count >= 1000) | |
display.setTextSize(1); | |
display.print(" CPM "); | |
// CPS | |
display.setTextSize(1); | |
display.setCursor(0, 32); | |
display.print(last_cps); | |
display.print(" CPS "); | |
// STS-5 CPM to µSievert/hour: | |
// CPM / 171 = uSv/h | |
// Sievert <-> Roentgen: | |
// 1 R = 0.00933 Sv; 1 Sv = 107.185 R | |
display.setTextSize(1); | |
display.setCursor(0, 40); | |
display.print(count / 171.0f); | |
display.print(" uSv/h "); | |
display.display(); | |
} | |
void setup() | |
{ | |
osp_setup(); | |
//encoder_setup(); | |
pinMode(LED_PIN, OUTPUT); | |
pinMode(GEIGER_PIN, INPUT_PULLUP); | |
pinMode(PCD8544_BL, OUTPUT); | |
analogWrite(PCD8544_BL, 127); | |
display.begin(40,4); // contrast, bias | |
display.setRotation(2); // 180°, header on top | |
refresh(); | |
attachInterrupt(digitalPinToInterrupt(GEIGER_PIN), geiger_isr, FALLING); | |
timers[1].init(refresh, PRINT_DELAY); | |
timers[0].init(buffer, 1000); | |
} | |
void loop() | |
{ | |
TinyTimer<millis>::update(timers); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment