Arduino · material didático

Cap. 2 — Controle de Fluxo: Condicionais

Prof. Clayton J A Silva Rev 2026.2

2. Programando com Arduino. Controle de fluxo: condicionais simples e compostas

Os comandos de controle de fluxo para o Arduíno são aqueles que permitem ao programador alterar a sequência de execução das instruções do programa, similares à linguagem C/C++.

Podem ser divididos em dois grupos:

As condições que determinam o fluxo de execução das instruções geralmente são definidas pelo resultado de uma expressão lógica.

2.1 Expressões lógicas

As expressões aritméticas resultam em números, por exemplo ponto flutuante (tipo float) ou inteiros (tipo int).

As expressões lógicas são aquelas cujo resultado é um valor lógico. Na linguagem do Arduíno (como em C/C++), o valor lógico retornado por uma expressão lógica verdadeira é 1; e o valor lógico falso é 0.

Nesse ponto cabe uma observação:

Assim como os operadores aritméticos especificam à máquina uma operação aritmética, os operadores lógicos especificam operações lógicas, que são de dois tipos: relacionais ou de comparação e operações lógicas (próprias da lógica matemática).

2.1.1 Operadores lógicos de comparação

Os operadores lógicos de comparação possibilitam criar proposições simples estabelecendo a relação comparativa entre dois dados do mesmo tipo, por exemplo, duas variáveis, uma variável e uma expressão aritmética, duas constantes etc.

A tabela especifica os operadores e a respectiva operação lógica correspondente.

Operador Operação
> maior
< menor
>= maior ou igual
<= menor ou igual
== igual
!= diferente

Os operadores relacionais são aplicados a dois operandos. Por exemplo, 3 > 2, que compara o número 3 com o número 2.

Os operandos podem conter números; variáveis, por exemplo, x > 3; e expressões aritméticas, por exemplo, x + 3 <= 4 + y. A máquina resolve primeiro as expressões aritméticas (os operadores aritméticos têm precedência sobre os lógicos).

Expressões lógicas podem ser operandos de outras expressões lógicas. Isso é possível porque as expressões lógicas retornam valores inteiros (int) que são interpretados como 0 (falso) ou 1 (verdadeiro). Pode-se usar esses valores como operandos em outras operações lógicas para construir expressões mais complexas.

2.1.2 Operadores lógicos

Variáveis, expressões ou constante lógicas podem ser combinadas com operadores lógicos para formar proposições compostas.
As operações lógicas básicas são conjunção, disjunção e negação (inversão lógica).

Operador Operação
&& conjunção (and)
|| disjunção (or)
! negação

Existem operações que podem ser aplicadas bit a bit.

As operações lógicas também podem ser utilizadas bit a bit. Nesse caso, os operandos devem ser inteiros. Os operadores são os seguintes:

Operador Operação
& conjunção bit a bit (and)
\ disjunção bit a bit (or)
^ ou exclusivo bit a bit (xor)
! negação
<< deslocamento à esquerda
>> deslocamento à direita

As operações lógicas bit a bit (ou bitwise) são usadas para manipular bits individuais de um número. Na linguagem do Arduíno (assim como em C/C++), essas operações são realizadas usando operadores específicos que operam diretamente nos bits de um operando. Essas operações são úteis em muitas aplicações de baixo nível, como manipulação de registros, criptografia, e controle de hardware.

As operações de conjunção, disjunção e negação são aplicadas a cada bit dos operandos. Os operadores bit a bit operam diretamente sobre os bits individuais dos operandos.

As operações de deslocamento requerem como operando o inteiro cuja representação em bita será aplicado o deslocamento, bem como o número de bits de posições de deslocamento. Por exemplo,

int a = 3; // 11 em binário
int res = a << 2; // Desloca os bits de 'a' duas posições para a esquerda
Serial.begin(9600);
Serial.println(res); // Imprime o valor de 'res' no monitor serial

irá apresentar na console do monitor serial o valor 12 (1100 em binário).

Operações lógicas bit a bit são projetadas para serem usadas com tipos de dados inteiros (como int, unsigned int, char, short, long). Aplicar esses operadores a tipos de dados de ponto flutuante (como float e double) não é apropriado e geralmente resulta em comportamento indefinido ou em um erro de compilação, dependendo do compilador e das configurações.

