Comunicação Serial no Arduino com Monitor Serial – Fundamentos e Uso com String

Comunicação Serial com Arduino e Monitor Serial

Objetivo

O objetivo deste artigo é apresentar, de forma clara e estruturada, como funciona a comunicação serial no Arduino utilizando o Monitor Serial da IDE.

Ao final desta leitura, você será capaz de:

  • Entender o que é comunicação serial e como ela ocorre no Arduino

  • Como configurar corretamente a porta serial
  • Como enviar e receber dados pelo Monitor Serial

  • Compreender os principais comandos do objeto Serial

  • Como interpretar comandos digitados pelo usuário

  • Como manipular textos recebidos utilizando a classe String

  • Criar a base para projetos mais avançados, como protocolos de aplicação e integração com outras linguagens (ex: Python)

Este conteúdo serve como fundamento para qualquer projeto que envolva troca de dados entre o Arduino e um computador. Ao final da leitura, você terá não apenas exemplos práticos funcionando, mas também entendimento técnico suficiente para decidir quando usar String e quando optar por char[] em seus projetos.

Definições

Comunicação Serial

Comunicação serial é o processo de transmissão de dados bit a bit, de forma sequencial, através de um canal de comunicação.

Diferente da comunicação paralela — onde vários bits são enviados simultaneamente — na comunicação serial os bits são enviados um após o outro, em uma única linha de transmissão.

Como isso acontece no Arduino?

No Arduino Uno, a comunicação serial ocorre através da interface UART (Universal Asynchronous Receiver Transmitter), que utiliza dois pinos principais:

  • TX (Transmit) → responsável por enviar dados

  • RX (Receive) → responsável por receber dados

Quando conectamos o Arduino ao computador via USB, um chip conversor USB-Serial transforma os sinais elétricos TX/RX em dados que o computador consegue interpretar. Esses dados são então visualizados no Monitor Serial da Arduino IDE.

⚠ Observação Importante sobre os pinos 0 e 1 no Arduino UNO

No Arduino Uno, os pinos digitais 0 (RX) e 1 (TX) são compartilhados com a USB.

Isso significa que:

  • Eles são usados tanto para o Monitor Serial quanto para upload do código.

  • Se houver algum módulo ou componente conectado nesses pinos, pode ocorrer erro no upload.

Sempre desconecte dispositivos dos pinos 0 e 1 antes de fazer o upload (gravar o programa).

No Arduino Mega 2560, isso é menos crítico, pois ele possui múltiplas portas seriais (Serial, Serial1, Serial2, Serial3), evitando conflitos.

Monitor Serial da IDE do Arduino

O Monitor Serial da Arduino IDE é uma interface de terminal que permite a comunicação direta entre o computador e a placa Arduino via USB, utilizando o protocolo serial (UART).

Ele funciona como um canal bidirecional:

  • Exibe dados enviados pelo programa através de Serial.print() e Serial.println().

  • Permite enviar dados digitados pelo usuário, que podem ser lidos pelo microcontrolador com Serial.available() e Serial.read().

A comunicação ocorre na velocidade definida por Serial.begin(baud rate), sendo essencial que o valor configurado no código coincida com o selecionado no Monitor Serial.

No contexto deste artigo, o Monitor Serial será utilizado como ferramenta de teste, depuração e simulação de comandos enviados ao Arduino Uno.

O que é Baud Rate?

Baud Rate é a velocidade da comunicação serial, ou seja, a quantidade de bits transmitidos por segundo (bps) entre dois dispositivos.

Por exemplo, se a taxa for 9600 bps:

  • 9.600 bits por segundo

  • Aproximadamente 960 caracteres por segundo (considerando 10 bits por caractere)

Na comunicação serial do Arduino Uno, o Baud Rate define o ritmo em que os dados são enviados e recebidos pela porta USB.

