Files
OptoTest/OpticalChannelTester/OpticalCurrent.cpp

75 lines
2.4 KiB
C++

#include "OpticalCurrent.h"
#include "Config.h"
namespace {
struct AdcAccumulator {
uint64_t senseRaw = 0;
uint64_t vccRaw = 0;
uint64_t senseMillivolts = 0;
uint64_t vccMillivolts = 0;
uint32_t samples = 0;
uint32_t startedMs = 0;
};
AdcAccumulator accumulator;
void resetAccumulator(uint32_t now) {
accumulator = {};
accumulator.startedMs = now;
}
OpticalCurrentMeasurement finishMeasurement() {
const float senseAdcVoltage =
accumulator.senseMillivolts / (1000.0f * accumulator.samples);
const float vccAdcVoltage =
accumulator.vccMillivolts / (1000.0f * accumulator.samples);
const float senseVoltage = senseAdcVoltage * OPTICAL_DIVIDER_RATIO;
const float vccVoltage = vccAdcVoltage * OPTICAL_DIVIDER_RATIO;
const float resistorVoltage = vccVoltage - senseVoltage;
const float currentMa = resistorVoltage * 1000.0f / OPTICAL_SENSE_R;
return {
static_cast<uint16_t>(accumulator.senseRaw / accumulator.samples),
static_cast<uint16_t>(accumulator.vccRaw / accumulator.samples),
senseAdcVoltage, vccAdcVoltage, senseVoltage, vccVoltage,
currentMa > 0.0f ? currentMa : 0.0f
};
}
}
void optical_current_begin(void) {
analogReadResolution(12);
pinMode(GPIO_OPTICAL_CURRENT, INPUT);
pinMode(GPIO_OPTICAL_VCC, INPUT);
// Both 10k/10k dividers can present about 2.5 V to their ADC inputs.
analogSetPinAttenuation(GPIO_OPTICAL_CURRENT, ADC_11db);
analogSetPinAttenuation(GPIO_OPTICAL_VCC, ADC_11db);
resetAccumulator(0);
}
bool optical_current_poll(OpticalCurrentMeasurement &measurement) {
const uint32_t now = millis();
if (!accumulator.startedMs) resetAccumulator(now ? now : 1U);
accumulator.senseRaw += analogRead(GPIO_OPTICAL_CURRENT);
accumulator.senseMillivolts += analogReadMilliVolts(GPIO_OPTICAL_CURRENT);
accumulator.vccRaw += analogRead(GPIO_OPTICAL_VCC);
accumulator.vccMillivolts += analogReadMilliVolts(GPIO_OPTICAL_VCC);
++accumulator.samples;
if (now - accumulator.startedMs < OPTICAL_CURRENT_AVERAGING_MS) return false;
measurement = finishMeasurement();
resetAccumulator(now);
return true;
}
OpticalCurrentMeasurement optical_get_led_measurement(void) {
OpticalCurrentMeasurement measurement = {};
resetAccumulator(millis());
while (!optical_current_poll(measurement)) delay(1);
return measurement;
}
float optical_get_led_current_ma(void) {
return optical_get_led_measurement().currentMa;
}