From bf974ab871e3be2eabb46be61e1934b8237e16a8 Mon Sep 17 00:00:00 2001 From: Daniel Friesel <derf@finalrewind.org> Date: Tue, 21 Dec 2021 22:01:43 +0100 Subject: [PATCH] arduino nano adc: add getPin_mV function --- include/arch/arduino-nano/driver/adc.h | 1 + src/arch/arduino-nano/driver/adc.cc | 36 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/arch/arduino-nano/driver/adc.h b/include/arch/arduino-nano/driver/adc.h index 30ac338..c89f915 100644 --- a/include/arch/arduino-nano/driver/adc.h +++ b/include/arch/arduino-nano/driver/adc.h @@ -17,6 +17,7 @@ class AVRADC { int16_t getTemp_mdegC(int16_t offset = 205); uint16_t getVCC_mV(); + uint16_t getPin_mV(uint8_t pin, uint16_t avcc = 0); }; extern AVRADC adc; diff --git a/src/arch/arduino-nano/driver/adc.cc b/src/arch/arduino-nano/driver/adc.cc index 17cfc27..8f828a4 100644 --- a/src/arch/arduino-nano/driver/adc.cc +++ b/src/arch/arduino-nano/driver/adc.cc @@ -8,6 +8,42 @@ #include "arch.h" #include "driver/adc.h" +uint16_t AVRADC::getPin_mV(uint8_t pin, uint16_t avcc) +{ + if (avcc) { + // measure with AVCC reference + ADMUX = _BV(REFS0) | pin; + } else { + // measure with internal 1.1V bandgap refernce + ADMUX = _BV(REFS1) | _BV(REFS0) | pin; + } + + // Enable ADC with /64 prescaler + ADCSRA = _BV(ADEN) | _BV(ADPS2); + + // Wait for bandgap to stabilise (70us according to datasheet table 28-3) + arch.delay_ms(1); + + // Start conversion + ADCSRA |= _BV(ADSC); + + // wait until conversion is complete + while (ADCSRA & _BV(ADSC)) ; + + uint8_t adcr_l = ADCL; + uint8_t adcr_h = ADCH; + uint16_t adcr = adcr_l + (adcr_h << 8); + + // Disable ADC + ADCSRA &= ~_BV(ADEN); + + if (avcc) { + return (uint32_t)avcc * adcr / 1023L; + } else { + return 1100L * adcr / 1023L; + } +} + int16_t AVRADC::getTemp_mdegC(int16_t offset) { // Measure temperature probe with 1.1V bandgap reference -- GitLab