20 de janeiro de 2022

Do bit Ao Byte

Embarcados, Linux e programação

Sensor de cores TCS35725 – visualizador gráfico

visualizador gráfico

No artigo anterior discorri a respeito desse sensor de cores, utilizando um sketch de exemplo da própria biblioteca. Eu gostaria de ter feito um video mostrando a correspondência em um LED RGB, mas (não por acaso) não encontrei meus LEDs RGB. Então resolvi fazer um programa gráfico pra ler no computador o resultado da leitura do sensor e exibir em um color picker.

Programa em Qt

Para programar interfaces gráficas, eu sempre utilizo o Qt, que é um framework de C++, mas que facilita tanto, mas tanto que nem parece programação C++ de tão simples e tão rápido. Pra ter uma ideia, levei menos de 2 horas para escrever esse programa, mas isso porque dei uma pesquisada antes em quais recursos eu iria utilizar. De código mesmo, o programa tem umas 80 linhas no máximo.

O Qt é multiplataforma, você pode utilizá-lo para programar para Windows, Linux, BSDs, MAC, Android, Raspberry etc. O mais legal é que você pode fazer no seu computador pessoal, executar, testar e depois só compilar na plataforma de destino (ou fazer cross-compiling).

Download

Dê uma passada pelo site do Qt e baixe a versão para Windows, se for sua plataforma. Ainda, você pode baixar um instalador para Linux, ou instalar a partir dos repositórios de sua distribuição.


Existe versão paga se desejar modificar o código do Qt em sí, mas você faz qualquer coisa com a versão opensource.

Programa pronto

Se quiser baixar esse programa de exemplo que fiz, pegue-o em meu repositório no github.

Bugs

Tem dois bugs, um é um pico que de vez em quando dá na cor verde. O outro era esperado, porque eu iniciei a serial dentro do fluxo da janela principal do programa, mas fiz de propósito porque não quis escrever uma thread para essa tarefa simples. Nesse caso, a janela fica bloqueada pela thread da serial, mas como essa tarefa está com o controle da janela, a aplicação de cores na paleta acontece sem maiores complicações.

Recursos utilizados

Só pra ter uma ideia da simplicidade, estou colocando apenas o código da MainWindow com alguns comentários.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /*Uma instância do controlador da porta serial*/
    this->serialPort = new QSerialPort;

    QStringList ports;

    //pegar portas disponiveis e alimentar o combobox
    const auto serialPortInfos = QSerialPortInfo::availablePorts();
    //criar uma lista com as portas disponíveis para alimentar o combobox
    int i = 0;
    for (const QSerialPortInfo &serialPortInfo : serialPortInfos) {
        ports.insert(i, serialPortInfo.portName());
        i++;
    }
    //alimentar o combobox com a lista de portas
    ui->comboBox_port->insertItems(0,ports);

    //criar lista de velocidades pro combobox
    QStringList bauds;
    bauds << "9600" << "19200" << "38400" << "57600" << "115200";
    ui->comboBox_baud->insertItems(0,bauds);

    //mostrar o diálogo de cores, que é um widget pronto
    this->showColor = new QColorDialog;
    this->showColor->show();

    //esse recurso se chama SIGNALS&SLOTS, que pretendo falar a respeito
    //fazendo tutoriais de Qt em video
    connect(this,SIGNAL(startReading(bool)),this,SLOT(mySerialReader()));
    connect(ui->pushButton_connect,SIGNAL(clicked(bool)),this,SLOT(connectToSerial()));
}

//método executado quando clicar em "Conectar"
void MainWindow::connectToSerial()
{
    if (this->isConnected){
        this->serialPort->close();
        ui->label_status->setText("Não conectado");
        this->isConnected = false;
        ui->pushButton_connect->setText("Conectar");
        return;
    }
    //configurar a porta serial
    this->serialPort->setPortName(ui->comboBox_port->currentText());
    this->serialPort->setBaudRate(ui->comboBox_baud->currentText().toUInt());

    //conectar à porta serial
    if (!this->serialPort->open(QIODevice::ReadOnly)){
        ui->label_status->setText("Falha ao tentar conectar :-(");
        return;
    }
    ui->label_status->setText("Conectado! :-)");
    ui->pushButton_connect->setText("Desconectar");
    this->isConnected = true;
    emit startReading(true);
}

