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,20 +7,29 @@ double Controller::m_adcSample;
double Controller::m_resistance; double Controller::m_resistance;
double Controller::m_temperature; double Controller::m_temperature;
uint8_t Controller::m_fanSpeed; uint8_t Controller::m_fanSpeed;
volatile uint32_t Controller::m_adcSampleSum;
volatile bool Controller::m_adcSampleReady = false;
void Controller::init() void Controller::init()
{ {
m_adcPin.init(); m_adcPin.init(sampleCallback);
pwm::init(); pwm::init();
pwm::setDuty(100); pwm::setDuty(100);
} }
void Controller::callback() void Controller::callback()
{ {
sample(); 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); m_fanSpeed = mapTemperature(m_temperature);
pwm::setDuty(m_fanSpeed); pwm::setDuty(m_fanSpeed);
} }
}
uint8_t Controller::mapTemperature(double temperature) uint8_t Controller::mapTemperature(double temperature)
{ {
@ -35,9 +44,20 @@ uint8_t Controller::mapTemperature(double temperature)
return clamp<uint8_t>(fanSpeed, 0, 100); 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); static uint32_t s_sampleSum = 0;
m_resistance = m_thermistor.getResistance(m_adcSample); static auto s_sampleCounter = NUM_ADC_SAMPLES;
m_temperature = m_thermistor.getTemperature(m_resistance);
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); static uint8_t mapTemperature(double temperature);
private: 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 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 Thermistor m_thermistor;
static void sample(); static void sampleCallback(const uint16_t &adcSample);
template <typename T> template <typename T>
static T clamp(double value, T lower, T upper) static T clamp(double value, T lower, T upper)

View File

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