⚠ Atenção: É fundamental que o valor configurado no código seja exatamente o mesmo selecionado no Monitor Serial da Arduino IDE. Caso contrário, os caracteres aparecerão incorretos.

Valores "Baud Rate" Mais Utilizados

  • 9600 → padrão para iniciantes e dispositivos simples

  • 57600 → intermediário

  • 115200 → muito usado em projetos mais rápidos

Para projetos básicos e didáticos, 9600 é suficiente. Para comunicação mais intensa (como integração com ESP ou Python), 115200 é mais eficiente.

Objeto Serial - Definição e Métodos Principais

O objeto Serial é responsável por controlar toda a comunicação serial no Arduino. Antes de manipular comandos, precisamos configurar corretamente a “estrada” por onde os dados irão trafegar.

Observações:

a) Na programação, Serial não é apenas um comando isolado. Ele é uma instância (objeto) criada automaticamente  de uma classe C++ definida no núcleo interno do Arduino — normalmente derivada da classe HardwareSerial.

b) Os "comandos ou funções" do objeto Serial (como Serial.begin(), Serial.print() ou Serial.available()) são chamados de métodos porque a linguagem do Arduino é baseada em C++, que é uma linguagem orientada a objetos. Para isso, usamos o ponto (Objeto.método).

c) Grande parte da literatura sobre Arduino utiliza o termo “classe Serial” apenas por simplificação didática. Embora não esteja completamente errado do ponto de vista conceitual, o termo mais tecnicamente preciso é objeto Serial, pois estamos utilizando uma instância já criada da classe responsável pela comunicação serial.

d) Utilizaremos ambas as nomenclaturas conforme a conveniência didática: Objeto Serial ou Classe Serial.

O objeto Serial permite:

  • Iniciar a comunicação

  • Enviar dados ao computador

  • Receber dados do usuário

  • Monitorar o buffer de entrada e saída

  • Controlar o fluxo de transmissão

No Arduino Uno e Mega, a comunicação serial ocorre através da UART interna do microcontrolador e é acessada por meio do objeto Serial.

Mas o que é buffer no Objeto Serial?

No contexto do objeto Serial, buffer é uma área de memória temporária usada para armazenar dados que estão sendo transmitidos ou recebidos. Ele funciona como uma fila de espera.

USB → Buffer RX → Código → Buffer TX → USB

Imagine que os dados chegam muito rápido pela comunicação serial. O microcontrolador pode não conseguir processá-los exatamente no mesmo instante em que chegam. Para evitar perda de informação, esses dados são armazenados temporariamente no buffer até que o programa os leia.

Buffer de Recepção (RX)

Quando você digita algo no campo mensagem do Monitor Serial da Arduino IDE, os caracteres enviados chegam ao Arduino Uno e são armazenados automaticamente no buffer de recepção.

No Arduino Uno, esse buffer possui normalmente 64 bytes.

Isso significa que:

  • Até 64 caracteres podem ficar armazenados na porta serial aguardando leitura.

  • Se você não ler os dados a tempo e o buffer encher, os próximos caracteres poderão ser descartados.

Buffer de Transmissão (TX)

Além do buffer de recepção, também existe um buffer de transmissão.

Quando você usa, por exemplo: Serial.print("Olá");

O texto não é enviado instantaneamente. Ele é colocado no buffer de transmissão e enviado gradualmente pela UART.

Veja abaixo o fluxograma de um sistema de comunicação serial para o Arduino UNO e Mega.

Computador (Monitor Serial)
            │
                   │ USB
            ▼
Conversor USB-Serial
            │
            ▼
     Buffer RX (Entrada)
            │
            ▼
     Seu Código (loop)
            │
            ▼
     Buffer TX (Saída)
            │
                             │ USB          
            ▼
Computador (Monitor Serial)

Métodos principais do objeto Serial

A seguir, veremos os comandos mais importantes e como utilizá-los corretamente:

1. Serial.begin()

Inicializa a comunicação serial.

