banner

Porque todo mundo quer automação com display grande!



Mais um vídeo sobre DISPLAY, um assunto que eu gosto demais e, por quê? Com ele é possível melhorar muito a interface com o usuário. Isso porque o usuário da automação precisa ter uma boa indicação visual. Eu trago, então, um exemplo com um display de 7 polegadas com touch capacitivo e um Raspberry Pi com QT Creator, que se trata de uma biblioteca gráfica.


No vídeo de hoje, portanto, apresentamos uma automação com QT Creator utilizando novos componentes e um exemplo de acionamento de servo motores utilizando a saída PWM do Raspberry Pi. Utilizaremos também um módulo de 4 relés na nossa automação.






Recursos usados

·         Raspberry Pi 3 model B+
·         2x Servos Towerpro MG996R
·         Módulo de 4 relés
·         2x lâmpadas
·         Extensão de tomadas
·         Fonte 5V
·         Adaptador de pinos de alimentação arduino
·         Jumpers
·         Protoboard
·         Display 7inch HDMI LCD 7’’ (Touch Screen)
·         Ventilador






Pinout Raspberry Pi 3 Model B





Montagem






Pinos PWM Raspberry Pi 3 Model B

Os pinos PWM no Raspberry Pi 3 são mostrados na figura abaixo. Usamos o canal 0 para um servo motor e o canal 1 para o outro. Devemos nos atentar quanto a GPIO utilizada pelo Wiring Pi (figura à direita), portanto utilizaremos o GPIO1 e GPIO24 é NÃO os pinos de BCM (Broadcom SOC channel) GPIO18 e GPIO19.







Interface do projeto QT



OBS: O componente push button não suporta giffs, portanto utilizamos uma label (lblFan) para a reprodução do giff. Utilizamos também um push button invisível chamado imgFan que fica acima da label e assim podemos trabalhar com o evento de clique. Existe outra forma de fazermos criando uma classe clickable label, mas optamos por não criar essa classe e deixar o código mais simples.



Código


mainwindow.cpp

Declarações e Variáveis

// Bibliotecas padrões
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>

// Biblioteca PWM
#include <softPwm.h>
// Biblioteca Wiring Pi para utilização das funções de GPIO
#include <wiringPi.h>

// Objeto que controlará a exibição do giff (ventilador funcionando)
QMovie *fanGiff;

// Fator de divisão usado para setarmos o clock dos servo motores
const int freq_div = 375;

// Pinos do relé - lampadas, extensão de tomadas (ventilador) e servo motores
const int LAMP1 = 29, LAMP2 = 25, POWER_PLUG = 28, SERVO1 = 1, SERVO2 = 24;

// Assinatura das funções para evitar erro de compilação
void setPins(Ui::MainWindow *);
void updateStatus(Ui::MainWindow *);


Construtor e Destrutor

// Construtor da janela/formulário
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    // Inicialização da user interface (o Qt gera o construtor já com este comando)
    ui->setupUi(this);
    // Setamos o tamanho fixo 1024x600, desabilitando o botão de maximizar
    setFixedSize(1024, 600);
    // Setamos os pinos (pinMode) e configuramos os PWM dos motores
    setPins(ui);
    
    // Instanciamos o objeto QMovie com o giff do ventilador
    fanGiff = new QMovie("/home/pi/Desktop/Automacao/Automacao/images/ventilator2.gif");
    // Setamos o tamanho do giff sendo mesmo o tamanho da label que o receberá
    fanGiff->setScaledSize(ui->lblFan->size());
    // Setamos o giff para a label lblFan
    ui->lblFan->setMovie(fanGiff);
    // Iniciamos o giff (se o ventilador estiver desligado o giff será pausado pela função updateStatus)
    fanGiff->start();
    // Sincronizamos os componentes da tela com as GPIOs dos relés
    updateStatus(ui);
}

// Destrutor
MainWindow::~MainWindow()
{  delete ui;  }


setPins

// Função que inicializa os pinos de saída e configura os PWM dos servo motores
void setPins(Ui::MainWindow *ui)
{
    // Iniciamos a biblioteca wiring, se acontecer algum erro abortamos o programa
    if (wiringPiSetup () == -1)
      exit(1);

    // Setamos os pios de saída
    pinMode(LAMP1, OUTPUT);
    pinMode(LAMP2, OUTPUT);
    pinMode(POWER_PLUG, OUTPUT);

    // Setamos os pinos PWM como PWM_OUTPUT
    pinMode(SERVO1, PWM_OUTPUT); //canal 0
    pinMode(SERVO2, PWM_OUTPUT); //canal 1

    // Configuramos o clock e modo dos servo motores
    pwmSetClock(freq_div);
    pwmSetMode(PWM_MODE_MS);
}


updateStatus

