Início
/
Projetos Arduino
/
Projetos Squids
/
Avançado
/
A02 - Como Controlar Arduino com Python, usando Interface Gráfica e Protocolo Serial Estruturado
A02 - Como Controlar Arduino com Python, usando Interface Gráfica e Protocolo Serial Estruturado
Angelo Luis Ferreira | 20/04/2026
Acessos: 132
Avançado - Projeto 02
Arduino + Python: Controle de LEDs com Interface Gráfica
Objetivo
O objetivo desse projeto é desenvolver um sistema de comunicação bidirecional entre o microcontrolador Arduino Uno e uma aplicação em Python, utilizando comunicação serial USB e um protocolo de aplicação estruturado com delimitadores.

Para isso, vamos criar um sistema completo de controle e monitoramento entre o Arduino Uno e Python, utilizando comunicação serial USB com um protocolo de aplicação estruturado.
Neste projeto, o usuário poderá:
- Controlar dois LEDs (verde e vermelho) diretamente pelo computador;
- Acionar comandos através de uma interface gráfica (GUI) com botões;
- Executar ações como:
- Ligar e desligar LEDs individualmente
- Controlar ambos simultaneamente
- Ativar um modo automático de alternância (pisca alternado a cada 1 segundo)
- Receber respostas do Arduino em tempo real, indicando sucesso ou erro nos comandos enviados
- Encerrar a aplicação com segurança, finalizando a comunicação serial corretamente
A interface gráfica será desenvolvida em Python utilizando a biblioteca Tkinter, permitindo interação via mouse de forma intuitiva, sem necessidade de uso do Monitor Serial da IDE.
O sistema permitirá:
- Controlar dois LEDs (verde e vermelho) via interface gráfica
- Executar comandos individuais e combinados
- Ativar um modo automático de alternância entre LEDs
- Receber respostas do Arduino em tempo real (OK ou ERRO)
- Encerrar a aplicação de forma segura
Além disso, o projeto introduz conceitos fundamentais de sistemas embarcados modernos, como:
- Comunicação não bloqueante
- Parser de comandos com
char[]
- Protocolo textual estruturado
- Integração entre firmware e software desktop
Definições
1. Comunicação Serial
A comunicação serial é um método de transmissão de dados onde os bits são enviados sequencialmente, um após o outro, através de um canal físico (USB, UART, etc.).
No Arduino Uno e Arduino Mega, essa comunicação é feita via interface UART, encapsulada pela USB.
Neste projeto:
- Velocidade: 9600 bps
- Meio físico: USB
- Interface:
Serial
2. Comunicação Bidirecional
É a capacidade de dois sistemas trocarem dados em ambos os sentidos:
Diferente do Projeto 01, aqui o sistema:
- envia comandos
- recebe respostas
- atua com feedback em tempo real
4. Protocolo de Aplicação
É o conjunto de regras que define:
- Como os dados são estruturados
- Como os comandos são interpretados
- Como as respostas são formatadas
Neste projeto, usamos:
<LED:GREEN:ON>
[MODE:ALT]
Características:
- Baseado em texto
- Leve e fácil de expandir
- Independente do meio físico
5. Delimitadores de Mensagem
São caracteres que indicam o início e o fim de um comando.
Utilizados:
| Tipo |
Início |
Fim |
Exemplo |
| LED |
< |
> |
<LED:RED:ON> |
| MODE |
[ |
] |
[MODE:ALT] |
Função:
- Evitar leitura de dados corrompidos
- Permitir parsing seguro
- Separar comandos no fluxo serial
6. Parser de Comandos
É o mecanismo responsável por:
- Receber a mensagem
- Separar seus elementos
- Interpretar ação e parâmetros de cada elemento
No Arduino:
- Implementado com
char[]
- Utiliza
strtok() para separar a string em partes (tokenização)
- Não utiliza
String (evita fragmentação de memória)
7. Comunicação Não Bloqueante
É um modelo onde o sistema continua executando outras tarefas enquanto aguarda eventos (como dados serial ou temporização).
✔ No Arduino:
- Uso de
Serial.available()
- Uso de
millis() (em vez de delay())
✔ No Python:
- Uso de
in_waiting
- Loop com
tkinter.after()
Resultado:
- Interface não trava
- Sistema responde em tempo real
8. Firmware
Firmware é o software embarcado que roda no microcontrolador.
Neste projeto, o firmware:
- Interpreta comandos recebidos
- Controla os LEDs
- Executa lógica de modo alternado
- Retorna respostas ao sistema
9. Interface Gráfica (GUI)
A interface gráfica é responsável pela interação com o usuário.
Implementada em Python com a biblioteca padrão:
Permite:
- Acionar comandos via botões
- Visualizar respostas do Arduino
- Encerrar o sistema com segurança
10. Tratamento de Erros
Mecanismo que garante robustez do sistema diante de falhas.
✔ No Arduino:
ERRO:FORMATO
ERRO:PARAM
ERRO:COMANDO
✔ No Python:
- Exceções na serial
- Validação de resposta
- Feedback visual na interface em tempo real
11. Sistema Orientado a Eventos
Modelo onde o sistema reage a eventos, como:
- Clique de botão (GUI)
- Chegada de dados (serial)
- Temporização (
millis())
Esse padrão é essencial para:
- Sistemas embarcados
- Interfaces gráficas
- Aplicações em tempo real
Fundamentos para:
- IoT
- Automação
- Sistemas embarcados profissionais
Referências
Aplicações
Controle de Dispositivos via Computador, Automação Residencial (Home Automation), Interfaces Supervisórias (Estilo SCADA), Prototipagem de Sistemas IoT, Desenvolvimento de Protocolos de Comunicação, Integração Hardware + Software (Desktop), Sistemas Educacionais e Laboratórios.
Componentes necessários
Referência
|
Componente
|
Quantidade
|
Imagem
|
Observação
|
| Protoboard |
Protoboard 400 pontos |
1 |
 |