Os caracteres podem ser usados com operadores bit a bit porque cada caractere é internamente representado por um valor inteiro correspondente ao seu código ASCII.

2.2 Condicionais simples

Na condicional simples, a execução de um bloco de instruções interno ao comando é condicionada ao resultado da expressão lógica da sentença.

Sua sintaxe é

if (<condição>) {
  <bloco de instruções>
}

Processo de execução pela máquina:

  1. A condição via de regra é uma expressão lógica, cujo valor é calculado pela máquina. A condição só pode gerar um resultado dentre dois possíveis: diferente de 0 - 1 se a condição for expressão lógica, (verdadeiro), ou 0, (falso).
  1. A instrução (ou bloco de instruções) interna é executada somente se a condição ou o cálculo da expressão lógica resultar diferente de 0 e a execução do programa prossegue após a estrutura if.

  2. Em caso contrário, se a condição for falsa (valor 0), a máquina executa a instrução seguinte ao if do programa, sem executar a instrução (ou bloco de instruções).

Observações gerais:

Um exemplo é o seguinte:

void setup() {
  Serial.begin(9600); // Inicializa a comunicação serial a 9600 bps
}

void loop() {
  int num; // Declaração da variável num

  // Solicitar ao usuário que insira um número
  Serial.println("Digite um numero: ");
  
  // Esperar até que o usuário insira um número no monitor serial
  while (Serial.available() == 0) {
    // Aguarda a entrada do usuário
  }
  
  // Lê o número inserido
  num = Serial.parseInt();

  // Limpa o buffer serial para evitar caracteres residuais
  while (Serial.available() > 0) {
    Serial.read();
  }

  // Verificar o valor de 'num' e enviar a resposta correspondente
  if (num > 10) {
    Serial.println("\n\nO numero e maior do que 10");
  }
  if (num == 10) {
    Serial.println("\n\nVoce acertou!\n");
    Serial.println("\nO numero e igual a 10");
  }
  if (num < 10) {
    Serial.println("\n\nO numero e menor do que 10");
  }
  
  // Adiciona um pequeno atraso antes de reiniciar o loop
  delay(1000); 
}