void setup() {
  Serial.begin(9600);
}
  • Deve ser chamada dentro da função setup()

  • Define a velocidade de comunicação (Baud Rate)

  • Valores comuns: 9600, 57600, 115200

  • Prepara a UART para transmissão e recepção de dados

Para projetos simples e testes, 9600 é suficiente. Para transmissões mais rápidas, 115200 é bastante utilizado.

Sem Serial.begin(), nenhum outro comando do objeto Serial funcionará corretamente.

2. Serial.print()

Envia dados para o Monitor Serial.

Serial.print("Temperatura: ");
Serial.print(25);

Ele pode enviar:

  • Texto

  • Números inteiros

  • Números decimais

  • Variáveis

A função print() não adiciona quebra de linha automaticamente. Envia o texto e continua na mesma linha.

3. Serial.println()

Funciona como o print(), mas adiciona uma quebra de linha ao final (\n).

  • A quebra de linha pula o cursor para a linha de baixo (equivalente à tecla Enter).

  • A representação padrão para quebra de linha é \n (newline), na maioria das linguagens de programação (C, Python, Java, JS, etc) e sistemas Linux. Atua como um caractere especial que informa ao computador para iniciar uma nova linha a partir daquele ponto no texto. Pode ser representado pelo código ASCII 10.

  • Em contexto web (HTML), usa-se <br> para quebrar linha, enquanto \n é usado no código (strings) para estruturar texto, frequentemente sem efeito visual no navegador

Serial.println("Sistema iniciado");

Facilita a organização visual das mensagens no Monitor Serial.

4. Serial.available()

Verifica se há dados recebidos aguardando leitura.

if (Serial.available() > 0) {
    // Existe dado disponível
}

Esse comando retorna:

  • 0 → nenhum byte disponível

  • Valor maior que 0 → número de bytes presentes no buffer de recepção

Ele é essencial para evitar leitura inválida, ou seja, evita que o programa tente ler dados que ainda não chegaram.

5. Serial.readString() – Leitura Completa como String

O método Serial.readString() lê todos os caracteres disponíveis na porta serial e os armazena automaticamente em uma variável do tipo String.

String texto = Serial.readString();
  • Lê os caracteres recebidos

  • Armazena em uma String

  • Para quando atinge o timeout (padrão ≈ 1 segundo)

⚠ Atenção: Serial.readString() é um método bloqueante.

Ele aguarda até:

  • O timeout ser atingido

  • Ou não haver mais dados no buffer

  • O Arduino para tudo o que está fazendo e fica esperando o o timeout (padrão de 1 segundo).

  • Se o seu código tiver que controlar um motor ou ler um sensor ultrassônico ao mesmo tempo, ele vai falhar.

6. Serial.readStringUntil('\n')

Lê caracteres do buffer até encontrar quebra de linha (nova linha). Isso permite capturar o comando inteiro digitado.

comando = Serial.readStringUntil('\n');
  • Retorna uma String.

  • Simplifica muito a captura de comandos completos.

⚠ Atenção: Serial.readStringUntil('\n') é uma função bloqueante.

Ele aguarda até:

  • Até encontrar o caractere "\n" ou atingir o timeout (padrão ≈ 1 segundo).

  • Ou não haver mais dados no buffer

7. Serial.parseInt() – Extraindo Números Automaticamente

O método Serial.parseInt() permite ler automaticamente um número inteiro enviado pela porta serial.

Ele ignora caracteres que não são numéricos e converte a sequência de dígitos em um valor do tipo long.

long valor = Serial.parseInt();
  • Lê caracteres recebidos pela porta serial

  • Ignora caracteres que não são números

  • Constrói automaticamente um número inteiro

  • Retorna um long (inteiro de 32 bits).

⚠ Atenção: Serial.parseInt() é um método bloqueante.

Ele aguarda:

  • Encontrar um número válido

  • Ou o tempo limite (timeout padrão ≈ 1 segundo)

8. Serial.parseFloat() – Leitura de Números Decimais

