Projetos

Controle do Arduino via GUI em Python

Eletrogate 21 de junho de 2021

Introdução

Hoje desenvolveremos um sistema que nos permitirá controlar o Arduino e nossos componentes de uma forma diferente. Iremos criar um projeto que fará com que controlemos, recebemos e  enviemos os dados ao Arduino via PySerial, controlando isso através de uma interface gráfica (GUI) feita em Python, pelo módulo PySimpleGUI.

O módulo PySimpleGUI é uma ótima alternativa para criar interfaces gráficas em Windows, Linux e MacOS, já que utiliza como base o Tkinter. O PySerial irá receber  e enviar comandos para o Arduino de forma Serial, via cabo USB. Logo, para o Arduino, será como se estivéssemos utilizando o Monitor Serial.

Para exemplificar as funções, iremos incluir em nosso projeto um servo-motor, três leds, um buzzer, e um módulo relé, sendo todos controlados pela GUI.


Módulos do Python

Para executar o projeto você deve ter o Python instalado em seu computador, algo que pode ser feito no site oficial deste. Para instalar, basta ir em downloads e escolher a sua plataforma. A instalação é rápida e é do tipo “next, next, finnish”, entretanto, em uma etapa, deve-se prestar muita atenção. Nela, é de extrema importância que você marque a opção “Add Python to PATH”. Após isso, já pode clicar em “Install Now”.

PySerial

Este módulo do Python faz com que seu computador se comunique via serial com algum outro dispositivo conectado que suporte este tipo de comunicação, não necessariamente o Arduino.

Esta biblioteca se conecta com uma das portas USB do computador, sendo possível escolher a porta e o baud-rate. Após isso, temos acesso a comandos tanto de leitura dos dados recebidos, quanto de envio de outros comandos. Utilizaremos apenas o primeiro em nosso projeto.

Esta biblioteca está disponível para Linux, MacOS e Windows, e pode ser instalada via Instalador de Pacotes do Python, o “pip”. Para isso, abra em seu computador o Prompt de Comando e digite o comando abaixo.

pip install pyserial

PySimpleGUI

Este é um dos módulos mais simples ao se trabalhar com interfaces gráficas, já que ele foi desenvolvido com base no Tkinter, criando comandos simples na hora de juntar componentes para o layout da tela.

Para utilizá-la, normalmente cria-se um layout em formato de matriz, sendo cada linha uma lista dentro da lista “mãe” do layout. Esta biblioteca permite a customização de todos os componentes, além de disponibilizar temas prontos, que você pode incluir no seu script. Para conhecer os temas, rode o código abaixo em seu ambiente de desenvolvimento, já com o módulo instalado.

import PySimpleGUI as sg
sg.theme_previwer()

A biblioteca está disponível para Linux, MacOS e Windows, e pode ser instalado pelo Instalador de Pacotes do Python, através do comando abaixo, assim como na biblioteca anterior.

pip install pysimplegui

 


Materiais Necessários para o Projeto Controle do Arduino via GUI em Python

Os materiais a serem utilizados estão indicados abaixo. Para o projeto, foi utilizado o Arduino Nano, porém, com o Uno também funcionaria. O sistema foi montado em uma protoboard de 830 pontos e foram utilizados jumpers para a conexão dos componentes.

cta_cart


Desenvolvimento

O desenvolvimento do projeto será dividido em duas grandes partes, na primeira, criaremos nossa interface gráfica e nosso script no Python. Na segunda, iremos desenvolver a parte do Arduino, onde criaremos o circuito.


Interface gráfica

Para o nosso projeto, criaremos uma interface bem simples, com alguns elementos de texto para dividir a tela e identificar algumas funções. Utilizaremos botões para enviar os comandos ao Arduino, sendo 3 botões para os leds, 5 para o controle dos ângulos do servo-motor, um para o buzzer e outro para o Relé.

Utilizaremos como base da nossa GUI o esquema abaixo.


Script em Python

A estrutura do nosso programa será fundamentada basicamente em 3 partes. Na primeira, criaremos uma função para o programa apenas avançar quando estivermos conectados ao Arduino. Após isso, iniciaremos a nossa interface, e por fim, criaremos um laço que irá coletar os dados que selecionamos na nossa GUI.

