Skip to content

Módulo 10: Comunicação Serial Avançada

Bem-vindo ao Módulo 10 do curso "Programação em Arduino: Conceitos Fundamentais sem Hardware". Neste módulo, você irá aprofundar seu conhecimento sobre comunicação serial na linguagem de programação Arduino (C/C++). A comunicação serial é essencial para a troca de dados entre o Arduino e outros dispositivos, como computadores, módulos de comunicação e outros microcontroladores.


Objetivos do Módulo

  • Compreender os conceitos avançados de comunicação serial.
  • Aprender a configurar e utilizar diferentes protocolos de comunicação serial, incluindo UART, I2C e SPI.
  • Implementar comunicação serial entre múltiplos dispositivos Arduino.
  • Utilizar a biblioteca SoftwareSerial para criar portas seriais adicionais.
  • Gerenciar a transferência e o parsing de dados de forma eficiente.
  • Resolver exercícios práticos para consolidar o conhecimento sobre comunicação serial avançada.

1. Introdução à Comunicação Serial Avançada

1.1 Revisão da Comunicação Serial Básica

Anteriormente, aprendemos a utilizar o Monitor Serial para enviar e receber dados entre o Arduino e o computador. Neste módulo, expandiremos esse conhecimento para incluir comunicação entre dispositivos e utilização de protocolos mais complexos.

1.2 Importância da Comunicação Serial Avançada

  • Interconectividade: Permite que o Arduino se comunique com uma variedade de dispositivos, como sensores avançados, módulos de comunicação (Wi-Fi, Bluetooth) e outros microcontroladores.
  • Controle Remoto: Facilita o controle e monitoramento do Arduino a partir de dispositivos externos.
  • Transferência de Dados: Habilita a troca eficiente de grandes volumes de dados entre dispositivos.

2. Protocolos de Comunicação Serial

2.1 UART (Universal Asynchronous Receiver/Transmitter)

UART é um protocolo de comunicação serial assíncrona que utiliza dois fios principais: TX (transmissão) e RX (recepção).

Características:

  • Comunicação ponto a ponto.
  • Não requer um relógio compartilhado.
  • Configurações comuns: baud rate, paridade, bits de dados e bits de parada.

Exemplo de Configuração UART:

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

void loop() {
    if (Serial.available() > 0) {
        char recebido = Serial.read();
        Serial.print("Você digitou: ");
        Serial.println(recebido);
    }
}

2.2 I2C (Inter-Integrated Circuit)

I2C é um protocolo de comunicação serial síncrona que utiliza dois fios: SDA (Serial Data) e SCL (Serial Clock).

Características:

  • Comunicação multi-mestre e multi-escravo.
  • Utiliza endereçamento para identificar dispositivos.
  • Ideal para comunicação com sensores e dispositivos que possuem suporte a I2C.

Exemplo de Comunicação I2C:

#include <Wire.h>

void setup() {
    Wire.begin(); // Inicia o I2C como mestre
    Serial.begin(9600);
}

void loop() {
    Wire.beginTransmission(8); // Endereço do dispositivo escravo
    Wire.write("Hello");
    Wire.endTransmission();
    delay(1000);
}

2.3 SPI (Serial Peripheral Interface)

SPI é um protocolo de comunicação serial síncrona que utiliza quatro fios: MOSI (Master Out Slave In), MISO (Master In Slave Out), SCK (Serial Clock) e SS (Slave Select).

Características:

  • Comunicação full-duplex.
  • Alta velocidade de transferência de dados.
  • Utilizado para comunicação com dispositivos de alta velocidade, como cartões SD e displays LCD.

Exemplo de Comunicação SPI:

#include <SPI.h>

void setup() {
    SPI.begin(); // Inicia o SPI como mestre
    pinMode(10, OUTPUT); // SS
    digitalWrite(10, HIGH);
    Serial.begin(9600);
}

void loop() {
    digitalWrite(10, LOW);
    SPI.transfer(0xFF); // Envia byte
    digitalWrite(10, HIGH);
    delay(1000);
}

3. Comunicação Serial Entre Múltiplos Dispositivos Arduino