// Função que atualiza os componentes da tela com o estado atual dos pinos dos relés
void updateStatus(Ui::MainWindow *ui)
{
    // Atualiza o componente referente ao ventilador
    if(digitalRead(POWER_PLUG))
        fanGiff->stop();
    else
        fanGiff->start();

    // Atualiza o componente referente a lampada 1
    if(digitalRead(LAMP1))
        changeImageButton(ui->imgLamp1, "lamp_off.png");
    else
        changeImageButton(ui->imgLamp1, "lamp_on.png");

    // Atualiza o componente referente a lampada 2
    if(digitalRead(LAMP2))
        changeImageButton(ui->imgLamp2, "lamp_off.png");
    else
        changeImageButton(ui->imgLamp2, "lamp_on.png");
}


Eventos dos sliders

// Evento de mudança do slide do servo 1
void MainWindow::on_slider1_valueChanged(int value)
{
    // Setamos a label de graus com o novo valor
    ui->lblSignalS1->setText(QString::number(value));

    // Obtemos o valor PWM correspondente
    long ciclo = map(value,0,180,34,120);

    // Setamos o PWM no pino do servo 1
    pwmWrite(SERVO1, ciclo);
}

void MainWindow::on_slider2_valueChanged(int value)
{
    // Setamos a label de graus com o novo valor
    ui->lblSignalS2->setText(QString::number(value));

    // Obtemos o valor PWM correspondente
    long ciclo = map(value,0,180,25,102);

    // Setamos o PWM no pino do servo 2
    pwmWrite(SERVO2, ciclo);
}


Eventos dos botões das lâmpadas

// Evento de clique da lâmpada 1
void MainWindow::on_imgLamp1_clicked()
{   
    // Mudamos a imagem da lâmpada para acesa ou apagada, de acordo com o estado atual do pino
    // Os relés possuem lógica inversa
    // LOW = Ligada
    // HIGH = Desligada
    // Se o estado atual estiver ligado, mudamos para OFF e vice versa
    if(digitalRead(LAMP1) == LOW)
        changeImageButton(ui->imgLamp1, "lamp_off.png");
    else
        changeImageButton(ui->imgLamp1, "lamp_on.png");     

    // Mudamos o estado do pino, ligando ou desligando a lâmpada
    digitalWrite(LAMP1, !digitalRead(LAMP1));
}

// Evento de clique da lâmpada 2, possuí a mesma lógica da função de evento da lâmpada 1
void MainWindow::on_imgLamp2_clicked()
{    
    if(digitalRead(LAMP2) == LOW)
        changeImageButton(ui->imgLamp2, "lamp_off.png");
    else
        changeImageButton(ui->imgLamp2, "lamp_on.png");

    digitalWrite(LAMP2, !digitalRead(LAMP2));
}


changeImageButton

// Função que altera a imagem do push button
// Parametros: Objeto QPushButton, nome do arquivo de imagem
void changeImageButton(QPushButton *btn, char *fileName)
{
    char style[200];
    // Montamos o array com o estilo do botão inserindo a nova imagem no atributo image
    sprintf(style, "background-color: transparent;image: url(/home/pi/Desktop/Automacao/Automacao/images/%s); background: transparent;border: none;", fileName);
    // Setamos o novo estilo do push button
    btn->setStyleSheet(style);
}


Evento do botão do ventilador

void MainWindow::on_imgFan_clicked()
{
    // Iniciamos ou pausamos o giff de acordo com o estado atual do pino
    // Os relés possuem lógica inversa
    // LOW = Ligado
    // HIGH = Desligado
    // Se o estado atual estiver ligado pausamos o giff e se estiver desligado iniciamos o giff
    if(digitalRead(POWER_PLUG) == LOW)
        fanGiff->stop();
    else
        fanGiff->start();

    // Mudamos o estado do pino, ligando ou desligando o ventilador
    digitalWrite(POWER_PLUG, !digitalRead(POWER_PLUG));
}


Evento do checkbox que exibe ou não o cursor do mouse


// Evento de mudança de estado do check box de exibição/ocultação do mouse
void MainWindow::on_ckbShowCursor_stateChanged(int arg1)
{
    // Se estiver checado exibimos o cursor e vice versa
    if(arg1 == Qt::Checked)
        this->setCursor(Qt::ArrowCursor);
    else
    if(arg1 == Qt::Unchecked)
        this->setCursor(Qt::BlankCursor);
}




FAÇA O DOWNLOAD DOS ARQUIVOS






Um comentário:

  1. Vídeo e apresentação de excelente qualidade. Muito bom. Ocorre que, apesar de ter a informação de que todos os desenhos estarem no blog, eu ainda não consegui ver onde estão. É possível a orientação de onde encontrá-los?

    ResponderExcluir

Tecnologia do Blogger.