How to use Arduino's Digial IO pins

How to use Arduino's Digial IO pins

The Arduino board allows users to connect and interact with a variety of external devices. One of the key features of the Arduino board is the ability to set any digital pin as either an input or an output, depending on the user’s needs.

By configuring a pin as an input, the user can read signals from other devices and execute logic based on that input. Conversely, setting a pin as an output allows the user to control other devices by switching the state of the output pin from low to high.

While some pins on the Arduino board can be configured to support alternative functions such as analog input or various interfaces, this article will focus on setting pins as digital inputs or outputs on the Arduino Uno board. The code examples provided are applicable to other Arduino boards as well, but it is important to set the pin number based on the specific board being used.

To set a pin on the Arduino board as either an input or an output, the pinMode() function is used. This function takes in two arguments: the pin number and the pin mode. The pin mode can be set to either OUTPUT, INPUT, or INPUT_PULLUP. Setting the pin mode to OUTPUT configures the pin as an output, while INPUT or INPUT_PULLUP sets the pin as an input. By default, all pins are set as INPUT, which means that if a pin is not connected to any device, it will be in a floating state and can pick up random signals. If the INPUT_PULLUP mode is used, the internal pull-up resistor will be enabled, resulting in a stable high signal value unless a low signal is explicitly applied.

Note: Depending on the microcontroller used on your Arduino board, the pin may output or sink up to 40mA. This is generally enough to light up an LED, but it is important to remember to include a serial resistor in the circuit. However, it is not recommended to directly connect devices that consume more power, such as DC motors or relays. In such cases, it is advisable to use BJT or MOSFET transistors as switches.

To set the output pin signal as low or high, the digitalWrite(pin, value) function is used. This function requires two parameters: the pin number and the value to be set, which can be either HIGH (1) or LOW (0). If the pin is set as INPUT, writing a value of HIGH with this function will enable the internal pull-up resistor, while writing a value of LOW will disable it.

The digitalRead(pin) function is used to read the signal level from the pin, regardless of whether the pin is set as an input or output. This function requires only one parameter, which is the pin number. The returned value will be either HIGH or LOW, depending on the signal level detected by the pin.

The code below will make the built-in LED on the Arduino Uno board blink:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}
  • Line 2 sets Pin 13 as an output, which is connected to the built-in LED on the board.
  • Line 3 sets the default value of Pin 13 as low, which turns the LED off.
  • In the loop() function, the code will run continuously until the board is turned off.
  • Line 7 sets the state of Pin 13 to high, which turns the LED on.
  • Line 8 adds a delay of one second before proceeding to the next line.
  • Line 9 sets the state of Pin 13 to low, which turns the LED off.
  • Line 10 adds another one-second delay before the cycle begins again from line 7.

In the next example we’re using an external LED and a button with Arduino Uno. The LED is connected to pin 2 and the button is connected to pin 3. The button is used to toggle the LED on and off (Figure 1).

Example schematic.

Figure 1. External LED and Button schematic with Arduino Uno

The 1uF capacitor is optional, but it helps to smooth the fluctuation when the button is pressed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#define LED_PIN 2
#define BUTTON_PIN 3

volatile int prevButtonState = HIGH;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  int currentButtonState = digitalRead(BUTTON_PIN);
  if (prevButtonState != currentButtonState && currentButtonState == LOW) {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
  }
  prevButtonState = currentButtonState;
  delay(1);
}
  • Lines 1 and 2: define macros for the LED and button pins.
  • Line 4: declares a global variable to store the previous state of pin 3.
  • Lines 7 and 8: set pin 2 as an output and initialize it to a low state.
  • Line 9: sets pin 3 as an input and enables the internal pull-up resistor.
  • Line 13: reads the state of pin 3 on each loop iteration.
  • Line 14: checks if the previous state has changed and if the current state is low, which indicates a button press.
  • Line 15: toggles the LED by writing the opposite of its current state to pin 2.
  • Line 17: saves the current state of the button pin for the next iteration.
  • Line 18: adds a 1 millisecond delay to prevent fluctuations when the button is pressed.

We can optimize the previous example by using interrupts. The program below is similar to the previous example with a few minor changes. Note that on Arduino Uno, interrupts can only be attached to pins 2 and 3. If you are using a different Arduino board model, check the documentation to see which pins support interrupts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#define LED_PIN 2
#define BUTTON_PIN 3

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), toggleLed, FALLING);
}

void loop() {
  // Do other stuff...
}

void toggleLed() {
  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
  • Line 8 attaches an interrupt handler function to the pin 3 on the falling edge.
  • Line 15 defines the interrupt function that will be executed when an interruption occurs, which is the same as the one in the previous example.

Note that we don’t have anything in the loop() function, but additional logic can be added. However, when an interrupt occurs, the execution of the loop() function will be paused, and the interrupt handler function will be executed. After the interrupt handler finishes, the loop() function will resume. It is important to keep the interrupt handler functions short and fast, as they can interfere with other operations and cause unexpected behavior.

This article covers the basics of configuring and using Arduino’s pins as input and output, with examples of controlling an LED and reading from a button. It explains how to use pinMode() to set the mode of a pin, digitalRead() to read the value of an input pin, and digitalWrite() to set the value of an output pin. The article also introduces the use of interrupts to handle pin changes, as an alternative to continuously polling the pin state. With this knowledge, Arduino users can begin to create a wide range of projects using the full capabilities of the device’s I/O pins.