No mínimo utilizar protoboard com 400 pontos
|
| Jumpers |
Kit cabos ligação macho / macho |
1 |
 |
|
| Led Difuso 5mm |
LEDs 5mm |
2 |
 |
1 LED Vermelho e 1 LED verde
Você poderá utilizar também LEDs de 3 mm.
|
| Resistor |
Resistor
|
2 |
 |
2 Resistores de 150Ω ou maiores
Se precisar usar outros valores, calcule o resistor apropriado para o led utilizado
|
| Arduino UNO |
Arduino UNO R3 com cabo USB |
1 |
 |
Você poderá utilizar uma placa Arduino MEGA 2560
|
Montagem do Circuito
Conecte os componentes no Protoboard como mostra a figura abaixo. Verifique cuidadosamente os cabos de ligação antes de ligar seu Arduino. Lembre-se que o Arduino deve estar totalmente desconectado da força enquanto você monta o circuito.

Atenção
1. Lembre-se que o LED tem polaridade: O terminal maior tem polaridade positiva e o lado do chanfro tem polaridade negativa.

1.1. Portanto, faça a conexão do Arduino no terminal positivo do led (anodo) e o GND no terminal negativo (catodo).
1.2. Para evitar danos ao led é necessário a inclusão de um resistor de no mínimo 150Ω circuito. Como o resistor é um limitador da corrente elétrica, ele poderá estar conectado no anodo (terminal maior) ou no catodo (terminal menor) do led, tanto faz.
2. Identifique a Porta Serial: Abra o IDE do Arduino e acesse Ferramentas → Porta e você verá a porta identificada.

Observe que na minha conexão a Porta identificada foi COM 4. Veja qual a porta identificada no seu Arduino, anote esse número, pois ele será utilizado no Python.
Instalação do Python
1. Antes de instalar o Python, você poderá verificar se o seu PC já possui o programa instalado. Para isso, abra o terminal (prompt de comando do Windows, por exemplo).
1.1. Digite no terminal: python --version

1.2. Se você não tiver uma resposta e aparecer Python não encontrado, precisará instalar o Python no seu PC.
2. Instalação do Python no PC
2.1. Acesso o site oficial do Python: https://www.python.org/ e clique no botão Downloads

