Make adc sampling interrupt driven
This commit is contained in:
parent
8db7bde6e5
commit
dd42aebb16
@ -1 +1 @@
|
||||
Subproject commit 5d38b97254e271e3e0fb48739a927be6eae26a7f
|
||||
Subproject commit 7fe32b9717285aef6c264fb294f1d37f91075d1c
|
@ -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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user