sábado, 7 de novembro de 2015

Gráfico em tempo real com Qt + QCustomPlot (Real Time Plot using Qt and QCustomplot)

Nessa primeira postagem vamos desenvolver um software em QT/C++ que irá plotar um gráfico em tempo real como mostra a figura abaixo. O código tá disponibilizado no reposiótio: https://github.com/filipecalasans/realTimePlot



Inicialmente nossa fonte de dados será o nosso própio software para facilitar a nossa vida, porém em próximos projetos possa ser que integramos esse software com algum sistema embarcado dotado de ADC (Conversor Analógico-Digital) e com comunicação serial/USB.

Nesse projeto vamos utilizar a framework Qt para C++ que pode ser encontrada no link http://www.qt.io/download/ ou pode ser instalado utilizando o repositórios de pacotes da sua distribuição de Linux, por exemplo, o apt-get caso sua versão seja derivada do debian. Além do Qt, iremos utilizar a biblioteca de plotagem de gráficos QCustomPlot que é disponibilizada sob licença GPL no seguinte link: http://www.qcustomplot.com/index.php/introduction,. Ambos os recursos utilizados possuem bastante documentação disponível na Internet com relação a instalação, portanto não trataremos disso aqui no post.

A escolha de uma aplicação de plotagem de tempo real se deu pelo fato de existir poucos exemplos que mostram a implementação desse caso específico de gráficos. Geralmente os exemplos tratam de gráficos estáticos.

Nossa impleentação seguirá uma arquitetura bastante simples. Mas que pode ser expandida para uma arquitetura mais complexa caso haja necessidade no seu projeto. Basicamente teremos uma janela principal que irá conter:

  • 1 Área de plotagem, que nesse caso será uma QWiget que herdará a QCustomplot.
  • 1 ou mais fontes de dados (PointStream), que será a classe responsável por armazenar os pontos amostrados (nesse caso simulados) e disponibilizar para a área de plotagem quando necessário.




A Classe PointStrem é uma classe com a seguinte interface:


A lista de pontos tem tamanho fixo e prá alocado de MAX_BUFFER_SIZE com o intuíto de evitar perda de performance por alocação de desalocação de memória. Criamos uma função de get e append para termos acesso aos pontos. Note que a função de append descarta os pontos quando o buffer fica cheio, porem nada impede que esses pontos fossem armazenados em arquivo para consulta posterior. A ressalva que temos com essa implementação é que se trata de uma aplicação singlethread, pois tanto a inserção e a remoção de pontos da lista se dá na mesma thread. Aplicações mais sofisticadas em que a captura e exibição dos pontos ocorrem em threads diferentes necessitarão de um tratamento utilizando Mutex, ou algo do gênero.

A Classe PlotArea implementa o gráfico em sí e herda a classe QCustomPlot. No construtor definimos um axisRect (área de plotagem) com os eixos inferior e lateral esquerdo apenas e o
inserimos na posição 0,0 do grid do layout de exibição gráfica.

Para interfacear nossa classe com o mundo externo criamos os métodos de inserção de novas fontes de dados,  que mapeia uma fonte de dados à uma curva (QCPGraph).
Por fim, definimos a função update() que será executada a cada PERIOD_OF_FRAMES para atualizar o gráfico. Essa função requisita um número fixo de pontos (sempre o número de pontos necessários à janela de exibição), porém exibe apenas os pontos necessários para que tenhamos aexibição semelhante a um osciloscópio.

A classe PlotArea foi adicionada na janela MainWindow utilizando o QDesign (Software que é parte do qtcreator para edição de GUI). Para aqueles que não são muito familiarizados com a IDE, o processo é bastante simples.

  1. Adicione uma nova QWidget a UI que vocês deseja.
  2. No menu à esquerda clique com o botão direito sob a linha da QWidget que você acabou de adicionar e selecione promoted widgets. 
  3. Preencha os dados sobre a sua classe PlotArea: Nome da classe e o nome do arquivo. A opção "global include" não precisa ser selecionada pois os arquivos estão no mesmo diretório.
  4. Finalize o processo clicando em Promote.
O que tá por trás de todo o processo poderia ser feito via código fonte, porém para manter o mesmo mais limpo e organizado preferimos realizar utilizando a IDE. Esse processo adiciona uma intância da classe PlotArea à classe que armazena todos os elementos da UI. Essa classe é instanciada sob o nome  Ui::MainWindow *ui nesse exemplo.






Por fim, a classe MainWindow aloca e inicializao os objetos PointStream e adiciona na janela de plotagem.  Um timer com periodo de SAMPLE_GENERATION_PERIOD é utilizado na geração de um sinal senoidal de 2Hz, como pode ser visto na função timerEvent(QTimerEvent *event) e representado pela equação abaixo. Onde, N = número da amostra e Ts é o tempo de amostragem em segundos.



Chegamos ao fim da minha primeira postagem. Espero que tenham gostado do nosso primeiro projeto. No futuro apresento como esse projeto pode ser utilizado para exibir dados amostrados por um sistema ambarcado dotado de ADC.

Abraços e até a próxima.










Primeiro Post


Fala pessoal, essa é a minha primeira postagem no blog Coolcode que tem como objetivo
apresentar alguns projetos pessoais e compartilhar o que tenho aprendido
na minha caminhada como desenvolvedor de Software.

Bom, mas quem sou eu afinal ?

Meu nome é Filipe. Sou formado em Eng. de Computação, pela USP São Carlos,
carinhosamente chamada de CAASO (raça CAASO!!!). Trabalho atualmente como
Engenheiro de Software na área de desenvolvimento de firmwares e software em
Qt/C++. Desde a época de faculdade já mechi com quase todo o espectro
da computação. Posso citar: ondas quadradas da etapa de verificação do Verilog, as baixaria
do assembly 8051 e ARM, os classudos firmwares bare-metal em C,
passando pelo admirável Qt/C++ e pelo nem tanto assim Java. Mais recentemente
descobri umas coisas legais da nova geração de desenvolvimento web e resolvi
arriscar algumas coisas no meu tempo livre.

A idéia desse blog é fazer uma mistura de tudo isso e passar aqui pra vocês um pouco do que
eu aprendi, e do que venho descobrindo nessa minha caminhada no mundo da computação. Se quiserem
conhecer mais sobre mim e o que eu faço, vocês podem acessar o LinkedIn ou o meu Github
através do menu lateral.