PCDisplay
Github: https://github.com/lucasoshiro/pcdisplay
Este projeto trata-se de um display LCD acoplado ao gabinete de meu computador, mostrando as seguintes informações:
- Uso de CPU
- Uso de RAM
- Velocidade de download/upload
- Temperatura do processador
- Data e hora
- Hostname e versão do sistema operacional
- Título e artista da faixa em execução
O hardware foi feito com um Arduino Nano junto do display em si. No repositório está contido o código host, feito em Ruby, que centraliza as informações do computador e as fornece para o Arduino, e o código guest, usado pelo Arduino para controlar o display.
Fluxo
+-----+ +---------+ Requisição +------------+
|Botão| --------> | Arduino | ----------------> | PC |
+-----+ | (guest) | | (host) |
| | <---------------- | |
+---------+ Dados +------------+
|
|
|
V
+---------+
| Display |
+---------+
As requisições têm o formato REQUISIÇÃO <argumentoss>, com cada argumento
separado por espaço. O argumento também pode vir entre aspas, podendo ser
escapado da mesma forma que no bash. As respostas são enviadas no formato
REQUISIÇÃO <dados>, com o mesmo nome da requisição.
PCDisplay Host
O PCDisplay host é executado no computador e envia os dados ao Arduino. Ele é composto pelos seguintes arquivos:
-
arduino_serial.rb: contém a classe Arduino, que abstrai a biblioteca SerialPort, para facilitar a comunicação com o Arduino; -
serial_server.rb: biblioteca que permite a criação de um servidor capaz de processar uma requisição feita pelo Arduino, e enviar os dados requeridos, com sintaxe semelhante ao framework Sinatra; -
pc.rb: contém a classe SingletonPC, que centraliza as diversas leituras do computador, provendo sempre de forma rápida os dados. Cada “leitor” é executado em uma thread diferente, atualizando os dados do singletonPCconforme os dados são obtidos; -
main.rb: neste arquivo são definidas os callbacks para cada requisição, no seguinte formato:
request 'REQUISIÇÃO' do
dado = algum_processamento
"REQUISIÇÃO #{dado}"
end
Ou seja, o fluxo é o seguinte:
+-------+ Requisição +------------+ +--------+
| | -------------> |SerialServer| ---> | |
|Arduino| +------------+ |callback|
| | <--------------------------------- | |
+-------+ Dados +--------+
^
|
+------------+ +--------+
| | <----- | Player |
| PC | +--------+
| |
+------------+ <----- +--------+
^ ^ ^ ^ ^ | Rede |
| | | | | +--------+
+-----+ | +---+ | +----+
| CPU | | |RAM| | |Hora|
+-----+ | +---+ | +----+
| |
+--------+ +-----------+
|Hostname| |Temperatura|
+--------+ +-----------+
PCDisplay Guest
O PCDisplay Guest é executado no Arduino, e ele funciona como uma máquina de estados:
+---------+ +------+ +-----+
| SYSINFO | ------> | TIME | -------> | CPU |
+---------+ +------+ +-----+
^ |
| V
+-------+ +-----+ +------+ +-----+
| MEDIA | <-- | NET | <--- | TEMP | <-- | RAM |
+-------+ +-----+ +------+ +-----+
Cada estado tem uma função de atualização da tela associada, que lê as
informações contidas na struct global INFO, e as mostra na tela.
O loop principal realiza um ciclo das seguintes ações:
-
Caso uma troca de estado esteja agendada, troca de estado, senão permanece no atual;
-
Envia uma requisição das listas de requisições;
-
Espera o resultado e atualiza a struct
INFOcom os dados vindos do computador. Caso exceda o limite de tempo, entende-se a conexão foi perdida e tenta-se conectar novamente; -
Mostra a informação na tela, executando-se a função associada ao estado.
O agendamento de uma troca de estado ocorre quando o botão é pressionado. Esse evento causa uma interrupção, ativando uma flag que indica que no próximo ciclo o estado deverá ser trocado.
Galeria
Update (10/2021)
Depois de algum tempo, o display tinha dado problema e eu resolvi trocar por um novo, gráfico, de 128x64 pixels. Nesse novo display é possível mostrar todas as informações em uma só tela, não é necessário mais usar a máquina de estados.
Quanto ao resto do código, permanece igual.