O método Serial.parseFloat() funciona de maneira semelhante ao parseInt(), mas extrai números decimais (com ponto).

float valor = Serial.parseFloat();
  • Ignora caracteres não numéricos

  • Reconhece números com ponto decimal

  • Retorna um valor do tipo float

⚠ Atenção: Assim como parseInt(), o método parseFloat() também é bloqueante.

Ele aguarda:

  • Encontrar um número válido

  • Ou atingir o timeout

9. Serial.setTimeout()

Por padrão, o timeout é de aproximadamente 1000 ms (1 segundo). Ele pode ser alterado com:

Serial.setTimeout(200);  // 200 ms

Mas se estiver usando os  métodos Serial.readString(), Serial.readStringUntil('\n'), parseInt() ou parseFloat(), ainda continuará sendo bloqueante — apenas por menos tempo.

10. Serial.read()

Lê o primeiro byte disponível no buffer serial.

char c = Serial.read();
  • Retorna um byte (tipo int) por vez

  • Remove o byte do buffer após a leitura
  • Normalmente armazenamos em uma variável char

  • Deve ser usado após verificar Serial.available()

Se você quiser ler uma palavra inteira, será necessário montar a string caractere por caractere.

6. Serial.flush()

Serial.flush();

Aguarda a finalização da transmissão de dados que estão sendo enviados.

⚠ Observação importante: Nas versões atuais da IDE, Serial.flush() não limpa o buffer de entrada, apenas garante que todos os dados de saída foram transmitidos.

Exemplo Prático: Enviando Dados Gerados no Loop para o Monitor Serial

Neste exemplo, o Arduino irá:

  • Gerar um contador automático

  • Simular uma leitura analógica

  • Enviar os dados formatados para o Monitor Serial

  • Utilizar Serial.begin(), Serial.print() e Serial.println()

// Variável global que armazenará o valor do contador
// Como é global, mantém o valor entre cada execução do loop()
int contador = 0;

void setup() {

  // Inicializa a comunicação serial com velocidade de 9600 bits por segundo
  // Esse valor deve ser o mesmo configurado no Monitor Serial
  Serial.begin(9600);

  // Envia uma mensagem inicial para indicar que o programa começou
  Serial.println("Sistema iniciado...");
}

void loop() {

  // Lê o valor analógico do pino A0
  // O valor retornado varia de 0 a 1023 (conversor ADC de 10 bits)
  // Nota: Se nada estiver conectado, os valores irão variar aleatoriamente (ruído elétrico).
  int leitura = analogRead(A0);  

  // Envia texto fixo para o Monitor Serial
  Serial.print("Contador: ");

  // Envia o valor atual do contador (sem quebra de linha)
  Serial.print(contador);

  // Envia um separador visual
  Serial.print(" | Leitura A0: ");

  // Envia o valor da leitura analógica e adiciona quebra de linha
  Serial.println(leitura);

  // Incrementa o contador em 1 a cada execução do loop()
  contador++;

  // Aguarda 1 segundo (1000ms) antes de repetir o processo
  // Isso evita que os dados sejam enviados rapidamente demais
  // Enquanto o Arduino espera, ele não processa outras funções.
  delay(1000);
}

O resultado no Monitor Serial será algo como:

Contador: 0 | Leitura A0: 523
Contador: 1 | Leitura A0: 519
Contador: 2 | Leitura A0: 530

Comunicação Serial Usando String (Didático e Simples)

Nesta seção, vamos trabalhar com a classe String, que facilita a manipulação de textos recebidos pela comunicação serial via Monitor Serial.

Essa abordagem é ideal para:

✔ Iniciantes
✔ Prototipagem rápida
✔ Projetos simples
✔ Foco em lógica antes de otimização de memória

O que é a classe String (objeto String)?

A String é uma classe da linguagem C++ já disponível no Arduino.