Nota-se a presença de muitos if’s e elif’s no código, isso ocorre pois temos que checar se vários botões estão sendo pressionados, criando várias condicionais, já que, por enquanto, o Python não dispõe de uma função de switch/case.

Os comandos a serem enviados serão baseados em caracteres e estão organizados segundo a relação abaixo:

  • a = led 1
  • b = led 2
  • c = led 3
  • d =  0° (servo-motor)
  • e = 45° (servo-motor)
  • f = 90° (servo-motor)
  • g = 135° (servo-motor)
  • h = 180° (servo-motor)
  • i = buzzer
  • j = relé

Código:

'''
Controlando o Arduino via GUI em Python
Autor: Miguel Sena
Blog Eletrogate: https://blog.eletrogate.com/
'''

from PySimpleGUI import * #Importa todos os comandos da biblioteca para a GUI   
import serial as srl #Importa a biblioteca pyserial
from time import sleep #Importa a biblioteca para criar delays no código

while True: #Laço para conexão com o Arduino
    try: #Tenta se conectar ao Arduino
        arduino = srl.Serial('COM7', 9600) #Cria um elemento conectado a porta COM7
        arduino.flush()
        break

    except Exception: #Se não for possível, imprime a mensagem e dá um delay de 1 segundo
        print('Não foi possível se conectar ao Arduino')
        sleep(1)

theme('Reddit') #Define o tema da GUI

layout = [ #Matriz do nosso layout
    [Text('Leds')], #Texto
    [Button('Led 1', size = (12, 1)), Button('Led 2', size = (12, 1)), Button('Led 3', size = (12, 1))], #Botões para os leds
    [Text('Servo-motor')], #Texto
    [Button('0°', size = (6, 1)), Button('45°', size = (6, 1)), Button('90°', size = (6, 1)), Button('135°', size = (6, 1)), Button('180°', size = (6, 1))], #Botões para o servo-motor
    [Text('Outros')], #Texto
    [Button('Buzzer', size = (12, 1)), Button('Relé', size = (12, 1))] #Botões para o relé e para o buzzer    
]

janela = Window('Controlador', layout) #Cria a janela

while True: #Laço para o envio do comandos
    eventos, valores = janela.Read() #Leitural dos valores e eventos da tela
    cmd = '' #Comando a ser enviado

    if eventos == WINDOW_CLOSED: #Checa se a janela é fechada
        break
    
    #Cerifica quais botões foram apertados
    if eventos == 'Led 1':
        cmd = 'a'

    elif eventos == 'Led 2':
        cmd = 'b'

    elif eventos == 'Led 3':
        cmd = 'c'

    elif eventos == '0°':
        cmd = 'd'

    elif eventos == '45°':
        cmd = 'e'

    elif eventos == '90°':
        cmd = 'f'

    elif eventos == '135°':
        cmd = 'g'
    
    elif eventos == '180°':
        cmd = 'h'

    elif eventos == 'Buzzer':
        cmd = 'i'

    elif eventos == 'Relé':
        cmd = 'j'
    
    arduino.write(cmd.encode()) #Envia o comando
    arduino.flush() #Limpa o serial

 


Circuito do projeto

O circuito do nosso projeto está representado abaixo. Ao criar o esquemático, não havia o módulo relé que utilizaremos, portanto, ele foi substituído pelo led laranja no esquema, mas isso não irá alterar o nosso projeto.


Script do Arduino

O código abaixo foi utilizado para fazer com que o Arduino seja controlado. Como enviaremos os comandos via serial, se utilizarmos o próprio Monitor Serial do Arduino, já poderemos controlar os nossos componentes. Ele foi feito baseado em uma estrutura de switch/case, que irá criar uma série de condicionais para checar os comandos recebidos, assim como foi feito no nosso script de python.

/*
Controlando o Arduino via GUI em Python
Autor: Miguel Sena
Blog Eletrogate: https://blog.eletrogate.com/
*/

#include <Servo.h>                    //Inclui a biblioteca do servo-motor

