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.
- Adicione uma nova QWidget a UI que vocês deseja.
- No menu à esquerda clique com o botão direito sob a linha da QWidget que você acabou de adicionar e selecione promoted widgets.
- 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.
- 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.




Muito obrigado Felipe. Vou testar seus códigos.
ResponderExcluirSaudações de Cuba, meu português não é muito bom, mas gostaria de fazer uma pergunta sobre este código que estou tentando compilar e está faltando arquivos. Estou desenvolvendo um projeto semelhante, mas ele não compila e não consigo verificar sua funcionalidade. Pode me ajudar?? Obrigado.
ResponderExcluir