Ela permite:

  • Armazenar textos dinamicamente

  • Comparar palavras com facilidade

  • Concatenar mensagens

  • Converter texto em número

  • Manipular conteúdo de forma simples

Exemplo:

String nome = "Angelo";

Principais Métodos do Objeto String

Aqui estão os métodos mais importantes para comunicação serial:

1. length()

Retorna o número de caracteres da string.

nome.length();

2. trim()

Remove espaços e caracteres invisíveis no início e no fim da string.

Muito útil para remover \r e \n enviados pelo Monitor Serial.

\r posiciona o cursor na coluna 0 da mesma linha. Se você escrever algo após um \r, o texto anterior naquela linha será sobrescrito.

\n representa uma nova linha (newline ou line feed)

comando.trim();

3. toInt()

Converte texto em número inteiro.

String valor = "123";
int numero = valor.toInt();

4. equals()

Compara duas strings.

if (comando.equals("LEDON"))

5. Operador ==

Também compara 2 strings diretamente:

if (comando == "LEDON")

6. startsWith()

Permite detectar comandos com parâmetros.

if (comando.startsWith("NUMERO "))

Exemplo de comandos com parâmetros:

NUMERO 10
NUMERO 200
NUMERO 1500

7. substring()

Extrai parte do texto a partir de uma posição.

comando.substring(7);

Exemplo: Remove a palavra "NUMERO " e mantém apenas o valor.

8. concat()

Concatena texto ao final da string.

mensagem.concat(" Mundo");

Exemplo de Comunicação Serial Usando String - Código Documentado

O exemplo abaixo mostra uso da classe String para manipulação de comandos na comunicação serial:

// Variável global do tipo String
// Armazenará o comando digitado pelo usuário no Monitor Serial
String comando = "";

void setup() {

  // Inicializa a comunicação serial com taxa de 9600 bits por segundo
  Serial.begin(9600);

  // Configura o pino 13 como saída (LED onboard do Arduino Uno)
  pinMode(13, OUTPUT);

  // Mensagens iniciais exibidas no Monitor Serial
  Serial.println("Sistema iniciado.");
  Serial.println("Digite: LEDON ou LEOFF");
  Serial.println("ou");
  Serial.println("Digite: NUMERO valor");
  // Linha separadora visual no Monitor Serial
  Serial.println("-------------------");
}

void loop() {

  // Verifica se existe pelo menos 1 byte disponível no buffer serial
  if (Serial.available() > 0) {

    // Lê todos os caracteres recebidos até encontrar '\n'
    // Isso captura a linha inteira digitada no Monitor Serial
    comando = Serial.readStringUntil('\n');

    // Remove espaços extras e caracteres invisíveis (\r)
    // Muito importante para evitar falhas na comparação
    comando.trim();

    // Mostra no Monitor Serial qual comando foi recebido
    Serial.print("Comando recebido: ");
    Serial.println(comando);

    // Exibe o tamanho do texto digitado
    // O método length() retorna o número de caracteres da String
    Serial.print("Tamanho do comando: ");
    Serial.println(comando.length());

    // ===== COMANDO LEDON =====
    // Se o texto for exatamente "LEDON"
    if (comando == "LEDON") {

      // Liga o LED do pino 13
      digitalWrite(13, HIGH);

      Serial.println("LED ligado.");
    }

    // ===== COMANDO LEDOFF =====
    else if (comando == "LEDOFF") {

      // Desliga o LED
      digitalWrite(13, LOW);

      Serial.println("LED desligado.");
    }

    // ===== COMANDO COM PARÂMETRO =====
    // Verifica se o comando começa com "NUMERO "
    else if (comando.startsWith("NUMERO ")) {

      // Extrai apenas a parte numérica
      // "NUMERO 50"
      // índice 0123456
      // substring(7) remove "NUMERO "
      String valorTexto = comando.substring(7);

      // Converte o texto para número inteiro
      int numero = valorTexto.toInt();

      Serial.print("Número recebido: ");
      Serial.println(numero);
    }

    // ===== CASO NENHUM COMANDO SEJA RECONHECIDO =====
    else {
      Serial.println("Comando inválido.");
    }

    // Linha separadora visual no Monitor Serial
    Serial.println("-------------------");
  }
}

