Desenvolvimento

17 jan, 2018

Criando o firmware para Raspberry PI com Elixir e Nerves

100 visualizações
Publicidade
https://grey-seagull.deviantart.com/art/Ogre-Cook-484516205

Como o PIX PROJECT começou a ser uma coisa real, eu decidi torná-lo mais dinâmico. A primeira versão escrita em Ruby é muito estática. Não existe uma maneira fácil de animar pontos no relógio, por exemplo. Além disso, você tem que instalar todo o Linux, instalar pacotes e iniciar o aplicativo. Não é assim que o firmware funciona corretamente? Eu decidi reescrevê-lo em Elixir e envolvê-lo com Nerves para criar o firmware. Deixe a história começar.

Não sei do que você está falando!

Apenas para deixar a coisa clara. O PROJETO PIX está prestes a criar algo como quadro de pixels. Resumindo, estou tentando consertar um brinquedo quebrado. É simplesmente Raspberry PI Zero com pixels 16×16 LED Matrix.

Os ingredientes

No começo, precisaremos de algum conhecimento de Elixir e OTP. Nós usaremos o GenServers, também precisaremos usar uma Portuária para conduzir a LED Matrix.

Nosso sistema terá três tipos de componentes principais:

Saída

Precisaremos de poucas implementações de saída. A primeira desenhará tudo para o console. Outra irá conduzir uma LED Matrix real. Mas esse não é nosso alvo agora. Se você olhar para o código, também há uma terceira saída. Ela está usando o módulo kernel que escrevi para a versão Ruby, apenas para testes.

Exibição

Esta é a parte principal. Esta peça irá coletar todos os dados, decidir qual desejamos exibir, nos mostrar transições extravagantes. Este componente usará um de saída para nos mostrar dados.

Recursos

Haverá muitos desses componentes. Eu chamei de recursos porque é como recursos de PIX THING. Por exemplo: relógio, temperatura, notificações. Cada recurso será programado como um aplicativo separado que gerará sua própria saída e conversará com nossa tela se tudo mudou.

A Jarra

Precisaremos de uma grande jarra para todos esses ingredientes. Sim, você está certo. Usaremos um aplicativo guarda-chuva. O primeiro aplicativo irá tirar dados e exibi-los no terminal.

Saída do terminal

É realmente um aplicativo GenServer simples. Ele espera por dados. Nos dados do nosso aplicativo há uma série de linhas. A linha é uma série de números e o número é uma cor do pixel na linha.

Nós precisamos convertê-lo e exibi-lo para o console.

defp draw(state) do 
  state 
  |> Enum.map(&process_line/1) 
  |> ANSI.format() 
  |> List.insert_at(0, [IO.ANSI.clear(), IO.ANSI.home()]) 
  |> IO.puts() 
end

Precisamos processar cada linha, limpar a tela e exibi-la.

defp process_line(line) do
  line    
  |> Enum.map(&process_pix/1)
  |> Kernel.++("\n")
end
defp process_pix(pix) do
  [color(pix), "■ "]
end

Cada cor será convertida em pixel uft8 com a cor correspondente. Você pode verificar todo o código aqui no Github.

Random Pixel Generator

Agora vamos fazer um pequeno atalho. Criaremos um recurso que gera o pixel aleatório e envia dados para a saída.

Precisamos gerar um aplicativo aleatório e criar um GenServer dentro dele. Todos os dados (cores de pixels) serão armazenados no estado GenServer. Para torná-lo vivo. O GenServer deve gerar pixels por si só.

def handle_info(:tick, state) do
  state = draw_random(state)     
  Process.send_after(self(), :tick, @timeout)
  Terminal.data(__MODULE__, state)     
  {:noreply, state}  
end

Nós podemos arquivar isso usando handle_info. Após cada atualização, nosso aplicativo de terminal receberá novos dados para serem exibidos. Aqui está todo o aplicativo aleatório.

Display

O display será a parte mais complicada de nosso aplicativo. Ele irá reunir todos os dados de todos os recursos, gerar tela atual e enviá-los para o aplicativo de saída. Você deve olhar o código você mesmo aqui.

Existem algumas coisas que eu vou descrever:

Ciclo

Cada recurso será exibido na tela por 30 segundos e mudará para o próximo registrado.

Inscrições

Quando executamos um aplicativo de recurso, ele precisa se inscrever para exibir. O aplicativo de display precisa saber quais recursos estão sendo executados.

Transições

Queremos fazer uma bela transição entre eles. O aplicativo de display armazena todos os dados de tela atuais para todos os recursos inscritos, para que possamos desenhar uma transição.

Agora você tem uma ideia de como isso funciona. O que é uma arquitetura, pelo que cada parte é responsável. Você pode verificar o repositório pix_elixir para mais exemplos de recursos como Relógio, Relógio Binário, Clima, etc. Precisamos ir mais longe.

LED Matrix

Para conduzir LED Matrix, você terá que usar Portas Erlang. Precisamos de um pequeno programa C que converse para Elixir com stdin/out e exiba nossos dados. Escrever portas está muito além do alcance deste artigo, mas para fazer isto funcionar, eu tenho que copiar um pouco de função C do Kernel e envolvê-la com a porta.

Tenho um problema com as prioridades e os horários do processo. Dentro do módulo do kernel, posso definir a prioridade para loop de LED. Então, eu não vejo falhas. Com a porta Erlang, toda operação io causa falhas LED. Ainda estou trabalhando nisso.

Nervos

A parte final está envolvendo tudo o que acabamos de criar uma pequena imagem que pode ser queimada no cartão SD e que funcionará com o Raspberry PI.

Para fazê-lo funcionar, precisamos adicionar outro aplicativo à nossa jarra. Desta vez, iremos nomeá-lo firmware e usar o comando nerves.new misto.

Tudo o que você precisa fazer é adicionar alguns aplicativos do nosso aplicativo guarda-chuva, construir o firmware com o mix firmware e queimá-lo com o mix firmware.burn. Espete seu cartão SD em seu raspberry pi,  e é isso!

As coisas mais importantes para fazê-lo funcionar com nerves são:

Makefile para portas deve suportar algumas VARIÁVEIS ENV importantes.

  • Lembre-se de configurar o Matrix (saída LED) para a construção da produção.
  • Certifique-se de que o bootloader esteja executando seu aplicativo após a inicialização.
  • Você pode conectar um teclado e monitor ao seu Raspberry PI e jogar com o console IEX no dispositivo.

Espero que tenha sido útil para você. Obrigado por ler! Você gostou? Clique no ícone abaixo. Obrigado!

***

Michał Kalbarczyk faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://blog.fazibear.me/brewing-the-firmware-for-raspberry-pi-with-elixir-and-nerves-5dd67970d073