//método para fazer a leitura da porta serial e atribuir a cor
//ao color picker.
void MainWindow::mySerialReader()
{
    QByteArray readData = this->serialPort->readAll();
    while (this->serialPort->waitForReadyRead(5000)){
        readData = this->serialPort->readAll();
        if (readData.contains("\r\n")){

            readData = readData.replace("\r\n","");
            QStringList TCS;
            TCS << QString(readData).split(" ");
            qDebug() << TCS;
            if (TCS.length() == 3){
                QColor myColor;
                myColor.setBlue(TCS.at(2).toInt());
                myColor.setRed(TCS.at(0).toInt());
                myColor.setGreen(TCS.at(1).toInt());
                this->showColor->setCurrentColor(myColor);
            }

        }
    }
}

//destrutor da classe
MainWindow::~MainWindow()
{
    delete ui;
}

Repare que o programa ficou mais ou menos do mesmo tamanho que o programa para o Arduino (falando em linhas de código, claro).

Quer aprender Qt?

Não sou nenhum guru em Qt, mas já fiz coisas interessantes e pensei em fazer videos tutoriais desde o básico, para interagirmos com Raspberry, Arduino, ESP, MIPS etc. Podemos fazer a comunicação por SSH, serial, MQTT etc.

Se tiver interesse, se inscreva em nosso canal no Youtube e deixe seu like ou comentário (ou preferencialmente os dois) para que eu tenha um feedback sobre essa ideia de tutoriais de programação em Qt.

No arduino

No Arduino, utilizei o seguinte código, baseado no sketch de exemplo:

#include <Wire.h>
#include "Adafruit_TCS34725.h"

// Pick analog outputs, for the UNO these three work well
// use ~560  ohm resistor between Red & Blue, ~1K for green (its brighter)
#define redpin 3
#define greenpin 5
#define bluepin 6
// for a common anode LED, connect the common pin to +5V
// for common cathode, connect the common to ground

// set to false if using a common cathode LED
#define commonAnode true

// our RGB -> eye-recognized gamma color
byte gammatable[256];


Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

void setup() {
  Serial.begin(115200);

  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1); // halt!
  }
  
  // use these three pins to drive an LED
  pinMode(redpin, OUTPUT);
  pinMode(greenpin, OUTPUT);
  pinMode(bluepin, OUTPUT);
  
  // thanks PhilB for this gamma table!
  // it helps convert RGB colors to what humans see
  for (int i=0; i<256; i++) {
    float x = i;
    x /= 255;
    x = pow(x, 2.5);
    x *= 255;
      
    if (commonAnode) {
      gammatable[i] = 255 - x;
    } else {
      gammatable[i] = x;      
    }
    //Serial.println(gammatable[i]);
  }
}


void loop() {
  uint16_t clear, red, green, blue;

  tcs.setInterrupt(false);      // turn on LED

  delay(60);  // takes 50ms to read 
  
  tcs.getRawData(&red, &green, &blue, &clear);

  tcs.setInterrupt(true);  // turn off LED

  // Figure out some basic hex code for visualization
  uint32_t sum = clear;
  float r, g, b;
  r = red; r /= sum;
  g = green; g /= sum;
  b = blue; b /= sum;
  r *= 256; g *= 256; b *= 256;
  Serial.print((int)r);
  Serial.print(" ");
  Serial.print((int)g);
  Serial.print(" ");
  Serial.println((int)b);

  analogWrite(redpin, gammatable[(int)r]);
  analogWrite(greenpin, gammatable[(int)g]);
  analogWrite(bluepin, gammatable[(int)b]);
}

No artigo anterior discorro sobre os detalhes da biblioteca.

Onde comprar o sensor de cores?

Esse sensor de cores está disponível no Baú da Eletrônica, cujo sensor escrevi o tutorial introdutório nesse outro artigo.  Achei ele bem interessante e mesmo sem ter feito um acoplamento, o resultado da detecção está sendo bastante satisfatório!

Video

Fiz um video utilizando os objetos da imagem abaixo:

visualizador gráfico

Da esquerda para a direita, fui colocando os objetos sobre o sensor de cores (à direita da imagem). O resultado você vê nesse video.

Siga-nos no Do bit Ao Byte no Facebook.

Prefere twitter? @DobitAoByte.

Inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Nossos grupos:

Arduino BR – https://www.facebook.com/groups/microcontroladorarduinobr/
Raspberry Pi BR – https://www.facebook.com/groups/raspberrybr/
Orange Pi BR – https://www.facebook.com/groups/OrangePiBR/
Odroid BR – https://www.facebook.com/groups/odroidBR/
Sistemas Embarcados BR – https://www.facebook.com/groups/SistemasEmbarcadosBR/

Sistemas Eletrônicos – https://www.facebook.com/groups/544679592355388/
MIPS BR – https://www.facebook.com/groups/MIPSBR/
Do Bit ao Byte – https://www.facebook.com/groups/dobitaobyte/

Próximo post a caminho!