2.2. Clique no link da última versão: Neste exemplo é a versão Python 3.14.3

2.3. Aguarde finalizar o download e clique no arquivo de instalação que foi baixado:

2.4.Clique no botão Install Now depois de ter marcado a opção Add python.exe to PATH.
2.4.1. ⚠ IMPORTANTE: Marque a opção Add python.exe to PATH

2.4.2. Aguarde a finalização da instalação. Se pedir alguma confirmação no Terminal, digite sempre Y (yes).
2.5. No terminal (prompt de comando) verifique novamente se foi instalado digitando: python --version

Instalação da biblioteca pyserial do Python
1. Abra o terminal (prompt de comando do Windows, por exemplo), e digite: pip install pyserial

Obs: O pip (Python Package Index) é o gerenciador de pacotes padrão do Python, utilizado para instalar, atualizar e remover bibliotecas e dependências de terceiros que não fazem parte da biblioteca padrão.
2. Digite Enter e aguarde a instalação. Esse processo pode demorar um pouco.

Código do Projeto (Sketch)
Agora vamos preparar o Arduino para: Receber comandos, Interpretar texto, Executar ação e Responder.
1. Copie e cole o código abaixo no IDE do Arduino:
/*******************************************************************************
*
* Projeto A02: Comunicação Bidirecional Arduino + Python com GUI (interface gráfica)
* ------------------------------------------------------
* Controle de LEDs via protocolo serial estruturado
*
* Autor: Angelo Luis Ferreira
* Data: 16/02/2026
*
* http://squids.com.br/arduino
*
*******************************************************************************/
/*
* PROTOCOLO:
* <LED:GREEN:ON>
* <LED:RED:OFF>
* <LED:ALL:ON>
*
* [MODE:ALT]
* [MODE:STOP]
*
* [SYS:EXIT]
*
* STATUS:
* LED VERDE LIGADO / DESLIGADO
* LED VERMELHO LIGADO / DESLIGADO
* TODOS LEDs LIGADOS / DESLIGADOS
* MODO ALTERNADO ATIVO / PARADO
* ENCERRANDO SISTEMA
*
* ERROS:
* ERRO:FORMATO / ERRO:PARAM / ERRO:COMANDO
*/
// -----------------------------
// DEFINIÇÃO PINOS
// -----------------------------
#define LED_VERDE 8
#define LED_VERMELHO 9
// -----------------------------
// BUFFER SERIAL
// -----------------------------
#define BUFFER_SIZE 50
char buffer[BUFFER_SIZE];
byte indexBuffer = 0;
bool recebendo = false;
// -----------------------------
// MODO ALTERNADO
// -----------------------------
bool modoAlternado = false;
unsigned long tempoAnterior = 0;
bool estado = false;
// -----------------------------
// MENSAGENS DE STATUS
// -----------------------------
const char* statusMsg[] = {
"LED VERDE LIGADO",
"LED VERDE DESLIGADO",
"LED VERMELHO LIGADO",
"LED VERMELHO DESLIGADO",
"TODOS LEDs LIGADOS",
"TODOS LEDs DESLIGADOS",
"MODO ALTERNADO ATIVO",
"MODO ALTERNADO PARADO",
"ENCERRANDO SISTEMA"
};
// -----------------------------
// PROTÓTIPOS DAS FUNÇÕES
// -----------------------------
void enviarStatus(int index);
void lerSerial();
void processarComando(char *cmd);
void processarLED(char *cmd);
void processarMODE(char *cmd);
void processarSYS(char *cmd);
void setLED(char *cor, bool estadoLed);
void pararModo();
void executarModo();
// --------------------------------------------------
void setup() {
pinMode(LED_VERDE, OUTPUT);
pinMode(LED_VERMELHO, OUTPUT);
Serial.begin(9600);
}
// --------------------------------------------------
void loop() {
lerSerial();
executarModo();
}
// --------------------------------------------------
void enviarStatus(int index) {
Serial.println(statusMsg[index]);
}
// --------------------------------------------------
void lerSerial() {
while (Serial.available()) {
char c = Serial.read();
// início do comando
if (c == '<' || c == '[') {
indexBuffer = 0;
recebendo = true;
buffer[indexBuffer++] = c;
continue;
}
if (recebendo) {
if (indexBuffer < BUFFER_SIZE - 1) {
buffer[indexBuffer++] = c;
}
// fim do comando
if (c == '>' || c == ']') {
buffer[indexBuffer] = '\0';
recebendo = false;
processarComando(buffer);
}
}
}
}
// --------------------------------------------------
void processarComando(char *cmd) {
if (cmd[0] == '<') {
processarLED(cmd);
}
else if (cmd[0] == '[') {
if (strstr(cmd, "MODE")) processarMODE(cmd);
else if (strstr(cmd, "SYS")) processarSYS(cmd);
else Serial.println("ERRO:COMANDO");
}
else {
Serial.println("ERRO:COMANDO");
}
}
// --------------------------------------------------
void processarLED(char *cmd) {
char *token = strtok(cmd, "<:>");
if (!token || strcmp(token, "LED") != 0) {
Serial.println("ERRO:FORMATO");
return;
}
char *cor = strtok(NULL, "<:>");
char *acao = strtok(NULL, "<:>");
if (!cor || !acao) {
Serial.println("ERRO:PARAM");
return;
}
bool estadoLed;
if (strcmp(acao, "ON") == 0) estadoLed = true;
else if (strcmp(acao, "OFF") == 0) estadoLed = false;
else {
Serial.println("ERRO:PARAM");
return;
}
setLED(cor, estadoLed);
}
// --------------------------------------------------
void setLED(char *cor, bool estadoLed) {
if (strcmp(cor, "GREEN") == 0) {
digitalWrite(LED_VERDE, estadoLed);
enviarStatus(estadoLed ? 0 : 1);
}
else if (strcmp(cor, "RED") == 0) {
digitalWrite(LED_VERMELHO, estadoLed);
enviarStatus(estadoLed ? 2 : 3);
}
else if (strcmp(cor, "ALL") == 0) {
digitalWrite(LED_VERDE, estadoLed);
digitalWrite(LED_VERMELHO, estadoLed);
enviarStatus(estadoLed ? 4 : 5);
}
else {
Serial.println("ERRO:PARAM");
}
}
// --------------------------------------------------
void processarMODE(char *cmd) {
char *token = strtok(cmd, "[:]");
if (!token || strcmp(token, "MODE") != 0) {
Serial.println("ERRO:FORMATO");
return;
}
char *modo = strtok(NULL, "[:]");
if (!modo) {
Serial.println("ERRO:PARAM");
return;
}
if (strcmp(modo, "ALT") == 0) {
modoAlternado = true;
enviarStatus(6);
}
else if (strcmp(modo, "STOP") == 0) {
pararModo();
}
else {
Serial.println("ERRO:PARAM");
}
}
// --------------------------------------------------
void processarSYS(char *cmd) {
char *token = strtok(cmd, "[:]");
if (!token || strcmp(token, "SYS") != 0) {
Serial.println("ERRO:FORMATO");
return;
}
char *acao = strtok(NULL, "[:]");
if (!acao) {
Serial.println("ERRO:PARAM");
return;
}
if (strcmp(acao, "EXIT") == 0) {
enviarStatus(8);
}
else {
Serial.println("ERRO:PARAM");
}
}
// --------------------------------------------------
void pararModo() {
modoAlternado = false;
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_VERMELHO, LOW);
enviarStatus(7);
}
// --------------------------------------------------
void executarModo() {
if (modoAlternado && millis() - tempoAnterior >= 1000) {
tempoAnterior = millis();
estado = !estado;
digitalWrite(LED_VERDE, estado);
digitalWrite(LED_VERMELHO, !estado);
}
}
2. Verifique se o código está funcionando corretamente usando o Monitor Serial (opcional).
2.1. Faça o upload do código para a placa do Arduino.