#define led1 2                        //Define os pinos dos componentes
#define led2 3
#define led3 4
#define buzzer 5
#define rele 6

byte estado_led1 = 0;                 //Define as variáveis de estado
byte estado_led2 = 0;
byte estado_led3 = 0;
byte estado_rele = 1;

char cmd;                             //Declara a variável dos comandos a serem recebidos
byte angulo = 0;                      //Declara a variável do ângulo do servo-motor

Servo s;                              //Cria um objeto do tipo "Servo"

void setup() {
  pinMode(led1, OUTPUT);              //Define os pinos dos componentes como "OUTPUT"
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(rele, OUTPUT);

  Serial.begin(9600);                 //Inicia o Monitor Serial

  s.attach(7);                        //Define o pino do servo-motor
  s.write(angulo);                    //Põe o servo-motor na posição 0
}

void loop() {
  cmd = Serial.read();                //Lê os dados do Monitor Serial e os anexa a variável "cmd"

  switch (cmd) {                      //Verifica as variações dos dados recebidos
    case 'a':
      estado_led1 = !estado_led1;     //Inverte os valores de estado do led1 se o valor recebido for "a"
      break;

    case 'b':
      estado_led2 = !estado_led2;     //Inverte os valores de estado do led2 se o valor recebido for "b"
      break;

    case 'c':
      estado_led3 = !estado_led3;     //Inverte os valores de estado do led3 se o valor recebido for "c"
      break;

    case 'd':
      angulo = 0;                     //Define o ângulo do motor para 0°
      break;

    case 'e':
      angulo = 45;                    //Define o ângulo do motor para 45°
      break;

    case 'f':
      angulo = 90;                    //Define o ângulo do motor para 90°
      break;

    case 'g':
      angulo = 135;                   //Define o ângulo do motor para 135°
      break;

    case 'h':
      angulo = 180;                   //Define o ângulo do motor para 180°
      break;

    case 'i':                         
      digitalWrite(buzzer, HIGH);     //Ativa o buzzer e desativa-o após 1/4 segundo
      delay(250);
      digitalWrite(buzzer, LOW);
      break;

    case 'j':
      estado_rele = !estado_rele;     //Inverte o estado do led
      break;

    default:                          //Sempre que um comando for recebido, todos os componentes são atualizados com seus estados, além do servo-motor ter seu ângulo atualizados
      digitalWrite(led1, estado_led1);
      digitalWrite(led2, estado_led2);
      digitalWrite(led3, estado_led3);
      digitalWrite(rele, estado_rele);
      s.write(angulo);
  }
}

 


Resultado final

Como você pode ver, todo o sistema está funcionando corretamente, com os botões ligando e desligando os componentes, assim como alterando os ângulos do servo-motor.


Conclusão

Como você pôde ver, é bem simples criar interfaces gráficas utilizando Python e implementá-las em seus projetos, não somente com Arduino. Para aprimorar este projeto, é possível incluir mais atuadores e sensores para os dados serem lidos e impressos em nossa GUI. Portanto, você pode, agora, inserir estas interfaces em seus projetos, aumentando ainda mais o nível e tornando-o cada vez mais imersivo para o usuários. 

Além disso, é possível também alterar a nossa interface gráfica, mudando as cores, o layout e as funcionalidades, como, por exemplo, controlar o brilho do led  ou os ângulos os servo-motor por um “slider”.

Você pode também, ao utilizar o módulo PySerial, controlar funções no seu computador utilizando o Arduino, que enviará comandos impressos no Monitor Serial e que poderão ser lidos pelo módulo, que pode ativar alguma função pré-programada do seu computador.

Portanto, observa-se que o Arduino e o Python são poderosas ferramentas se utilizadas em conjunto. Se tiver alguma dúvida, deixe nos comentários.


Sobre o Autor

 


Miguel Sena
@arduuno

Estudante e hobbista na parte de eletrônica e programação. Gosto de desenvolver projetos no Arduino e ESP-32 voltados á robótica e automação residencial, e de desenvolver projetos em Python, assim como a integração dele com o Arduino.


Eletrogate

21 de junho de 2021

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!