Make adc sampling interrupt driven

This commit is contained in:
BlackMark 2020-04-06 19:43:32 +02:00
parent 8db7bde6e5
commit dd42aebb16
5 changed files with 46 additions and 24 deletions

@ -1 +1 @@
Subproject commit 5d38b97254e271e3e0fb48739a927be6eae26a7f
Subproject commit 7fe32b9717285aef6c264fb294f1d37f91075d1c

View File

@ -7,19 +7,28 @@ double Controller::m_adcSample;
double Controller::m_resistance;
double Controller::m_temperature;
uint8_t Controller::m_fanSpeed;
volatile uint32_t Controller::m_adcSampleSum;
volatile bool Controller::m_adcSampleReady = false;
void Controller::init()
{
m_adcPin.init();
m_adcPin.init(sampleCallback);
pwm::init();
pwm::setDuty(100);
}
void Controller::callback()
{
sample();
m_fanSpeed = mapTemperature(m_temperature);
pwm::setDuty(m_fanSpeed);
if (m_adcSampleReady) {
m_adcSample = static_cast<double>(m_adcSampleSum) / NUM_ADC_SAMPLES;
m_adcSampleReady = false;
m_resistance = m_thermistor.getResistance(m_adcSample);
m_temperature = m_thermistor.getTemperature(m_resistance);
m_fanSpeed = mapTemperature(m_temperature);
pwm::setDuty(m_fanSpeed);
}
}
uint8_t Controller::mapTemperature(double temperature)
@ -35,9 +44,20 @@ uint8_t Controller::mapTemperature(double temperature)
return clamp<uint8_t>(fanSpeed, 0, 100);
}
void Controller::sample()
void Controller::sampleCallback(const uint16_t &adcSample)
{
m_adcSample = m_thermistor.sampleAdc(m_adcPin, 1000);
m_resistance = m_thermistor.getResistance(m_adcSample);
m_temperature = m_thermistor.getTemperature(m_resistance);
static uint32_t s_sampleSum = 0;
static auto s_sampleCounter = NUM_ADC_SAMPLES;
s_sampleSum += adcSample;
if (--s_sampleCounter <= 0) {
if (!m_adcSampleReady) {
m_adcSampleSum = s_sampleSum;
m_adcSampleReady = true;
}
// else lose this sample, which happens during long running commands like "curve", but has no impact
s_sampleSum = 0;
s_sampleCounter = NUM_ADC_SAMPLES;
}
}

View File

@ -20,12 +20,17 @@ class Controller {
static uint8_t mapTemperature(double temperature);
private:
using adc_conf = adc::Config<adc::SingleMode>;
using adc_conf = adc::Config<adc::FreeRunningMode>;
static adc::Adc<adc_conf, io::P, io::P::C0> m_adcPin;
static constexpr auto NUM_ADC_SAMPLES = 1000;
static volatile uint32_t m_adcSampleSum;
static volatile bool m_adcSampleReady;
static Thermistor m_thermistor;
static void sample();
static void sampleCallback(const uint16_t &adcSample);
template <typename T>
static T clamp(double value, T lower, T upper)

View File

@ -19,7 +19,7 @@ GF(CURVE_CMD, "curve");
GF(MONITOR_CMD, "monitor");
GF(BOOTLOADER_CMD, "bootloader");
GF(VERSION_CMD, "version");
GF(VERSION, "1.1");
GF(VERSION, "1.2");
static inline bool substringEquals(const char *str, const ::detail::FlashString *flashStr, const size_t &size)
{
@ -99,14 +99,17 @@ class Terminal {
m_serial << F("$ ");
}
if (m_state == State::MONITOR)
if (m_state == State::MONITOR && --m_monitorDelayCounter == 0) {
showState();
m_monitorDelayCounter = MONITOR_DELAY;
}
}
private:
static constexpr auto INPUT_BUFFER_SIZE = 128;
static constexpr auto BACKSPACE = uint8_t{0x7f};
static constexpr auto CTRL_C = uint8_t{0x03};
static constexpr auto MONITOR_DELAY = 60000;
enum class State {
NONE,
@ -117,6 +120,7 @@ class Terminal {
static char m_inputBuffer[INPUT_BUFFER_SIZE];
static uint16_t m_inputSize;
static State m_state;
static uint16_t m_monitorDelayCounter;
static void parseInput()
{
@ -131,6 +135,7 @@ class Terminal {
printCurve();
} else if (substringEquals(m_inputBuffer, detail::MONITOR_CMD, m_inputSize)) {
m_state = State::MONITOR;
m_monitorDelayCounter = MONITOR_DELAY;
} else if (substringEquals(m_inputBuffer, detail::BOOTLOADER_CMD, m_inputSize)) {
handleBootloader();
} else if (substringEquals(m_inputBuffer, detail::VERSION_CMD, m_inputSize)) {
@ -216,3 +221,6 @@ uint16_t Terminal<Uart>::m_inputSize = 0;
template <class Uart>
typename Terminal<Uart>::State Terminal<Uart>::m_state = State::NONE;
template <class Uart>
uint16_t Terminal<Uart>::m_monitorDelayCounter;

View File

@ -4,17 +4,6 @@
class Thermistor {
public:
template <typename Adc>
static double sampleAdc(Adc &adcPin, uint16_t numSamples = 100)
{
double samples = 0;
for (uint16_t i = 0; i < numSamples; ++i)
samples += adcPin.read();
return samples / numSamples;
}
static double getResistance(double adcSample);
static double getTemperature(double resistance);