mirror of
https://github.com/sigmasternchen/dosimeter-arduino
synced 2025-03-15 17:48:53 +00:00
103 lines
2.1 KiB
C++
103 lines
2.1 KiB
C++
#include "dosimeter.h"
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include <ESP8266TimerInterrupt.h>
|
|
|
|
DosimeterType Dosimeter;
|
|
|
|
static float getCalibrationFactor(int type) {
|
|
switch(type) {
|
|
case J305:
|
|
case M4011:
|
|
return 0.0065;
|
|
break;
|
|
default:
|
|
return NAN;
|
|
}
|
|
}
|
|
|
|
int type;
|
|
volatile int buckets[BUCKETS_PER_MINUTE] = {0};
|
|
int last = 0;
|
|
bool valid = false;
|
|
bool measureDose = false;
|
|
volatile float dose = 0;
|
|
|
|
ESP8266Timer timer;
|
|
|
|
static inline void clearISR() {
|
|
unsigned long gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
|
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
|
|
}
|
|
|
|
static void ICACHE_RAM_ATTR geigerISR() {
|
|
int next = (millis() / BUCKET_WIDTH_IN_MS) % BUCKETS_PER_MINUTE;
|
|
|
|
if (last != next) {
|
|
for (int i = (last + 1) % BUCKETS_PER_MINUTE; i != next; i = (i + 1) % BUCKETS_PER_MINUTE) {
|
|
buckets[i] = 0;
|
|
}
|
|
|
|
buckets[next] = 1;
|
|
last = next;
|
|
} else {
|
|
buckets[next]++;
|
|
}
|
|
|
|
clearISR();
|
|
}
|
|
|
|
// timerISR gets called every minute
|
|
static void ICACHE_RAM_ATTR timerISR() {
|
|
if (measureDose && valid) {
|
|
dose += Dosimeter.getEquivalentDoseRate() / 60;
|
|
}
|
|
}
|
|
|
|
void DosimeterType::begin(int pin, int _type) {
|
|
type = _type;
|
|
|
|
pinMode(pin, INPUT);
|
|
attachInterrupt(digitalPinToInterrupt(pin), geigerISR, RISING);
|
|
|
|
timer.attachInterruptInterval(60l * 1000 * 1000, timerISR);
|
|
}
|
|
|
|
int DosimeterType::getCPM() {
|
|
int result = 0;
|
|
for (int i = 0; i < BUCKETS_PER_MINUTE; i++) {
|
|
result += buckets[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
float DosimeterType::getEquivalentDoseRate() {
|
|
return getCPM() * getCalibrationFactor(type);
|
|
}
|
|
|
|
float DosimeterType::getEquivalentDose() {
|
|
if (measureDose) {
|
|
return dose;
|
|
} else {
|
|
return NAN;
|
|
}
|
|
}
|
|
|
|
bool DosimeterType::isValid() {
|
|
if (valid) {
|
|
return true;
|
|
} else {
|
|
valid = millis() > (60l * 1000);
|
|
return valid;
|
|
}
|
|
}
|
|
|
|
void DosimeterType::startRecording() {
|
|
dose = 0;
|
|
measureDose = true;
|
|
}
|
|
|
|
void DosimeterType::stopRecording() {
|
|
measureDose = false;
|
|
}
|