2.2. Abra o Monitor Serial. Verifique se a porta de comunicação está correta com o que você verificou antes.
2.3. Digite os comandos:
<LED:GREEN:ON> → Liga o LED verde
<LED:GREEN:OFF> → Desliga o LED verde
<LED:RED:ON> → Liga o LED vermelho
<LED:RED:OFF> → Desliga o LED vermelho
<LED:ALL:ON> → Liga os dois LEDs
<LED:ALL:OFF> → Desliga os dois LEDs
[MODE:ALT] → Ativa o modo alternado (pisca)
[MODE:STOP] → Para o modo alternado
[SYS:EXIT] → Encerra a aplicação Python
2.4. Você deverá receber as mensagens de status também:

Código Python (no computador)
1. Crie uma pasta com o nome C:\Arduino\Python\
2. Utilize um editor de código como VS Code, NetBeans, PyCharm entre outros, ou mesmo o bloco de notas do Windows. Copie o código Python abaixo e salve como gui_arduino.py dentro da pasta que você criou.
2.1. Se você utilizar um editor de texto, tipo bloco de notas, renomeie o arquivo de .txt para .py
2.2. O código Python foi cuidadosamente documentado com comentários técnicos que descrevem sua arquitetura, fluxo de execução e a função de cada instrução, facilitando a compreensão e a manutenção do projeto.
import serial
import tkinter as tk
# -----------------------------
# CONFIGURAÇÃO
# -----------------------------
PORTA = 'COM4'
BAUDRATE = 9600
# -----------------------------
# Inicializa comunicação serial
# -----------------------------
try:
arduino = serial.Serial(PORTA, BAUDRATE)
except Exception as e:
print("Erro ao abrir porta:", e)
exit()
# -----------------------------
# ENVIO DE COMANDOS
# -----------------------------
def enviar(cmd):
try:
arduino.write((cmd + '\n').encode())
except Exception as e:
status_label.config(text=f"ERRO ENVIO: {e}", fg="red")
# -----------------------------
# LEITURA SERIAL (não bloqueante)
# -----------------------------
def ler_serial():
try:
while arduino.in_waiting > 0:
resposta = arduino.readline().decode(errors='ignore').strip()
if not resposta:
continue
# Tratamento de erro
if "ERRO" in resposta:
status_label.config(text=resposta, fg="red")
# Encerramento remoto
elif "ENCERRANDO SISTEMA" in resposta:
status_label.config(text=resposta, fg="blue")
janela.after(500, fechar_app)
# Status normal
else:
status_label.config(text=resposta, fg="green")
except Exception as e:
status_label.config(text=f"ERRO SERIAL: {e}", fg="red")
janela.after(100, ler_serial)
# -----------------------------
# COMANDOS (LED)
# -----------------------------
def verde_on(): enviar("<LED:GREEN:ON>")
def verde_off(): enviar("<LED:GREEN:OFF>")
def red_on(): enviar("<LED:RED:ON>")
def red_off(): enviar("<LED:RED:OFF>")
def all_on(): enviar("<LED:ALL:ON>")
def all_off(): enviar("<LED:ALL:OFF>")
# -----------------------------
# COMANDOS (MODE)
# -----------------------------
def alt(): enviar("[MODE:ALT]")
def stop(): enviar("[MODE:STOP]")
# -----------------------------
# ENCERRAMENTO
# -----------------------------
def sair():
enviar("[SYS:EXIT]")
def fechar_app():
try:
arduino.close()
except:
pass
janela.destroy()
# -----------------------------
# INTERFACE GRÁFICA
# -----------------------------
janela = tk.Tk()
janela.title("Controle Arduino")
janela.geometry("250x350")
# LEDs
tk.Button(janela, text="Verde ON", command=verde_on).pack(pady=2)
tk.Button(janela, text="Verde OFF", command=verde_off).pack(pady=2)
tk.Button(janela, text="Vermelho ON", command=red_on).pack(pady=2)
tk.Button(janela, text="Vermelho OFF", command=red_off).pack(pady=2)
tk.Button(janela, text="Ambos ON", command=all_on).pack(pady=2)
tk.Button(janela, text="Ambos OFF", command=all_off).pack(pady=2)
# Modos
tk.Button(janela, text="Modo Alternado", command=alt).pack(pady=5)
tk.Button(janela, text="Parar", command=stop).pack(pady=2)
# Sair
tk.Button(janela, text="SAIR", command=sair, fg="white", bg="red").pack(pady=10)
# Status
status_label = tk.Label(janela, text="Status: ---", wraplength=200)
status_label.pack(pady=10)
# Inicia leitura contínua
ler_serial()
janela.mainloop()
⚠ ATENÇÃO: Se necessário, altere 'COM4' para a porta que você identificou no início do projeto.
3. Reset automático ao abrir a porta serial
Ao abrir a porta serial no Python, o Arduino normalmente é reiniciado automaticamente. Isso ocorre devido ao sinal DTR (Data Terminal Ready), utilizado pela interface USB-Serial.
Por esse motivo, é recomendado adicionar uma pequena pausa após abrir a conexão:
time.sleep(2)
Esse tempo permite que o Arduino finalize sua inicialização antes de receber comandos, evitando falhas na comunicação inicial.
4. Tratamento de erros na conexão serial
O código utiliza try/except para tratar possíveis erros ao abrir a porta serial.
Isso evita que o programa seja encerrado inesperadamente em situações como:
- Porta incorreta
- Arduino desconectado
- Porta já em uso
Com isso, o usuário recebe uma mensagem clara para corrigir o problema.
5. Encerramento controlado do programa
Foi implementado o comando:
Esse comando permite que o Python e o Arduino encerrem a comunicação de forma organizada.
Ao acioná-lo, o Arduino responde com: ENCERRANDO SISTEMA
E o Python finaliza a aplicação automaticamente.
Esse recurso evita encerramentos bruscos e torna o sistema mais robusto.
Executando o Projeto de Comunicação Bidirecional com Interface Gráfica
Após montar o circuito, carregar o código no Arduino e configurar o ambiente no Python, é hora de executar o projeto e observar a comunicação funcionando na prática.
1. Antes de executar o projeto, verifique se:
- O Arduino está conectado no computador via cabo USB
- O Código (sketch) do IDE do Arduino foi carregado usando o Upload.
- O Monitor Serial está fechado
- Se a Porta identificada (ex:
COM3, COM4, etc.) está correta no script do Python
- Se Baud rate está com 9600 (no monitor serial)
2. Abra o terminal (prompt do Windows) e execute diretamente o arquivo.
3. Vá até a pasta que você criou o arquivo, digite: cd C:\Arduino\Python