3.1 Comunicação UART Entre Dois Arduinos

Configuração:

  • Conectar o pino TX do Arduino A ao pino RX do Arduino B.
  • Conectar o pino RX do Arduino A ao pino TX do Arduino B.
  • Conectar GND entre os dois Arduinos.

Exemplo de Código para o Arduino A (Transmissor):

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

void loop() {
    Serial.println("Olá Arduino B!");
    delay(1000);
}

Exemplo de Código para o Arduino B (Receptor):

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

void loop() {
    if (Serial.available() > 0) {
        String mensagem = Serial.readString();
        Serial.print("Recebi: ");
        Serial.println(mensagem);
    }
}

3.2 Comunicação I2C Entre Múltiplos Dispositivos Arduino

Configuração:

  • Conectar SDA a SDA e SCL a SCL entre os Arduinos.
  • Definir endereços únicos para cada dispositivo escravo.

Exemplo de Código para o Arduino Mestre:

#include <Wire.h>

void setup() {
    Wire.begin(); // Inicia como mestre
    Serial.begin(9600);
}

void loop() {
    Wire.beginTransmission(8); // Endereço do escravo
    Wire.write("Dados do Mestre");
    Wire.endTransmission();
    delay(1000);
}

Exemplo de Código para o Arduino Escravo:

#include <Wire.h>

void setup() {
    Wire.begin(8); // Endereço do escravo
    Wire.onReceive(receiveEvent);
    Serial.begin(9600);
}

void loop() {
    // Não há código no loop
}

void receiveEvent(int bytes) {
    while (Wire.available()) {
        char c = Wire.read();
        Serial.print(c);
    }
    Serial.println();
}

4. Utilizando a Biblioteca SoftwareSerial

A biblioteca SoftwareSerial permite criar portas seriais adicionais em pinos digitais, permitindo comunicação com múltiplos dispositivos seriais.

4.1 Configuração da SoftwareSerial

Exemplo de Uso:

#include <SoftwareSerial.h>

// Define os pinos RX e TX para a SoftwareSerial
SoftwareSerial meuSerial(10, 11); // RX, TX

void setup() {
    Serial.begin(9600);        // Porta serial padrão
    meuSerial.begin(4800);     // Porta serial adicional
    Serial.println("Iniciando comunicação serial...");
}

void loop() {
    if (meuSerial.available()) {
        char c = meuSerial.read();
        Serial.print("Recebi via SoftwareSerial: ");
        Serial.println(c);
    }

    if (Serial.available()) {
        char c = Serial.read();
        meuSerial.print(c);
    }
}

Explicação:

  • Definição: SoftwareSerial meuSerial(10, 11); define pinos 10 e 11 como RX e TX adicionais.
  • Inicialização: meuSerial.begin(4800); configura a velocidade da porta serial adicional.
  • Transferência de Dados: Dados recebidos na SoftwareSerial são enviados para a porta serial padrão e vice-versa.

5. Gerenciamento de Transferência e Parsing de Dados

5.1 Formatação de Dados

Para uma comunicação eficiente, é importante definir um protocolo de formatação de dados, utilizando delimitadores ou estruturas específicas.

Exemplo de Dados Delimitados por Vírgulas:

String dados = "23.5,47.8,15.2"; // Temperatura, Umidade, Pressão
Serial.println(dados);

5.2 Parsing de Dados Recebidos

No lado receptor, os dados podem ser divididos e convertidos para os tipos apropriados.

Exemplo de Parsing:

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

void loop() {
    if (Serial.available() > 0) {
        String recebidos = Serial.readStringUntil('\n');
        int primeiraVirgula = recebidos.indexOf(',');
        int segundaVirgula = recebidos.indexOf(',', primeiraVirgula + 1);

        float temperatura = recebidos.substring(0, primeiraVirgula).toFloat();
        float umidade = recebidos.substring(primeiraVirgula + 1, segundaVirgula).toFloat();
        float pressao = recebidos.substring(segundaVirgula + 1).toFloat();

        Serial.print("Temperatura: ");
        Serial.println(temperatura);
        Serial.print("Umidade: ");
        Serial.println(umidade);
        Serial.print("Pressão: ");
        Serial.println(pressao);
    }
}