O que aparece no Monitor Serial?

Veja no exemplo abaixo os dados que aparecem no Monitor Serial, sendo que foi digitado primeiro o comando LEDON e depois o comando com parâmetro NUMERO 1500.

Eficiência do Uso da classe String na Comunicação Serial

O código apresentado utilizando a classe String é altamente eficiente do ponto de vista didático e estrutural, mas possui limitações técnicas quando analisado sob a ótica de sistemas embarcados.

Gestão de Memória Dinâmica (Heap)

Obs.: A memória dinâmica heap no Arduino Uno é uma região da memória RAM (SRAM) dedicada à alocação de dados durante a execução do programa. No Arduino Uno, temos apenas 2 KB de SRAM.

A classe String utiliza alocação dinâmica de memória. Isso significa que:

  • A memória é reservada conforme o texto cresce.

  • A memória pode ser liberada e realocada diversas vezes.

  • Pode ocorrer fragmentação do heap ao longo do tempo e gerar falhas.

  • Instabilidade em aplicações longas ou complexas

Em projetos pequenos isso não é problema. Mas em sistemas maiores, com muitas Strings sendo criadas e modificadas, pode ocorrer: Fragmentação de memória, Comportamento instável, Reset inesperado, Travamentos difíceis de diagnosticar.

Para aplicações didáticas ou protótipos simples, isso raramente acontece.

Natureza Bloqueante da Leitura

O método abaixo é bloqueante:

Serial.readStringUntil('\n');

Isso significa que o Arduino:

  • Para a execução naquele ponto

  • Aguarda o delimitador

  • Ou espera o timeout (padrão ≈ 1 segundo)

Durante essa espera:

  • O loop() não continua

  • Sensores não são lidos

  • Atuadores não são atualizados

Em projetos simples isso não afeta o funcionamento. Em sistemas de tempo real, pode comprometer o desempenho.

Quando é Adequado Utilizar String?

✔ Projetos educacionais
✔ Prototipagem rápida
✔ Sistemas simples
✔ Configuração de parâmetros via serial
✔ Aplicações não críticas

Quando Deve-se Evitar?

❌ Sistemas embarcados de longa duração
❌ Controle de motores ou robótica
❌ Sistemas com múltiplas tarefas simultâneas
❌ Aplicações com memória limitada próxima do limite

A classe String oferece excelente produtividade e clareza, mas com custo potencial de previsibilidade de memória e tempo de execução.

Ela é adequada para aprendizado e aplicações simples, porém não representa a abordagem mais robusta para projetos embarcados profissionais.

Na próxima seção, analisaremos a alternativa com char[], que oferece maior controle de memória e comportamento não bloqueante.

Conclusão

Ao longo deste artigo, exploramos a comunicação serial no Arduino sob uma abordagem didática e estruturada, utilizando a classe String como ferramenta principal.

Começamos compreendendo os fundamentos da comunicação serial, o funcionamento do objeto Serial, o papel dos buffers internos e a importância do Baud Rate. Em seguida, aplicamos esses conceitos na prática, manipulando comandos recebidos pelo Monitor Serial da Arduino IDE de forma simples e intuitiva.

Essa abordagem é ideal para aprendizado, prototipagem rápida e consolidação dos conceitos fundamentais.

No próximo artigo, avançaremos para uma implementação mais robusta e profissional, utilizando arrays de caracteres (char[]) e controle manual de buffer:  Comunicação Serial Profissional no Arduino: char[], Buffer e Controle de Memória

O anúncio abaixo ajuda a manter o Squids Arduino funcionando

Comentários

×

Infomações do site / SEO








×

Adicionar Marcadores