diff options
author | Daniel Friesel <derf@finalrewind.org> | 2020-03-18 22:01:06 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2020-03-18 22:01:06 +0100 |
commit | de23a47009bb301518417d097b3360253a01c635 (patch) | |
tree | efbe470365a62c52345b6d3fd100f338f3cf2ad7 | |
parent | 7588f9c2ada3f4b10586826ee95eb8795fb69729 (diff) |
Arduino: Add ADC driver
-rw-r--r-- | include/arch/arduino-nano/driver/adc.h | 17 | ||||
-rw-r--r-- | src/arch/arduino-nano-168/Makefile.inc | 8 | ||||
-rw-r--r-- | src/arch/arduino-nano/Makefile.inc | 4 | ||||
-rw-r--r-- | src/arch/arduino-nano/driver/adc.cc | 76 |
4 files changed, 105 insertions, 0 deletions
diff --git a/include/arch/arduino-nano/driver/adc.h b/include/arch/arduino-nano/driver/adc.h new file mode 100644 index 0000000..4af64b8 --- /dev/null +++ b/include/arch/arduino-nano/driver/adc.h @@ -0,0 +1,17 @@ +#ifndef ADC_H +#define ADC_H + +class AVRADC { + private: + AVRADC(AVRADC const ©); + + public: + AVRADC() {} + + int16_t getTemp_mdegC(int16_t offset = 205); + uint16_t getVCC_mV(); +}; + +extern AVRADC adc; + +#endif diff --git a/src/arch/arduino-nano-168/Makefile.inc b/src/arch/arduino-nano-168/Makefile.inc index f57914e..70392e1 100644 --- a/src/arch/arduino-nano-168/Makefile.inc +++ b/src/arch/arduino-nano-168/Makefile.inc @@ -37,6 +37,10 @@ else ifneq ($(findstring i2c,${arch_drivers}), ) CXX_TARGETS += src/arch/arduino-nano/driver/i2c.cc endif +ifneq ($(findstring adc,${arch_drivers}), ) + CXX_TARGETS += src/arch/arduino-nano/driver/adc.cc +endif + ifneq ($(findstring spi,${arch_drivers}), ) CXX_TARGETS += src/arch/arduino-nano/driver/spi.cc endif @@ -53,6 +57,10 @@ ifneq ($(findstring counter,${arch_drivers}), ) CXX_TARGETS += src/arch/arduino-nano/driver/counter.cc endif +ifneq ($(findstring neopixel,${arch_drivers}), ) + CXX_TARGETS += src/arch/arduino-nano/driver/neopixel.cc +endif + ifeq (${cpu_freq}, 16000000) uart_baud = 57600 else ifeq (${cpu_freq}, 8000000) diff --git a/src/arch/arduino-nano/Makefile.inc b/src/arch/arduino-nano/Makefile.inc index ebc77ea..a664a30 100644 --- a/src/arch/arduino-nano/Makefile.inc +++ b/src/arch/arduino-nano/Makefile.inc @@ -37,6 +37,10 @@ else ifneq ($(findstring i2c,${arch_drivers}), ) CXX_TARGETS += src/arch/arduino-nano/driver/i2c.cc endif +ifneq ($(findstring adc,${arch_drivers}), ) + CXX_TARGETS += src/arch/arduino-nano/driver/adc.cc +endif + ifneq ($(findstring spi,${arch_drivers}), ) CXX_TARGETS += src/arch/arduino-nano/driver/spi.cc endif diff --git a/src/arch/arduino-nano/driver/adc.cc b/src/arch/arduino-nano/driver/adc.cc new file mode 100644 index 0000000..1583b15 --- /dev/null +++ b/src/arch/arduino-nano/driver/adc.cc @@ -0,0 +1,76 @@ +#include <avr/io.h> + +#include "arch.h" +#include "driver/adc.h" + +int16_t AVRADC::getTemp_mdegC(int16_t offset) +{ + // Measure temperature probe with 1.1V bandgap reference + ADMUX = _BV(REFS1) | _BV(REFS0) | 0x08; + + // 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 for conversion to complete + while (ADCSRA & _BV(ADSC)) ; + + // typical values: 242 mV @ -45 degC + // typical values: 314 mV @ +25 degC + // typical values: 380 mV @ +85 degC + // slope: 0.9090.. degC / mV at 25 .. 85 degC + // -> approx. 286.5 mV @ 0 degC / approx -260.45 degC @ 0 mV + // -> T[degC] = ADC[mV] * 0.91 - 261 + // -> T[mdegC] = ADC[mV] * 91 - 26100 + // slope: 0.9722.. mV / degC at -45 .. 25 degC + // slope: 0.942 mV / degC at -45 .. 85 degC + uint8_t adcr_l = ADCL; + uint8_t adcr_h = ADCH; + uint16_t adcr = adcr_l + (adcr_h << 8); + uint16_t vadc = 1100L * adcr / 1023L; + + // adjust for chip-specific variations + vadc += offset; + + int16_t temp_mdegc = vadc * 91 - 26100L; + + // Disable ADC + ADCSRA &= ~_BV(ADEN); + + return temp_mdegc; +} + +uint16_t AVRADC::getVCC_mV() +{ + // Measure internal 1.1V bandgap using VCC as reference + ADMUX = _BV(REFS0) | 0x0e; + + // 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 for conversion to complete + while (ADCSRA & _BV(ADSC)) ; + + uint8_t adcr_l = ADCL; + uint8_t adcr_h = ADCH; + uint16_t adcr = adcr_l + (adcr_h << 8); + uint16_t vcc = 1100L * 1023 / adcr; + + // Disable ADC + ADCSRA &= ~_BV(ADEN); + + return vcc; +} + +AVRADC adc; |