Explicação:

  • Delimitação: Utiliza vírgulas para separar os valores.
  • Parsing: Usa indexOf e substring para extrair e converter os valores para float.

6. Comunicação Serial com Múltiplos Dispositivos

6.1 Comunicação entre Arduino e Computador via Serial USB

O Arduino pode se comunicar com o computador através da porta USB utilizando a porta serial padrão.

Exemplo de Envio de Dados para o Computador:

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

void loop() {
    Serial.println("Dados do Arduino");
    delay(1000);
}

6.2 Comunicação entre Arduino e Módulos Bluetooth

Utilizando módulos como o HC-05, o Arduino pode se comunicar sem fio com dispositivos como smartphones.

Exemplo de Configuração com SoftwareSerial:

#include <SoftwareSerial.h>

SoftwareSerial bluetooth(10, 11); // RX, TX

void setup() {
    Serial.begin(9600);
    bluetooth.begin(9600);
    Serial.println("Conectado ao Bluetooth.");
}

void loop() {
    if (bluetooth.available()) {
        char c = bluetooth.read();
        Serial.print("Recebi via Bluetooth: ");
        Serial.println(c);
    }

    if (Serial.available()) {
        char c = Serial.read();
        bluetooth.print(c);
    }
}

Explicação:

  • Definição: Pinos 10 e 11 são usados para comunicação serial com o módulo Bluetooth.
  • Transferência de Dados: Dados recebidos do Bluetooth são enviados para o Monitor Serial e vice-versa.

7. Exemplos Práticos

7.1 Comunicação Serial Entre Dois Arduinos Usando I2C

// Código para o Arduino Mestre
#include <Wire.h>

void setup() {
    Wire.begin(); // Inicia como mestre
    Serial.begin(9600);
}

void loop() {
    Wire.beginTransmission(8); // Endereço do escravo
    Wire.write("Dados do Mestre");
    Wire.endTransmission();
    delay(1000);
}
// Código para o Arduino Escravo
#include <Wire.h>

void setup() {
    Wire.begin(8); // Endereço do escravo
    Wire.onReceive(receiveEvent);
    Serial.begin(9600);
}

void loop() {
    // Não há código no loop
}

void receiveEvent(int bytes) {
    while (Wire.available()) {
        char c = Wire.read();
        Serial.print(c);
    }
    Serial.println();
}

Explicação:

  • Mestre: Envia uma string "Dados do Mestre" para o escravo a cada segundo.
  • Escravo: Recebe os dados e os imprime no Monitor Serial.

7.2 Utilizando SoftwareSerial para Comunicação com um Módulo Bluetooth

#include <SoftwareSerial.h>

SoftwareSerial bluetooth(10, 11); // RX, TX

void setup() {
    Serial.begin(9600);
    bluetooth.begin(9600);
    Serial.println("Conectado ao Bluetooth.");
}

void loop() {
    if (bluetooth.available()) {
        char c = bluetooth.read();
        Serial.print("Recebi via Bluetooth: ");
        Serial.println(c);
    }

    if (Serial.available()) {
        char c = Serial.read();
        bluetooth.print(c);
    }
}

Explicação:

  • Envio e Recebimento: Permite enviar e receber dados entre o Arduino e um dispositivo Bluetooth, como um smartphone, utilizando a porta serial adicional criada pela biblioteca SoftwareSerial.

7.3 Comunicação Serial com Parsing de Dados Delimitados

void setup() {
    Serial.begin(9600);
    Serial.println("Envie dados no formato: temperatura,umidade,pressao");
}

