Commit de23a470 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Arduino: Add ADC driver

parent 7588f9c2
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
#ifndef ADC_H
#define ADC_H

class AVRADC {
	private:
		AVRADC(AVRADC const &copy);

	public:
		AVRADC() {}

		int16_t getTemp_mdegC(int16_t offset = 205);
		uint16_t getVCC_mV();
};

extern AVRADC adc;

#endif
+8 −0
Original line number Diff line number Diff line
@@ -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)
+4 −0
Original line number Diff line number Diff line
@@ -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
+76 −0
Original line number Diff line number Diff line
#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;