ARDUINO IDE: INPUT/OUTPUT

INTRODUCTION
Arduino microcontrollers have plenty of I/O pins, some of which have an “analog” capability. Although Arduino’s function pinMode() sets the pins as inputs or outputs, neither do they always need to be set, nor they will always work as we expect them to. The aim of this tutorial is to clarify the use and behavior of I/O pins on 8bit AVR Arduino boards, such as Dasduino Core, Dasduino Lite, Arduino Uno, Mega, etc.
INITIAL STATE
When starting Arduino, all pins are set to INPUT. As an INPUT, the pins are in a high impedance state, which prevents short circuits. If we would read the state of these pins, it would not be stable, i.e. the pin would float between LOW and HIGH. More about that phenomenon in the tutorial about pull-up resistors.
An exception is the digital pin13, which is defined as an OUTPUT. The reason for it is the fact that Arduino starts the bootloader program at each startup, whose purpose is listening of serial pins in order to registrate the new code in PROGMEM. Try to reset the Dasduino, and you will notice that the orange LED on the 13th pin has blinked. Upon completion, pin13 returns to INPUT state and you can continue using it as every other I/O pin.
INPUT
INPUT is each pin defined to read the input state, e.g. photo-resistor, push-button, potentiometer and some sensors. The state of pin is determined in a way that microcontroller reads the voltage on the pin. There are analog and digital inputs. Analog inputs are, unlike digital ones, connected to a multiplexer, and each of them to an A/D converter.
analogRead() by the reference voltage gives 32bit values (0-1023). The default value of the reference voltage is 5V. It means that, if the microcontroller charges the voltage of 0V, it will assign the analog value 0, while 1023 indicates 5V. For other values, proportional to that. We can assign the reference voltage ourselves, by bringing it to aref Arduino pin, ofcourse, under the assumption that it is not greater than the maximum the microcontroller can take (5V).
digitalRead() defines every voltage above 3V (for 5V boards) as HIGH, and every one below it as LOW. NOTE: the practice is to define pins as HIGH/LOW, even though they will work properly as 1/0 (as shown by the Serial Monitor) or true/false.
pinMode() can be used to define pins as INPUT, but it is good to bear in mind that:
1. pinMode() defines pins as digital, not analog inputs.
2. when analogRead() is called upon, the pin automatically reconfigures to an input pin
Regardless of the above, the reccomendation is to use the pinMode() while defining input pins, because of the transparency of the code. The code will be more clear by knowing which pins we use and in which way.
An example:
int
ulaz = A0;
void
setup
() {
pinMode
(ulaz,
INPUT
);
// not necessary
Serial.begin(9600);
// starting serial communication
}
void
loop
() {
int
digOcitanje =
digitalRead
(ulaz);
// saving digital reading of the pin A0 in the dig0citanje variable
int
anaOcitanje =
analogRead
(ulaz);
// saving analog reading of the pin A0 in the an0citanje variable
// printing out the read values in Serial Monitor
Serial.print(
"Digitalno ocitanje: "
);
Serial.println(digOcitanje);
Serial.print(
"Analogno ocitanje: "
);
Serial.println(anaOcitanje);
delay
(100);
}
If you have a potentiometer at hand, connect it according to the picture below, change the position and monitor changes in Serial Monitor.
OUTPUT
OUTPUT defines output pins, i.e. output voltage. As with inputs, we distinguish digital and “analog” (PWM) pins. Examples of components and modules used as OUTPUT : LED diodes, buzzer, relays, engines, etc.
analogWrite() works with pins supporting the PWM (Puls-Width Modulation). On the Croduino, those are digital pins 3, 5, 6, 9, 10 i 11, and they are marked with an apostrophe (‘). Check the pin-out. As with analogRead (), analogWrite () sets the pin as OUTPUT. The value we can set with analogWrite is 8bit (0-255).
digitalWrite “sends” 5V (HIGH) or 0V (LOW) to the pin.
Example:
We connect the cathode(shorter pin) of the LED diode through 330ohm resistor to the gnd, and the anode(longer pin) to the digital pin(PWM)9 as shown in the picture below
int
led = 9;
// LED on the PWM pin 9
int
pwnVrijednost = 153;
// defining the pwm value (between 0 and 255)
// 0 = 0V; 255 = 5V and proportionally
void
setup
() {
pinMode
(led,
OUTPUT
);
// defining LED as OUTPUT
}
void
loop
() {
digitalWrite
(led,
HIGH
);
// the first argument is the pin, the second LOW/HIGH; turning the LED(5V) on
delay
(500);
// we stop the program at 500ms = 0.5sek
digitalWrite
(led,
LOW
);
// turning the LED(0V) off
delay
(1000);
analogWrite
(led, pwmVrijednost);
// the first argument is the pin, the second a value between 0 i 255, turning the LED(3v) on
delay
(500);
analogWrite
(led, 0);
// turning the LED(0V) off
delay
(1000);
}
NOTE(in the example above): 153(PWM) is equivalent to a voltage of 3V. We get this from the ratio x / 5V = 153/255. So, x = 153 * 5V / 255 = 3V. * (we know that 0V = 0 (PWM) and that 5V = 255 (PWM))
HOW TO CONVERT ANALOGUE READING TO PWM
In the end we will show how to turn analogue readings(0-1023) to PWM(0-255). From the example with the potentiometer and LED diode we used for testing INPUT/OUTPUT, we will read the potentiometer status, and depending on it, amplify/decrease the light of the LED. Although, at first glance, it looks very simple and easy, the problem may arise due to the range. Let’s see in the example below, which IS NOT CORRECT:
INTERESTING!
Do you know that in one line of code you can change OUTPUT pin status and use digitalRead () with OUTPUT pins?
The first thing you notice is how the digitalRead() is used to define pin13’s status. Does it mean that the pin is used as INPUT and OUTPUT at the same time? No. Actually, it seems that, when calling a digitalRead () to a pin defined as OUTPUT, we read the status of the PORTX register within the ATmega microcontroller.
There are several such registers inside the microcontroller (x represents “B, C, D”), and they contain the current pin status. In particular, pin13 is located at PORTB. When the pin is defined as OUTPUT, digitalWrite () communicates with PORT to change it, i.e. enable HIGH or LOW. When calling digitalRead (), the PORTx register changes to the current value, if digitalWrite () is set to LOW digitalRead (), it will return LOW and vice versa. Interesting!
“!” still needs to be explained. We call it NOT operator or bang, and in fact, it is the fastest way to invert the value. It converts HIGH to LOW, and vice versa.
In the end, try out the code:
void
setup
() {
pinMode
(13,
OUTPUT
);
// we use the orange LED on the Croduino board
}
void
loop
() {
digitalWrite
(13, !
digitalRead
(13));
delay
(1000);
}