void loop() {
    if (Serial.available() > 0) {
        String recebidos = Serial.readStringUntil('\n');
        int primeiraVirgula = recebidos.indexOf(',');
        int segundaVirgula = recebidos.indexOf(',', primeiraVirgula + 1);

        if (primeiraVirgula > 0 && segundaVirgula > primeiraVirgula) {
            float temperatura = recebidos.substring(0, primeiraVirgula).toFloat();
            float umidade = recebidos.substring(primeiraVirgula + 1, segundaVirgula).toFloat();
            float pressao = recebidos.substring(segundaVirgula + 1).toFloat();

            Serial.print("Temperatura: ");
            Serial.println(temperatura);
            Serial.print("Umidade: ");
            Serial.println(umidade);
            Serial.print("Pressão: ");
            Serial.println(pressao);
        } else {
            Serial.println("Formato inválido. Tente novamente.");
        }
    }
}

Explicação:

  • Formato de Dados: Espera uma string no formato "temperatura,umidade,pressao".
  • Parsing: Divide a string com base nas vírgulas e converte os segmentos para float.
  • Validação: Verifica se o formato dos dados está correto antes de processar.

8. Exercícios Práticos

Exercício 1: Comunicação Serial Entre Arduino e PC com Comando de Controle

  • Tarefa: Crie um programa onde o Arduino recebe comandos do computador via Serial para ligar e desligar um LED. Use comandos como "LIGAR" e "DESLIGAR".

  • Dicas:

  • Utilize Serial.readStringUntil('\n') para ler comandos completos.
  • Compare strings para identificar o comando recebido.

  • Exemplo de Código:

const int ledPin = 13;

