In one of the earlier logs PORT was explained, but that can only be used for digital I/O, meaning, it can turn outputs on or off, or detect if an input is on or off. The actual pin number for digital I/O consists of a PORT letter followed by a pin (or bit #) in that PORT. Every non-power related leg (like VDD and GND) on the ATtiny is linked to one of those PORTS, but that is usually not the only function of that leg.
The Analog to Digital Converter (ADC) is a great feature on the MCU to measure input voltage. Instead of using PORT to link a the digital I/O to the leg, it uses channels. The ATtiny1616 has 12 input channels (AIN0 to AIN11) on two ADC’s (ADC0 and ADC1). The location of these input channels (we are going to use ADC0 only) are as follows:
// _____ // VDD 1|* |20 GND // (nSS) (AIN4) PA4 0~ 2| |19 16~ PA3 (AIN3)(SCK)(EXTCLK) // (AIN5) PA5 1~ 3| |18 15 PA2 (AIN2)(MISO) // (DAC) (AIN6) PA6 2 4| |17 14 PA1 (AIN1)(MOSI) // (AIN7) PA7 3 5| |16 17 PA0 (AIN0/nRESET/UPDI) // (AIN8) PB5 4 6| |15 13 PC3 // (AIN9) PB4 5 7| |14 12 PC2 // (RXD) (TOSC1) PB3 6 8| |13 11~ PC1 (PWM only on 1-series) // (TXD) (TOSC2) PB2 7~ 9| |12 10~ PC0 (PWM only on 1-series) // (SDA) (AIN10) PB1 8~ 10|_____|11 9~ PB0 (AIN11)(SCL)
So as you can see a leg could have be a digital pin (for example PA4) and an analog input (AIN4). Like the digital I/O we are going to tell Arduino which pin# is linked to each analog channel as follows in pins_arduino.h:
#define digitalPinToAnalogInput(p) ((p<6)?(p+4):(p==17?0:((p>13)?(p-13):((p==8)?10:(p==9?11:NOT_A_PIN)))))
Big thanks to Spence Konde! He helped enormous in creating all the pre-processor macros. But newbies, like me, are probably wondering what this line above is doing.
We are all familiar with an if statement, for example:
if(p < 6) {
p = p + 4;
} else {
P = NOT_A_PIN;
}
There is actually a shorter method writing the same if statement above, for example as follows:
p = (p<6)?(p+4):NOT_A_PIN;
Using this same method for the macro above will result in the following if statement:
if(p < 6) {
digitalPinToAnalogInput(p) = p + 4;
} elseif (p == 17 {
digitalPinToAnalogInput(p) = 0;
} elseif (p > 13 {
digitalPinToAnalogInput(p) = p-13;
} elseif (p == 8 {
digitalPinToAnalogInput(p) = 10;
} elseif (p == 9 {
digitalPinToAnalogInput(p) = 11;
else {
NOT_A_PIN
}
With “p” being the Arduino pin number, we can now determine which channel belongs to that pin with the macro above. For example when p=5 (leg #7), digitalPinToAnalogInput(p) will be 5 + 4, resulting in channel 9.
You can just read the voltage on the input pin by entering the following in Arduino:
analogRead(5) // reading the analog input on channel 9.
But most Arduino’s have a dedicated section for analog inputs, for example on the Arduino UNO A0 up to A5 are used as analog inputs. In order to use these A0, A1 etc numbers we have to add these with macros to the pins_arduino.h as well as follows:
#define PIN_A0 (17)
#define PIN_A1 (14)
#define PIN_A2 (15)
#define PIN_A3 (16)
#define PIN_A4 (0)
#define PIN_A5 (1)
#define PIN_A6 (2)
#define PIN_A7 (3)
#define PIN_A8 (4)
#define PIN_A9 (5)
#define PIN_A10 (10)
#define PIN_A11 (11)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
static const uint8_t A8 = PIN_A8;
static const uint8_t A9 = PIN_A9;
static const uint8_t A10 = PIN_A10;
static const uint8_t A11 = PIN_A11;
Instead of only using the pin#, now analogRead(A9) can be used as well, resulting with the same readings.
In the next log I will explain the internal voltages which can be used to get a reliable analog input reading.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.