Objetivo do Projeto
Algumas escolas do Brasil, em época de eleição, realizam projetos com os alunos visando o ensino da cidadania e democracia para que os alunos compreendam seus direitos e deveres desde cedo. Os projetos também apresentam as características fundamentais das eleições ensinando aos alunos a função das eleições, dos votos e o papel que cada tipo de candidato exerce e seus compromissos com a sociedade.
Apesar de algumas escolas proporcionarem uma experiência de eleição empolgante para seus alunos, existe um aspecto que ainda é pouco ou quase nada explorado, que é a votação em si. Muitas escolas utilizam o método de cédulas de papel para realização dos votos e algumas outras utilizam-se de um computador com software para realização dos votos.
Foi aí que surgiu a ideia de melhoria do processo de votação visando torná-lo mais fácil, prático, empolgante e o mais próximo da realidade possível, para que os alunos realmente experimentassem como seria votar em uma Urna Eletrônica.
E para colocar essa ideia em prática, um sistema embarcado foi desenvolvido juntando recursos de hardware e software e um pouco de programação, resultando em um dispositivo que se assemelha muito a uma Urna Eletrônica utilizada em eleições. No decorrer do artigo será detalhado um pouco mais sobre os componentes técnicos deste projeto de Urna Eletrônica Educativa.
Aviso: Um dos crimes eleitorais previstos em lei é o de Fabricar, mandar fabricar e fornecer (ainda que gratuitamente), subtrair ou guardar urnas, objetos ou papéis de uso exclusivo da Justiça Eleitoral. O texto abaixo nao visa ensinar ninguem a fabricar uma Urna Eletronica. Trata-se apenas de uma forma de ensinar como sistemas eletronicos podem ser construidos e a finalidade deste projeto foi mostrar para as crianças como seria votar.
Componentes de Hardware
A Urna Educativa contém em seu núcleo um computador embarcado Raspberry Pi 2 e é nele que é executada a aplicação. Utilizou-se do display touch oficial da Raspberry Pi que tem 7” e contém uma placa de interface.
Para tornar o projeto parecido com original e também para melhor aproveitar a área gráfica da tela, optou-se por utilizar um teclado numérico USB para entrada dos dígitos. Esse tipo de teclado funciona “plug-and-play” na Raspberry Pi. A Urna Educativa também conta com alguns efeitos sonoros e para isso foram utilizadas caixas de som USB que também funcionam “plug-and-play”, bastando apenas ter suporte para tocar áudio na distribuição do Linux.
Componentes de Software
A imagem Linux utilizada foi Raspbian Jessie versão Desktop, que pode ser baixada na seção de downloads do site oficial da Raspberry Pi.
O Raspbian, por padrão, não possui Qt5 instalado, então foi necessário cross compilá-lo. Para isso seguiu-se os passos de dois artigos muito bons com algumas modificações. Esses artigos são:
Basicamente os passos são:
1 – Baixar uma imagem Raspbian Jessie Desktop;
2 – Baixar uma toolchain para Raspberry Pi, que pode ser encontrada aqui;
3 – Gravar a imagem Raspbian Jessie em um cartão SD;
4 – Copiar o rootfs do cartão SD para alguma pasta do computador de desenvolvimento;
5 – Rodar o script python “sysroot-relativelinks.py” indicanto o diretório do rootfs copiado do cartão. O script transforma todos os links simbólicos absolutos para relativos tornando o rootfs útil em diferentes sistemas. O script pode ser baixado aqui;
6 – Clonar o Qt5 em um diretório da máquina de desenvolvimento:
1 |
git clone git://code.qt.io/qt/qt5.git -b 5.6 |
7 – Dentro do diretório clonado, executar ./configure indicando o diretório do root-filesystem copiado do cartão SD. Indicar o diretório da toolchain, e prefixo (/usr/local/qt5pi). Exemplo a seguir:
1 |
./configure -opengl es2 -device linux-rasp-pi-g++ -device-option CROSS_COMPILE=/home/projects/raspberry-dev/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot /home/projects/raspberry-dev/sysroot -opensource -confirm-license -reduce-exports -release -make libs -prefix /usr/local/qt5pi -hostprefix /usr/local/qt5pi -skip wayland |
Com o comando acima configuramos o ambiente para compilar o Qt5 com suporte a aplicações QML e OpenGL/EGLFS, para que as aplicações sejam exibidas diretamente no framebuffer sem necessidade de janelas do Raspbian;
8 – Executar “make” e depois “make install”. Isso vai levar um tempo;
9 – Por fim teremos um rootfs modificado incluindo suporte a Qt5. Copie este rootfs de volta para o cartão SD.
Para desenvolver o software da Urna foi usada a toolchain encontrada no GitHub da Raspberry Pi e o Qt Creator foi configurado da seguinte maneira:
1 – Debugger path:
1 |
/home/projects/raspberry-dev/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gdb |
2 – Compiler path:
1 |
/home/projects/raspberry-dev/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ |
3 – Qt Version (qmake location):
1 |
/usr/local/qt5pi/bin/qmake |
4 – Kit sysroot (rootfs copiado do cartão SD e onde posteriormente foi compilado Qt5):
1 |
/home/projects/raspberry-dev/sysroot |
Também é possível utilizar outros métodos para habilitar Qt5 na Raspberry Pi. Um deles, talvez até mais profissional, é utilizar o Yocto. Seguindo o pequeno tutorial Setting up a Yocto build with Qt5 for Raspberry Pi 2 with official touchscreen foi possível gerar uma imagem console (sem Desktop) onde as aplicações são executadas diretamente no framebuffer. A imagem também possui suporte a aplicações QML e suporte à tela oficial da Raspberry Pi. Os layers utilizados, tanto meta-raspberrypi quanto meta-qt5, são versão Jethro.
Ambos os métodos têm suas vantagens e desvantagens. Nessa excelente palestra do Diego Sueiro, ele explica as vantagens e desvantagens de distribuições prontas e customizadas e os conceitos por trás do processo de geração de distribuições customizadas com Yocto.
Integração QML e C++
A princípio o software da Urna educativa estava sendo desenvolvido apenas em linguagem QML, que é usada para desenvolvimento da parte gráfica de aplicações, posicionamento de elementos, efeitos especiais e outros aspectos, possibilitando ao desenvolvedor ou designer criar aplicações visualmente atraentes ao consumidor. QML usa uma sintaxe fácil de ler, em formato de declarações parecido com JSON. QML suporta também expressões em JavaScript. Como exemplo de aplicação desenvolvida em QML, existe este pequeno demo simulando um check-in em um Aeroporto.
Mas quando surgiu a questão de computação dos votos concluiu-se que QML apenas não bastaria. Seria inviável computar os votos em uma variável no ambiente QML pois ela se perderia caso a aplicação terminasse. A computação dos votos teria que ser gravada em arquivos no sistema. QML por si só não possibilita manipulação de arquivos do sistema e para isso foi necessário o uso de C++ e a integração entre ambas as linguagens. Essa prática de desenvolvimento é bastante aconselhável, separando a maior parte lógica da aplicação (C++) da parte gráfica (QML).
Para colocar em prática a integração QML e C++ foi desenvolvido um plugin de extensão (Qt Quick 2 Extension Plugin) chamado “Urna”. Plugins são desenvolvidos em C++ e possibilitam a declaração de propriedades que estarão disponíveis no ambiente QML e vice-versa, permitindo a comunicação entre os dois ambientes.
No Qt Creator é possível criar um plugin como se fosse um novo projeto. Seguem os passos:
- File > New File or Project > Library > Qt Quick 2 Extension Plugin > Choose…;
- Escolha um nome e um diretório para o plugin;
- Selecione o Kit já pré configurado anteriormente;
- Em Object class-name e URI escolha um nome. Ex. “Urna”;
- Clique em Finish.
Após esses passos teremos a seguinte estrutura de diretórios e arquivos na aba Projects:
Se compilarmos o plugin clicando no martelinho ou apertando Ctrl+B, teremos o arquivo do plugin gerado com nome “libUrna.so” e juntamente o arquivo “qmldir”, que é responsável por indicar o nome do plugin e do módulo, ambos de nome “Urna”. Esse plugin, após desenvolvido todos seus recursos, foi copiado para a Raspberry dentro da pasta de plugins do Qt juntamente com o arquivo “qmldir”:
1 2 |
pi@raspberrypi:/usr/local/qt5pi/qml/Urna $ ls libUrna.so qmldir |
Funcionamento do Plugin Urna
Para usar o plugin Urna em ambiente QML é necessário importá-lo e declará-lo como um componente QML dando um id ao mesmo:
1 2 3 4 |
import Urna 1.0 Urna { id: urna } |
Assim, toda propriedade criada no plugin em ambiente C++ estará disponível em ambiente QML da seguinte maneira:
1 |
urna.<propriedade> |
Por exemplo quando um botão é pressionado podemos atribuir uma string de valor “João” à propriedade:
1 2 3 4 5 6 |
Button { id: btn onClicked: { urna.<propriedade> = “João” } } |
Então podemos processar a propriedade em ambiente C++, que agora tem valor “João”.
As propriedades devem ser criadas em ambiente C++ como explicado a seguir.
Os dois principais arquivos do plugin são urna.h e urna.cpp. Em urna.h são declaradas todas as funções e propriedades que desejamos usar no QML. Abaixo segue exemplo das propriedades declaradas relacionadas a Vereador:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// arquivo urna.h #ifndef URNA_H #define URNA_H #include <QQuickItem> #include <QtCore> class Urna : public QQuickItem { Q_OBJECT Q_DISABLE_COPY(Urna) Q_PROPERTY(QString voto_vereador READ voto_vereador WRITE setVoto_vereador NOTIFY voto_vereadorChanged) Q_PROPERTY(QString nome_vereador READ nome_vereador WRITE setNome_vereador NOTIFY nome_vereadorChanged) Q_PROPERTY(QString partido_vereador READ partido_vereador WRITE setPartido_vereador NOTIFY partido_vereadorChanged) Q_PROPERTY(QString num_vereador READ num_vereador WRITE setNum_vereador NOTIFY num_vereadorChanged) Q_PROPERTY(QString foto_vereador READ foto_vereador WRITE setFoto_vereador NOTIFY foto_vereadorChanged) public: Urna(QQuickItem *parent = 0); ~Urna(); QString voto_vereador() const; void setVoto_vereador(const QString &newVotoVereador); QString nome_vereador() const; void setNome_vereador(const QString &newNomeVereador); QString partido_vereador() const; void setPartido_vereador(const QString &newPartidoVereador); QString num_vereador() const; void setNum_vereador(const QString &newNumVereador); QString foto_vereador() const; void setFoto_vereador(const QString &newFotoPrefeito); signals: void voto_vereadorChanged(); void nome_vereadorChanged(); void partido_vereadorChanged(); void num_vereadorChanged(); void foto_vereadorChanged(); private: QString m_voto_vereador; QString m_nome_vereador; QString m_partido_vereador; QString m_num_vereador; QString m_foto_vereador; }; #endif // URNA_H |
Para declarar uma propriedade usa-se Q_PROPERTY contendo os tipos READ, WRITE e NOTIFY.
- O tipo READ é uma função que retorna um valor que pode ser lido em ambiente QML;
- O tipo WRITE é uma função que recebe um valor do ambiente QML para ser processado;
- O tipo NOTIFY é uma função que serve para emitir um sinal quando um valor é mudado indicando ao QML que toda propriedade relacionada àquele valor deve ser atualizada.
A seguir declara-se em public as funções READ e WRITE:
1 2 |
QString voto_vereador() const; // tipo READ void setVoto_vereador(const QString &newVotoVereador); // tipo WRITE |
A definição dessas duas funções é feita no arquivo urna.cpp. A função voto_vereador() é responsável por retornar para o lado QML o novo valor da propriedade e a segunda função setVoto_vereador() é responsável por receber um valor do ambiente QML e processá-lo.
Funcionamento Geral da Urna e Computação dos Votos
Abaixo podem ser vistos alguns screenshots da aplicação em funcionamento. Lembrando que o posicionamento dos elementos e toda parte gráfica foi feita em QML.
Os nomes, números, partidos e diretório das fotos dos candidatos estão todos registrados em um arquivo JSON, funcionando como um banco de dados.
1 2 3 4 5 6 7 8 9 10 |
{ "vereador": [ { "nome":"Mariana", "numero":"1180", "partido":"1M16", "foto":"sources/foto_mariana1180.png" }, … |
Para votar em vereador o usuário precisa digitar 4 dígitos. Após digitar, esse número passa do ambiente QML para a função setNum_vereador() em ambiente C++. A função tem a seguinte lógica:
- receber o número do candidato do ambiente QML;
- procurar no banco de dados pelo número;
- retornar ao QML as informações do candidato para serem exibidos na tela, nome, partido e nome do arquivo da foto.
O usuário, tendo certeza do voto, aperta em confirma. Após apertar confirma, o voto agora passa de QML para a função setVoto_vereador() que salva o voto em um arquivo do sistema. Esse arquivo fica com a seguinte forma:
1 2 3 4 |
nome:Rodrigo numero:1483 nome:Lucas Felipe numero:1584 nome:Mariana numero:1180 ... |
Por fim foi desenvolvido um pequeno programa em Qt console que lê o arquivo dos votos e faz a contagem. O programa é executado via SSH na própria Raspberry e a visualização dos votos é feita no próprio terminal SSH:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
pi@raspberrypi:~/urna-files $ ./contaVotos votos_vereador.txt votos_prefeito.txt MANHA *********** PREFEITO Candidato | n de votos ---------------|--------------- Lucas | 51 Luiz | 49 Mirela | 127 VEREADOR Candidato | n de votos ---------------|--------------- Mariana | 50 Frederico | 12 Rebeca | 19 Rodrigo | 78 Lucas Felipe | 45 Yago | 23 Total votos manha: 227 |
No vídeo abaixo serão explicados os conceitos acima e você poderá ver a Urna em pleno funcionamento.
Conclusão e trabalhos futuros
Neste artigo foram vistos conceitos de desenvolvimento de aplicações Qt com integração QML/C++, mostrando que Qt pode suprir vários recursos que as aplicações demandam, tanto na parte gráfica como na parte lógica. Apesar dos conceitos serem mostrados neste artigo de forma sucinta, eles estão muito bem documentados. Veja os links na referência.
O código fonte da Urna é um pouco extenso, por isso não foi incluído totalmente neste artigo. Todo o código fonte, incluindo o código do plugin e do contador de votos, está disponível no GitHub.
Para trabalhos futuros está sendo planejado o desenvolvimento de outra aplicação para configuração e gerenciamento da Urna tornando a adição de candidatos e suas fotos uma tarefa mais fácil. Planeja-se o uso de pendrive que conterá o banco de dados dos candidatos e suas fotos.
O código ainda pode passar por melhorias, incluindo mudanças na nomenclatura de funções e variáveis, e também incluir mais comentários no decorrer do código.
A Urna Eletrônica Educativa foi testada em uma situação real na Escola Municipal Francisco Cardona na cidade de Artur Nogueira, interior de São Paulo. Uma matéria sobre o projeto de eleição da escola contendo o depoimento dos alunos pode ser encontrado no site de notícias da cidade.
Qualquer dúvida escreva nos comentários ou entre em contato da forma que desejar.
Referências
Qt Cross compile – Configure Options
Stackoverflow – reading and writing files in QML
Askubuntu – how to read file contents in QML
Askubuntu – simplest way to write to a text file QML
Qt5 Cadaques Book chapter 15 – Qt and C++
Para quem está perguntando sobre o projeto e como adquiri-lo.
Basta acessar o projeto no GitHub através do link:
https://github.com/giobauermeister/UrnaEletronica
Vaso eu queira comprar um exemplar, quanto custaria meu amigo?
Olá Renato! Este não é um equipamento para venda. Foi feito com fins educacionais.
GOSTARIA MUITO DE FAZER UMA DESSAS TERIA COMO ME AJUDAR OBGDO
BOA TARDE GOSTEI MUITO DO PROJETO ! PARABENS MAS TERIA COMO FAZER UM VIDEO MOSTRANDO A CONFIGURACAO DO SOFTWARE E MONTAGEM NO RASP BERRY PI
Olá não fizemos vídeo da montagem pois é relativamente simples.
A montagem foi feita com caixa de madeira e cola.
Teclado numérico e caixa de som conectados na USB da Raspberry Pi.
Fonte conectada no Micro USB da Raspberry Pi.
Display touch conectado na porta DSI da Raspberry Pi.
A programação pode ser encontrada toda no GitHub: https://github.com/giobauermeister/UrnaEletronica
boa tarde achei muito interessante o projeto gostaria de fabricar uma dessas teria como disponibilizar um video da montagem e a programacao no rasp berry pi
A montagem foi simples, caixa feita de madeira e cola.
Teclado numérico e caixa de som conectados na USB da Raspberry Pi.
Fonte conectada no Micro USB da Raspberry Pi.
Display touch conectado na porta DSI da Raspberry Pi.
A programação pode ser encontrada toda no GitHub: https://github.com/giobauermeister/UrnaEletronica
Essa urna não corresponde à urna usada pelo TSE, o teclado é diferente e tem os números invertidos em relação à urna original.
Isso mesmo não é a mesma Urna. Esta foi feita para fins educacionais apenas.
Boa noite Giovanni como vc pode me ajudar a fazer esse projeto? Por favor irmão
Olá Taciano, pedimos, por gentileza, que direcione essa discussão em particular com o desenvolvedor desejado. Grato pela compreensão.
Olá Giovanni vamos vê a possibilidade de vc poder me ajudar a desenvolver esse projeto da urna. Como podemos conversar em particular?
[email protected]
Então, pra eu fazer esse projeto eu preciso de que além do Raspberry PI e da tela? Me ajuda a fazer esse projeto. Fico muito Feliz se vc me ajudar. Quais os materiais necessário
Posso prestar uma consultoria de engenharia para desenvolvimento de projetos. Se quiser podemos discutir preços no privado.
No Artigo acima na seção “Componentes de Hardware” listei todos os componentes que utilizei para fazer a Urna. A caixa é de madeira mesmo. Além da Rasp e tela, usei caixas de som e teclado USB. Componentes facilmente encontrados na internet e lojas de informática.
Abraço e sucesso em seu projeto!
Giovanni entre em contato comigo pelo whats 75982465180.
[email protected]
Giovanni me ajuda a desenvolver uma urna dessa.
Olá Taciano!
FIcou alguma dúvida sobre o artigo? Por favor especifique melhor sua dúvida que eu te ajudo com certeza na medida do possível e dentro do meu nível de conhecimento.
Abraço!