Nesse exemplo, acho importante destacar:

  1. Serial.available(): é um método da classe que o objeto Serial representa. Verifica quantos bytes estão disponíveis para leitura na porta serial e retorna o número de bytes disponíveis para leitura na porta serial. Em outras palavras, indica quantos caracteres (ou bytes) foram recebidos pela porta serial e estão prontos para serem lidos.
  2. A estrutura while (Serial.available() == 0):: é uma estrutura de repetição - como trataremos mais adiante, que continua a rodar em loop enquanto Serial.available() retorna 0, ou seja, mantém o Arduino preso dentro do loop até que pelo menos um byte de dados esteja disponível para leitura. Quando o usuário digita um número e pressiona "Enter", os bytes correspondentes ao número (e possivelmente um caractere de nova linha \n ou \r, Serial.available() retorna um valor maior que 0, significando que há pelo menos um byte de dados na fila de recepção serial, e o loop while termina, permitindo que o código continue sua execução.
  3. while (Serial.available() > 0): é um loop que continua a rodar enquanto Serial.available() retorna um valor maior que 0, indicando que há dados disponíveis residuais no buffer serial. Serial.read() é um método lê um byte de dados do buffer serial, logo, nesse caso, limpando o buffer.
  4. Serial.parseInt():: é um método que lê a entrada serial até encontrar um número válido e busca convertê-lo em um inteiro (int). Ignora automaticamente qualquer caractere não numérico (exceto sinais de negativo) até encontrar o início de um número. Assim que encontra um dígito numérico, começa a construir o número até que ele encontre um número completo ou até que o tempo limite (timeout, 1 segundo, que pode ser ajustado com o método Serial.setTimeout()) seja alcançado. O método retorna o número inteiro que foi lido e convertido. Esse valor pode ser armazenado em uma variável, como no exemplo. continua lendo caracteres do buffer serial. Observação: caracteres como espaços, quebras de linha (\n), ou qualquer caractere não numérico (exceto sinais de negativo) são ignorados até que o método encontre um número válido.

2.3 Condicionais compostas

Na condicional composta, a execução de um bloco de instruções interno ao comando if é condicionada ao valor da condição ou resultado da expressão lógica da sentença ser verdadeiro (diferente de 0), enquanto a execução de outro bloco de instruções, interno ao else do comando if, é condicionada ao resultado ser falso (valor lógico igual a 0).

A sintaxe é

if (<condição>) {
  <bloco 1 de instruções>
}
else {
  <bloco 2 de instruções>
}

Processo de execução pela máquina:

  1. A condição é avaliada ou a expressão lógica é calculada pela máquina, gerando um dentre dois resultados, diferente de 0 (verdadeiro) ou 0 (falso).
  2. A instrução (ou bloco 1 de instruções) - interno ao if - é executado somente se a expressão lógica de sua sentença resultar 1.
  3. A instrução (ou bloco 2 de instruções) - interno ao else é executado se a expressão lógica resultar 0.
  4. Em ambas as situações, o programa prossegue sua execução a partir da instrução seguinte ao comando if.

Observações gerais:

Um exemplo é o seguinte:

void setup() {
  Serial.begin(9600); // Inicializa a comunicação serial a 9600 bps
}

void loop() {
  int num; // Declaração da variável num

  // Solicitar ao usuário que insira um número
  Serial.println("Digite um numero: ");
  
  // Esperar até que o usuário insira um número no monitor serial
  while (Serial.available() == 0) {
    // Aguarda a entrada do usuário
  }
  
  // Lê o número inserido
  num = Serial.parseInt();

  // Limpa o buffer serial para evitar caracteres residuais
  while (Serial.available() > 0) {
    Serial.read();
  }

  // Verificar o valor de 'num' e enviar a resposta correspondente
  if (num > 10) {
    Serial.println("\n\nO numero e maior do que 10");
  } else {
    Serial.println("\n\nO numero e menor ou igual a 10");
    if (num < 5) {
      Serial.println("\n\nO numero e menor do que 5\n");
      Serial.print("\nO numero e ");
      Serial.println(num);
    }
  }
  
  // Adiciona um pequeno atraso antes de reiniciar o loop
  delay(1000); 
}

2.4 Aninhamento de ifs - comando switch...case

Seja o seguinte uso de condicional composta

void setup() {
  Serial.begin(9600); // Inicializa a comunicação serial a 9600 bps
}

void loop() {
  int a; // Declaração da variável a

  // Solicitar ao usuário que insira um número
  Serial.println("Digite um numero: ");
  
  // Esperar até que o usuário insira um número no monitor serial
  while (Serial.available() == 0) {
    // Aguarda a entrada do usuário
  }
  
  // Lê o número inserido
  a = Serial.parseInt();

  // Limpa o buffer serial para evitar caracteres residuais
  while (Serial.available() > 0) {
    Serial.read();
  }

  // Verificar o valor de 'a' e enviar a resposta correspondente
  if (a > 100) {
    Serial.println("a maior do que 100");
  } else if (a > 50) {
    Serial.println("a maior do que 50");
  } else {
    Serial.println("a menor ou igual a 50");
  }
  
  // Adiciona um pequeno atraso antes de reiniciar o loop
  delay(1000); 
}

O código possui dois comandos condicionais compostos if...else. Diz-se que os ifs estão aninhados.

A linguagem do Arduíno possui uma instrução composta (switch...case) de condicional composta múltipla cuja sintaxe é a seguinte:

switch (<expressão integral>) {
case <dado inteiro, caractere ou enumerador>:
  <bloco 1 de instruções>
  break;
case <dado inteiro, caractere ou enumerador>:
  <bloco 2 de instruções>
  break;
...
default:
  <bloco n de instruções>
}

O argumento do switch é a expressão que você deseja avaliar. Esta expressão pode ser de qualquer tipo de dado integral, ou seja, que representa inteiros, como int, char, enum, etc. O valor desta expressão é comparado com os valores especificados em cada case.

O argumento do case pode ser:

O funcionamento do switch...case é o seguinte:

  1. A máquina testa o valor do argumento do switch comparando-o com o argumento do primeiro case.
  2. Caso seja igual, executa o bloco 1 de instruções (interno ao case) e segue para a instrução posterior ao switch do código.
  3. Caso não seja igual, testa o valor do argumento do switch, comparando-o com o argumento do próximo case.
  4. Caso seja igual, executa o bloco de instruções interno ao case; em caso contrário, segue ao próximo case.
  5. A máquina executa esse procedimento até alcançar default, caso o argumento do switch não seja igual aos argumentos dos case.
  6. Nesse caso, executa o bloco de instruções interno ao default e segue à execução da próxima instrução do código.
  7. Importante que o uso do default é opcional.

Adaptando o exemplo anterior para ilustrar o uso do switch...case, temos:

void setup() {
  Serial.begin(9600); // Inicializa a comunicação serial a 9600 bps
}

void loop() {
  int a; // Declaração da variável a

  // Solicitar ao usuário que insira um número
  Serial.println("Digite um numero: ");
  
  // Esperar até que o usuário insira um número no monitor serial
  while (Serial.available() == 0) {
    // Aguarda a entrada do usuário
  }
  
  // Lê o número inserido
  a = Serial.parseInt();

  // Limpa o buffer serial para evitar caracteres residuais
  while (Serial.available() > 0) {
    Serial.read();
  }

  // Usando switch para verificar o valor de 'a'
  switch (a) {
    case 100:
      Serial.println("Voce digitou 100");
      break;
    case 50:
      Serial.println("Voce digitou 50");
      break;
    default:
      Serial.println("Voce digitou numero diferente de 50 e de 100");
      break;
  }

  // Adiciona um pequeno atraso antes de reiniciar o loop
  delay(1000); 
}

Observação. Você pode usar o mesmo bloco de instruções subordinado a vários case diferentes. Isso é feito simplesmente omitindo as instruções de break entre os case, permitindo que a execução "caia" (fall through) para o próximo case. Por exemplo,

switch (<expressão integral>) {
case <dado inteiro, caractere ou enumerador>: 
case <dado inteiro, caractere ou enumerador>:
  <bloco 2 de instruções>
  break;
...
default:
  <bloco n de instruções>
}

2.5 O operador ternário ? :

Na linguagem do Arduíno, o operador ternário ? : é uma forma concisa de expressão condicional que pode substituir a estrutura if-else para operações simples. Este operador é também conhecido como operador condicional.

A sintaxe é

<condição> ? <instrução ou bloco de instruções 1> : <instrução ou bloco de instruções 2>;

, onde

2.6 Desvio incondicional. Comando goto

Na linguagem do Arduíno dispõe-se de um comando de desvio incondicional, goto. Precisa ser utilizado com muito cuidado, pois é próprio de uma linguagem não estruturada.

O comando goto é frequentemente associado a linguagens de programação não estruturadas, onde o fluxo de controle pode ser alterado arbitrariamente, levando a um código difícil de seguir e manter. No entanto, é importante entender que o C, embora seja uma linguagem de programação estruturada, inclui o comando goto por razões históricas e por permitir certos usos específicos onde pode ser conveniente.

As linguagens não estruturadas são caracterizadas pela ausência de estruturas claras para o controle de fluxo de execução das instruções, como loops e condicionais, o que frequentemente leva ao uso excessivo de comandos goto, resultando em código espaguete (spaghetti code). Exemplos incluem linguagens de primeira geração como Assembly.

O formato geral do goto é

<nome do rotulo>: <instrução>
...
goto <nome do rótulo>;

O rótulo (label) pode ser um nome qualquer, contanto que siga as regras de nomenclatura dos identificadores. Um rótulo é definido como um identificador seguido de dois pontos (:), e pode ser colocado antes de qualquer instrução em uma função.

2.7 Tipos caracteres e cadeias de caracteres

2.7.1 Tipo caractere (char)

Os caracteres são tipo char. Os caracteres válidos na linguagem do Arduíno são baseados no conjunto de caracteres ASCII. O ASCII (American Standard Code for Information Interchange) é um padrão de codificação de caracteres que representa texto em computadores e outros dispositivos que utilizam texto. O ASCII usa valores numéricos para representar caracteres, incluindo letras, dígitos, sinais de pontuação e caracteres de controle.

Caracteres ASCII no Arduíno Letras: A-Z (maiúsculas), a-z (minúsculas) Dígitos: 0-9 Sinais de pontuação: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ { | } ~ ` Caracteres de controle: como \n (nova linha), \t (tabulação), \0 (nulo), entre outros.

Os caracteres são representados internamente por seus valores ASCII, que são inteiros decimais correspondentes a cada caractere. A tabela ASCII (American Standard Code for Information Interchange) define esses valores para um conjunto padrão de caracteres.

A tabela ASCII mapeia caracteres para números inteiros. Por exemplo,

Os caracteres individuais precisam ser delimitados por aspas simples (' '). Alguns caracteres de controle comuns também são representados usando aspas simples, mas com sequências de escape (\).

A declaração de variáveis do tipo char possui a seguinte sintaxe:

char x;

e a declaração com inicialização

char x = '<caractere>';

As atribuições podem ser realizadas para caracteres da mesma forma que para variáveis int e float, <nome> = '<caractere>'.

Além disso, pode-se comparar caracteres diretamente usando os operadores de comparação (==, !=, <, >, <=, >=), pois os caracteres são representados internamente por seus valores ASCII. Similarmente, entre eles podem ser aplicados operadores lógicos bit a bit.

2.7.2 Tipo cadeia de caracteres (string)

As cadeias de caracteres podem ser definidas de duas formas no Arduino: usando vetores de caracteres (char) ou objetos String. Para a linguagem Arduino, um conjunto de caracteres entre aspas duplas é considerado uma string.

No caso de variáveis, as strings baseadas em char precisam ser declaradas sem inicialização ou com inicialização da seguinte forma:

Tipo Descrição
char <nome>[<tamanho>]; Declaração sem inicialização
char <nome>[] = "<cadeia de caracteres>" Declaração com inicialização

Onde

Observações:

  1. Os comandos de atribuição não podem ser utilizados nas strings baseadas em char da mesma forma que nas variáveis int, float e char; Para manipulação de strings no Arduino, você pode usar o objeto String que permite atribuições diretas, como String nome = "Maria";.
  2. As strings baseadas em char não podem ser usadas diretamente em operações lógicas da mesma forma que variáveis inteiras ou caracteres. **Strings em C (e Arduino) são arrays de caracteres terminados com o caractere nulo.

Toda string baseada em char possui um caractere 'terminador' definido no ASCII pelo caractere de escape /0. Por exemplo, a palavra "Maria" é uma string que na linguagem Arduino é definida em memória por:

0 1 2 3 4 5
'M' 'a' 'r' 'i' 'a' '/0'

Como uma string baseada em char é um vetor de caracteres, o nome do vetor define um ponteiro do vetor, ou seja, a variável que aponta para o endereço onde o primeiro caractere do vetor está armazenado em memória. Em razão disso, os elementos da string (os caracteres) podem ser identificados pela sua posição relativa. A sintaxe para a identificação é, como mostrado no exemplo:

char nome[] = "Maria";
Serial.print("A primeira letra do nome é ");
Serial.println(nome[0]);

É bom destacar que a posição sempre é iniciada a partir de 0.

2.7.3 Tipo String

Na linguagem Arduino uma cadeia de caracteres também pode ser declarada com um objeto tipo String. Nesse caso, deve ser declarado da seguinte forma:

Tipo Descrição
String <nome> = "<cadeia de caracteres>"; Declaração com inicialização
String <nome>; Declaração sem inicialização

2.8 Entrada e saída com caracteres e cadeias de caracteres no Arduino

2.8.1 Entrada e Saída com o Monitor Serial do Arduino

Funções Serial.print() e Serial.println()

Como já utilizado nos exemplos anteriores, no Arduino as funções Serial.print() e Serial.println() são usadas para enviar dados do Arduino para o Monitor Serial no computador.

Exemplo básico:

void setup() {
  Serial.begin(9600);  // Inicializa a comunicação serial a 9600 bps
}

void loop() {
    // Limpa o buffer serial
  while (Serial.available() > 0) {
    Serial.read();  // Lê e descarta qualquer dado restante no buffer
  }
  Serial.print("Digite um caractere: ");
  while (Serial.available() == 0) {
    // Aguarda até que um caractere seja digitado no Monitor Serial
  }
  char c = Serial.read();  // Lê o caractere digitado 
  Serial.print("\nVocê digitou: ");
  Serial.println(c);
  delay(1000);  // Pequeno atraso para dar tempo ao usuário
}

Função Serial.read()

A função Serial.read() lê o primeiro byte de dados disponíveis na entrada serial e o retorna como um valor inteiro. Esse valor pode ser convertido em um caractere se necessário.

Exemplo:

void setup() {
  Serial.begin(9600);
}

void loop() {
  delay(1000);
  if (Serial.available() > 0) {
    char c = Serial.read();  // Lê o caractere digitado
    Serial.print("Você digitou: ");
    Serial.println(c);
    while (Serial.available()>0)
      Serial.read();
  }
  
}

Função Serial.readString()

A função Serial.readString() lê a entrada serial e retorna uma String contendo os caracteres recebidos até um delimitador ou timeout. Por padrão, o delimitador é o caractere de nova linha (\n).

Exemplo:

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    String texto = Serial.readString();
    Serial.print("Você digitou: ");
    Serial.println(texto);
  }
}

Função Serial.parseInt()

A função Serial.parseInt() lê a entrada serial e converte os números recebidos em um valor inteiro (int).

Exemplo:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("Digite um número:");
  while (Serial.available() == 0) {
    // Aguarda a entrada do usuário
  }
  int num = Serial.parseInt();
  while (Serial.available() > 0) {
    // Limpa o buffer
    Serial.read();
  }
  Serial.print("Você digitou: ");
  Serial.println(num);
}

2.8.2 Manipulação de Strings no Arduino

As String são objetos utilizados no Arduino para manipulação de texto. As String podem ser manipuladas de diversas maneiras, utilizando métodos específicos.

Exemplo de criação e manipulação de uma String:

void setup() {
  Serial.begin(9600);
  String nome = "Arduino";  // Cria uma String
  Serial.print("O nome é: ");
  Serial.println(nome);
  
  nome += " Mega";  // Concatena " Mega" à String
  Serial.print("O nome completo é: ");
  Serial.println(nome);
}

void loop() {
  // O loop fica vazio neste exemplo
}

A tabela abaixo apresenta um resumo dos principais métodos para trabalhar com o monitor serial.

Método Descrição Entrada Saída
Serial.begin(baudrate) Inicializa a comunicação serial com a taxa de baud especificada. baudrate (taxa de transmissão em bps) Nenhuma
Serial.available() Retorna o número de bytes disponíveis para leitura na porta serial. Nenhuma Número de bytes disponíveis
Serial.read() Lê o próximo byte de dados recebidos no buffer serial. Nenhuma Byte lido (int, -1 se falha)
Serial.peek() Olha o próximo byte de dados recebidos sem removê-lo do buffer. Nenhuma Byte lido (int, -1 se falha)
Serial.flush() Aguarda até que a transmissão de dados em andamento seja concluída. Nenhuma Nenhuma
Serial.print(data) Envia dados para o monitor serial em formato texto. data (int, float, string, etc.) Nenhuma
Serial.println(data) Envia dados para o monitor serial em formato texto, seguido por uma nova linha. data (int, float, string, etc.) Nenhuma
Serial.write(val) Envia um byte ou uma sequência de bytes para o monitor serial. val (byte, char, array, string) Número de bytes escritos
Serial.end() Finaliza a comunicação serial, liberando os pinos digitais usados. Nenhuma Nenhuma
Serial.parseInt() Lê os dados da porta serial como um valor inteiro. Nenhuma Valor inteiro lido
Serial.parseFloat() Lê os dados da porta serial como um valor flutuante (float). Nenhuma Valor float lido
Serial.find(target) Lê os dados recebidos até encontrar uma correspondência com o valor de destino especificado. target (string ou char) true se encontrado, false se não
Serial.readString() Lê todos os caracteres recebidos como uma string até que um tempo limite expire. Nenhuma String lida
Serial.readBytes(buffer, length) Lê uma quantidade específica de bytes no buffer fornecido. buffer (char array), length (int) Número de bytes lidos
Serial.findUntil(target, terminator) Lê os dados até encontrar um alvo ou terminador, o que ocorrer primeiro. target, terminator (string ou char) true se encontrado, false se não
Serial.setTimeout(timeout) Define o tempo limite para operações de leitura. timeout (milissegundos) Nenhuma

Os métodos descritos na tabela são aplicáveis a qualquer objeto da classe HardwareSerial (da qual Serial é uma instância) no Arduino, e não apenas ao monitor serial. A classe HardwareSerial é usada para se comunicar com dispositivos seriais em geral, o que inclui:

Esses métodos permitem que você envie e receba dados através de qualquer interface serial disponível na placa, seja ela conectada ao monitor serial no computador ou a outro dispositivo serial externo.