void setup() {
    pinMode(ledPin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Digite 'LIGAR' ou 'DESLIGAR' para controlar o LED.");
}

void loop() {
    if (Serial.available() > 0) {
        String comando = Serial.readStringUntil('\n');
        comando.trim(); // Remove espaços em branco

        if (comando.equalsIgnoreCase("LIGAR")) {
            digitalWrite(ledPin, HIGH);
            Serial.println("LED Ligado.");
        } else if (comando.equalsIgnoreCase("DESLIGAR")) {
            digitalWrite(ledPin, LOW);
            Serial.println("LED Desligado.");
        } else {
            Serial.println("Comando inválido. Use 'LIGAR' ou 'DESLIGAR'.");
        }
    }
}

Exercício 2: Comunicação Serial com Arduino e Módulo Bluetooth para Controle de Servo

  • Tarefa: Desenvolva um sistema onde um smartphone envia comandos via Bluetooth para o Arduino controlar a posição de um servo motor. Utilize comandos como "ESQUERDA" e "DIREITA" para ajustar o ângulo do servo.

  • Dicas:

  • Utilize a biblioteca SoftwareSerial para comunicação com o módulo Bluetooth.
  • Controle o servo utilizando a biblioteca Servo.

  • Exemplo de Código:

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial bluetooth(10, 11); // RX, TX
Servo meuServo;

void setup() {
    Serial.begin(9600);
    bluetooth.begin(9600);
    meuServo.attach(9); // Servo conectado ao pino 9
    meuServo.write(90); // Posição inicial
    Serial.println("Controle do Servo via Bluetooth iniciado.");
}

void loop() {
    if (bluetooth.available() > 0) {
        String comando = bluetooth.readStringUntil('\n');
        comando.trim();

        if (comando.equalsIgnoreCase("ESQUERDA")) {
            int pos = meuServo.read();
            pos -= 10;
            if (pos < 0) pos = 0;
            meuServo.write(pos);
            Serial.print("Servo movido para a esquerda: ");
            Serial.println(pos);
        } else if (comando.equalsIgnoreCase("DIREITA")) {
            int pos = meuServo.read();
            pos += 10;
            if (pos > 180) pos = 180;
            meuServo.write(pos);
            Serial.print("Servo movido para a direita: ");
            Serial.println(pos);
        } else {
            Serial.println("Comando inválido. Use 'ESQUERDA' ou 'DIREITA'.");
        }
    }
}

Exercício 3: Comunicação Serial com Parsing de Dados para Monitoramento de Sensores

  • Tarefa: Crie um programa onde o Arduino envia dados de múltiplos sensores formatados em JSON para o computador. Utilize parsing para organizar os dados recebidos.

  • Dicas:

  • Utilize delimitadores para estruturar os dados em formato JSON.
  • Implemente funções para criar e interpretar strings JSON.

  • Exemplo de Código:

#include <ArduinoJson.h>

void setup() {
    Serial.begin(9600);
    Serial.println("Monitoramento de Sensores Iniciado.");
}

void loop() {
    // Simulação de leituras de sensores
    float temperatura = 23.5;
    float umidade = 47.8;
    float pressao = 1013.25;

    // Cria um documento JSON
    StaticJsonDocument<200> doc;
    doc["temperatura"] = temperatura;
    doc["umidade"] = umidade;
    doc["pressao"] = pressao;

    // Serializa o JSON
    String output;
    serializeJson(doc, output);
    Serial.println(output);

    delay(1000);
}

Explicação:

  • Biblioteca ArduinoJson: Facilita a criação e parsing de dados em formato JSON.
  • Criação do JSON: Armazena os valores dos sensores em um documento JSON e o envia via Serial.
  • Monitoramento: O computador pode receber e interpretar os dados estruturados para visualização ou processamento.

9. Conceitos Importantes

9.1 Baud Rate

  • Definição: Taxa de transmissão de dados na comunicação serial, medida em bits por segundo (bps).
  • Considerações:
  • Deve ser consistente entre os dispositivos comunicantes.
  • Baud rates comuns: 9600, 19200, 38400, 57600, 115200.

9.2 Paridade e Bits de Parada

  • Paridade: Método de verificação de erros que adiciona um bit extra para garantir a integridade dos dados.
  • Bits de Parada: Indicam o final de um byte de dados.
  • Configuração: Geralmente configurada como 8N1 (8 bits de dados, sem paridade, 1 bit de parada).

9.3 SoftwareSerial vs. HardwareSerial

  • HardwareSerial:
  • Utiliza a porta serial padrão do Arduino.
  • Mais eficiente e rápido.
  • Limitado a uma única porta serial (exceto em Arduinos com múltiplas portas seriais).

  • SoftwareSerial:

  • Permite criar portas seriais adicionais em pinos digitais.
  • Menos eficiente e pode ser mais lenta.
  • Útil para comunicação com múltiplos dispositivos seriais.

9.4 Parsing de Dados

  • Definição: Processo de interpretar e extrair informações de uma string ou fluxo de dados.
  • Importância: Essencial para organizar e utilizar dados recebidos de forma estruturada.

9.5 Boas Práticas na Comunicação Serial

  • Consistência: Mantenha as configurações de baud rate e parâmetros de comunicação consistentes entre os dispositivos.
  • Delimitação de Dados: Utilize delimitadores claros para separar diferentes partes dos dados.
  • Validação: Sempre verifique e valide os dados recebidos para evitar erros de interpretação.
  • Gerenciamento de Buffer: Evite sobrecarregar o buffer serial, controlando a quantidade e a frequência dos dados enviados.

10. Recursos Adicionais


11. Conclusão do Módulo

Neste módulo, você aprendeu:

  • Conceitos avançados de comunicação serial, incluindo UART, I2C e SPI.
  • Como configurar e utilizar diferentes protocolos de comunicação serial no Arduino.
  • Implementação de comunicação serial entre múltiplos dispositivos Arduino.
  • Utilização da biblioteca SoftwareSerial para criar portas seriais adicionais.
  • Técnicas de transferência e parsing de dados para comunicação eficiente.
  • Integração de comunicação serial com módulos de comunicação como Bluetooth.
  • Praticou com exemplos e exercícios que reforçam o entendimento da comunicação serial avançada.

Você está agora preparado para avançar para o próximo módulo, onde exploraremos Controle de Motores e Atuadores, aprofundando seu conhecimento em automação e controle com Arduino.


12. Próximos Passos

  • Revisar o conteúdo deste módulo e certificar-se de que compreendeu os conceitos apresentados.
  • Completar os exercícios propostos para consolidar o aprendizado.
  • Preparar-se para o Módulo 11: Controle de Motores e Atuadores.

Se tiver dúvidas ou precisar de assistência, não hesite em procurar recursos adicionais ou participar de comunidades de aprendizagem para obter suporte.


Bom trabalho e continue assim!