5. Utilize os botões da interface:
A interface permite enviar comandos diretamente ao Arduino:
- Botões de controle dos LEDs
- Ativação do modo alternado
- Parada do modo
- Encerramento do sistema
Cada clique envia um comando estruturado para o Arduino, como:
<LED:GREEN:ON>
6. Observe o retorno do Arduino
Após receber o comando, o Arduino processa a ação e envia uma resposta pela serial.
Essa resposta é exibida na interface gráfica, como: LED VERDE LIGADO

Isso caracteriza uma comunicação bidirecional, onde:
- Python envia comandos
- Arduino executa
- Arduino responde
- Python exibe o resultado
7. Teste o modo alternado
Ao clicar no botão Modo Alternado será enviado o código estruturado para o Arduino:
Os LEDs passam a alternar automaticamente a cada 1 segundo.
Para interromper clique no botão Parar que enviará o código:
[MODE:STOP]
8. Encerramento do sistema
Ao clicar no botão SAIR, o seguinte comando é enviado:
[SYS:EXIT]
O Arduino responde: ENCERRANDO SISTEMA e o Python finaliza a aplicação de forma segura.
Conclusão
Com esse fluxo, você tem um sistema completo funcionando:
Interface gráfica → envia comando → Arduino executa → retorna status → interface atualiza
Esse modelo é a base para sistemas reais de automação, IoT e interfaces supervisórias.
O anúncio abaixo ajuda a manter o Squids Arduino funcionando
Comentários