From dd42aebb16d297fbace1cab1155c1ff03eec981a Mon Sep 17 00:00:00 2001 From: BlackMark Date: Mon, 6 Apr 2020 19:43:32 +0200 Subject: [PATCH] Make adc sampling interrupt driven --- fantemp/adc | 2 +- fantemp/controller.cpp | 36 ++++++++++++++++++++++++++++-------- fantemp/controller.hpp | 9 +++++++-- fantemp/terminal.hpp | 12 ++++++++++-- fantemp/thermistor.hpp | 11 ----------- 5 files changed, 46 insertions(+), 24 deletions(-) diff --git a/fantemp/adc b/fantemp/adc index 5d38b97..7fe32b9 160000 --- a/fantemp/adc +++ b/fantemp/adc @@ -1 +1 @@ -Subproject commit 5d38b97254e271e3e0fb48739a927be6eae26a7f +Subproject commit 7fe32b9717285aef6c264fb294f1d37f91075d1c diff --git a/fantemp/controller.cpp b/fantemp/controller.cpp index 06977d8..46f02f2 100644 --- a/fantemp/controller.cpp +++ b/fantemp/controller.cpp @@ -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(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(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; + } } diff --git a/fantemp/controller.hpp b/fantemp/controller.hpp index a4bb661..bdd1de4 100644 --- a/fantemp/controller.hpp +++ b/fantemp/controller.hpp @@ -20,12 +20,17 @@ class Controller { static uint8_t mapTemperature(double temperature); private: - using adc_conf = adc::Config; + using adc_conf = adc::Config; static adc::Adc 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 static T clamp(double value, T lower, T upper) diff --git a/fantemp/terminal.hpp b/fantemp/terminal.hpp index 83b0e55..77d00e6 100644 --- a/fantemp/terminal.hpp +++ b/fantemp/terminal.hpp @@ -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::m_inputSize = 0; template typename Terminal::State Terminal::m_state = State::NONE; + +template +uint16_t Terminal::m_monitorDelayCounter; diff --git a/fantemp/thermistor.hpp b/fantemp/thermistor.hpp index bb748a4..a542f7f 100644 --- a/fantemp/thermistor.hpp +++ b/fantemp/thermistor.hpp @@ -4,17 +4,6 @@ class Thermistor { public: - template - 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);