Adc is an interactive command line program that demonstrates control of an Analog-to-Digital Converter from pins PC0 through PC7 on an ATmega328p.
Arduino Uno is marked as A0 though A5, which is sometimes confused as PA0. The ADMUX register is set to 0 when selecting ADC channel 0. The analog channel has nothing to do with the digital pin number used by the Wiring. The pin used by ADC channel 0 has been assigned the number 14 for the digital Wiring functions (used with pinMod, digitalRead...), however for analogRead the ADC channel number is used.
A map of calibration valuses in EEPROM.
function type ee_addr:
id UINT16 30
ref_extern_avcc UINT32 32
ref_intern_1v1 UINT32 36
The AVCC pin is used to power the analog to digital converter and is also selected as a reference. On RPUlux the AVCC pin is powered by a switchmode supply that can be measured to use as a calibrated reference.
The internal 1V1 bandgap is not trimmed by the manufacturer, so it needs to be measured. However, once it is known it is a better reference than AVCC.
Note: calibration is new in this example, and may have problems. The EEPROM needs to have the measured values of the references.
With a serial port connection (see BOOTLOAD_PORT in Makefile) and optiboot installed on the RPUlux run 'make bootload' and it should compile and then flash the MCU.
sudo apt-get install make git gcc-avr binutils-avr gdb-avr avr-libc avrdude
git clone https://github.com/epccs/RPUlux/
cd /RPUlux/Adc
make bootload
...
avrdude done. Thank you.
Now connect with picocom (or ilk).
#exit is C-a, C-x
picocom -b 38400 /dev/ttyUSB0
or log the terminal session
script -f -c "picocom -b 38400 /dev/ttyUSB0" stuff.log
Commands are interactive over the serial interface at 38400 baud rate. The echo will start after the second character of a new line.
rpu_address is taken from the I2C address 0x29 (e.g. get_Rpu_address() which is included form ../lib/rpu_mgr.h). The value of rpu_address is used as a character in a string, which means don't use a null value (C strings are null terminated) as an adddress. The ASCII value for '1' (0x31) is easy and looks nice, though I fear it will cause some confusion when it is discovered that the actual address value is 49.
Commands and their arguments follow.
identify
/1/id?
{"id":{"name":"Adc","desc":"RPUlux (17323^0) Board /w atmega328p","avr-gcc":"5.4.0"}}
Analog-to-Digital Converter reading from up to 5 ADMUX channels. The reading repeats every 60 Seconds until the Rx buffer gets a character. On RPUlux channel 7 is the input voltage (PWR_V), channel 6 is the input current (PWR_I), channel 3 is a voltage divider on the channel 2 input, channel 2, 1, and channel 0 inputs can read up to 3.5V (higher voltages are blocked by a level shift). Note channel 4 and 5 are used for I2C on RPUlux.
/1/analog? 6,7
{"PWR_I":"0.000","PWR_V":"12.51"}
/1/analog? 0,1,2,3
{"ADC0":"1.38","ADC1":"2.83","ADC2":"0.72","ADC3":"0.61"}
/1/analog? 4,5
{"ADC4":"SDA","ADC5":"SCL"}
Values are from the SelfTest harness with a red LED on. PWR_I is scaled so it will need more current to get a reading.
The value reported is based on the avcc referance value which is saved in EEPROM, see bellow.
Calibrate the AVCC reference in microvolts.
/1/avcc 5006500
# do this with the SelfTest
Set the 1V1 internal bandgap reference in microvolts.
/1/onevone 1100000
# do this with the SelfTest
The SelfTest will calculate this value when it is ran based on the AVCC value compiled into source.
Save the reference in static memory to EEPROM.
/1/reftoee
# do this with the SelfTest
Load the reference from EEPROM into static memory.
/1/reffrmee
{"REF":{"extern_avcc":"5.0065","intern_1v1":"1.0733",}}