Programação da Raspberry Pi com .Net Core 10

Nem só de Python (e C/C++) vive o mundo da Internet das Coisas. Outras linguagens e plataformas podem ser utilizadas para a criação de programas sem muito esforço, permitindo a utilização de conhecimentos já existentes e permitindo a inclusão de programadores no mundo do hardware mais facilmente, como foi visto no artigo sobre Programação da Raspberry Pi com Java. E é justamente por essa inclusão que a Microsoft trabalhou com sua equipe de engenheiros para levar o .Net Core (lê-se “dot net core”) ao Raspberry Pi, seja utilizando o Windows 10 IoT Core (versão do Windows 10 para Raspberry Pi) ou até mesmo rodando em cima do Raspbian.

Apresentando o .Net Core

.Net Core é uma plataforma open source (e seu código fonte pode ser encontrado no GitHub oficial) desenvolvida pela Microsoft, que tem como premissa rodar nos mais variados ambientes, compartilhando o mesmo código. Por esse motivo, a aplicação web que será exibida aqui pode rodar tanto na Raspberry Pi quanto em um ambiente clusterizado de nuvem, caso exija alta performance.

.net core

Como é uma plataforma, o .Net Core engloba vários módulos, e inclusive conta com suporte à algumas linguagens de programação proprietárias. No exemplo faremos uso da quinta linguagem de programação mais utilizada do mundo pelo IEEE, o C# (leia-se C Sharp).

Preparando o ambiente

Antes de tudo, é necessário salientar que o .Net Core precisa de processadores com arquitetura armv7, o que, infelizmente, exclui a Raspberry Pi Zero, mas Raspberry Pi 2 ou 3 são plenamente suportadas.

Será preciso um ambiente de desenvolvimento .Net, que você pode instalar em seu computador pessoal, independente do sistema operacional. A maneira mais fácil de se ter um ambiente desses é instalando o Visual Studio 2017 Community, a IDE oficial da Microsoft para Windows e macOS. Essa versão é gratuita e suporta tudo o que iremos precisar.

O Visual Studio não conta com versões para Linux, mas é possível instalar o SDK do .Net Core 2.0 e utilizar o Visual Studio Code, um editor de texto mais leve. Outras alternativas são o Atom, Sublime e etc.

Na placa, é necessário ter o Raspbian Stretch instalado, e alguma maneira de transferir os arquivos do computador de desenvolvimento. Recomendo a utilização de Samba ou FTP. É possível também transferir os arquivos utilizando a ferramenta Cake.

Visual Studio 2017

Show me the code!

Na Raspberry Pi, vamos instalar somente o runtime do .Net Core. Runtime é o que possibilita que aplicações escritas em .Net Core sejam executadas. Para isso, vamos utilizar os seguintes comandos no terminal.

Instalar os pré-requisitos da plataforma

sudo apt-get install curl libunwind8 gettext

Baixar o runtime mais recente do .Net Core 2.0

curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz

Criar um diretório de destino e extrair o runtime para dentro dele

sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet

Definir um alias pro comando dotnet

sudo ln -s /opt/dotnet/dotnet /usr/local/bin

Feito isso, o comando dotnet deve estar disponível para execução, assim como abaixo:

Sobre a aplicação web

A aplicação criada é bem simples. Ela vai interagir com a GPIO da Raspberry Pi, ligando e desligando seus pinos à medida que o usuário informa qual pino deseja alterar o estado. A ideia é que o usuário vá no browser e informe o endereço http://<ENDEREÇO_IP>/api/gpio/<PINO>. Assim, o browser vai retornar qual o novo estado do pino, true (ligado) ou false (desligado).

Vale notar que essa aplicação não tem telas, por isso não trabalharemos com HTML. O tipo de aplicação será WebAPI, algo muito leve para tráfego de dados entre a placa e qualquer dispositivo que a esteja chamando. O resultado final pode ser conferido no Github, onde é possível efetuar o download de todo o código. Caso vá pelo caminho do código pronto, basta pular o próximo tópico.

Criando a aplicação no Visual Studio

  1. Na IDE, vá ao menu File e em seguida, New Project.
  2. Na janela New Project, selecione .Net Core e depois ASP.Net Core Web Application.
  3. Defina também o nome para a aplicação (no caso, chamei de RaspberryPi.API) e também o local onde ela será salva. New Project
  4. Uma nova janela chamada New ASP.Net Core Web Application vai aparecer. Nela, escolha o tipo Web API, deixando as demais opções como padrão e clicando em Ok.
  5. Depois de pronto, o próximo passo é ir até a janela Solution Explorer e renomear o arquivo ValuesController.cs para GPIOController.cs. O Visual Studio vai perguntar se você quer também renomear todas as referências que o projeto possui de ValuesController. Aperte Sim, e teremos um arquivo consistente.
  6. O conteúdo do arquivo GPIOController será alterado. Substituiremos todo o texto pelo seguinte código abaixo:
    using System;
    using Microsoft.AspNetCore.Mvc;
    using Unosquare.RaspberryIO;
    using Unosquare.RaspberryIO.Gpio;
    
    namespace RaspberryPi.API.Controllers
    {
        [Route("api/[controller]")]
        public class GPIOController : Controller
        {
            // GET api/values/5
            [HttpGet("{id}")]
            public bool Get(uint id)
            {
                var pin = GetPin(id);
                pin.PinMode = GpioPinDriveMode.Output;
                var isOn = pin.Read();
    
                pin.Write(!isOn);
    
                return !isOn;
            }
    
            private GpioPin GetPin(uint value)
            {
                GpioPin pin;
    
                switch (value)
                {
                    case 0:
                        pin = Pi.Gpio.Pin00;
                        break;
                    case 1:
                        pin = Pi.Gpio.Pin01;
                        break;
                    case 2:
                        pin = Pi.Gpio.Pin02;
                        break;
                    case 3:
                        pin = Pi.Gpio.Pin03;
                        break;
                    case 4:
                        pin = Pi.Gpio.Pin04;
                        break;
                    case 5:
                        pin = Pi.Gpio.Pin05;
                        break;
                    case 6:
                        pin = Pi.Gpio.Pin06;
                        break;
                    case 7:
                        pin = Pi.Gpio.Pin07;
                        break;
                    case 8:
                        pin = Pi.Gpio.Pin08;
                        break;
                    case 9:
                        pin = Pi.Gpio.Pin09;
                        break;
                    case 10:
                        pin = Pi.Gpio.Pin10;
                        break;
                    case 11:
                        pin = Pi.Gpio.Pin11;
                        break;
                    case 12:
                        pin = Pi.Gpio.Pin12;
                        break;
                    case 13:
                        pin = Pi.Gpio.Pin13;
                        break;
                    case 14:
                        pin = Pi.Gpio.Pin14;
                        break;
                    case 15:
                        pin = Pi.Gpio.Pin15;
                        break;
                    case 16:
                        pin = Pi.Gpio.Pin16;
                        break;
                    case 17:
                        pin = Pi.Gpio.Pin17;
                        break;
                    case 18:
                        pin = Pi.Gpio.Pin18;
                        break;
                    case 19:
                        pin = Pi.Gpio.Pin19;
                        break;
                    case 20:
                        pin = Pi.Gpio.Pin20;
                        break;
                    case 21:
                        pin = Pi.Gpio.Pin21;
                        break;
                    case 22:
                        pin = Pi.Gpio.Pin22;
                        break;
                    case 23:
                        pin = Pi.Gpio.Pin23;
                        break;
                    case 24:
                        pin = Pi.Gpio.Pin24;
                        break;
                    case 25:
                        pin = Pi.Gpio.Pin25;
                        break;
                    case 26:
                        pin = Pi.Gpio.Pin26;
                        break;
                    case 27:
                        pin = Pi.Gpio.Pin27;
                        break;
                    case 28:
                        pin = Pi.Gpio.Pin28;
                        break;
                    case 29:
                        pin = Pi.Gpio.Pin29;
                        break;
                    case 30:
                        pin = Pi.Gpio.Pin30;
                        break;
                    case 31:
                        pin = Pi.Gpio.Pin31;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(value), "Value must be between 0 and 31");
                }
    
                return pin;
            }
        }
    }
  7. O código utiliza a biblioteca Unosquare para interagir com a GPIO do RaspberryPi. Foi criado um método chamado GetPin para retornar o pino da GPIO de acordo com o parâmetro que o usuário informar no browser. Mas a biblioteca não está inclusa no código. Para funcionar, devemos instalá-la através do gerenciador de dependências do Visual Studio, o NuGet. Para isso, clique com o botão direito em cima do projeto Web RaspberryPi.API e vá em Manage NuGet packages.
  8. Na janela de pacotes do NuGet, na aba Browse, devemos procurar por Unosquare.Raspberry.IO, onde deve aparecer apenas um item. Selecione-o, e clique em Install. Dê Ok e I Accept nas janelas que aparecerem.
  9. Voltando ao arquivo GPIOController.cs, notamos que os itens sublinhados em vermelho sumiram. Hora de compilar o código para ver se está tudo ok, através do menu Build > Build Solution. Caso esteja tudo ok, no canto inferior esquerdo aparecerá a frase Build succeeded.

Gerando o executável

O código está rodando na máquina de desenvolvimento, mas é necessário gerar um arquivo executável, transportando-o para a Raspberry Pi da maneira desejada (FTP, Samba, dentre outros). Para isto

  1. Abra o prompt de comando do Windows (ou terminal, no Linux/macOS).
  2. Vá até o diretório do código que criamos acima (cd <CAMINHO_DO_CODIGO>). É importante que esteja na pasta raiz, onde se encontra o arquivo RaspberryPi.API.sln.
  3. Execute o seguinte comando
    dotnet publish -c Release -r linux-arm

    Ele vai gerar uma pasta chamada publish com o código compilado para arquitetura armv7 em Linux.

  4. A última linha representa o caminho onde o código foi compilado para release. Copie esse endereço e acesse-o no Windows Explorer. Esse é o código que será executado pela Raspberry Pi. Copie todo o conteúdo da pasta para dentro do sistema da placa utilizando o melhor meio.

Executando o código no Raspbian

Aqui copiei os arquivos para dentro de uma pasta chamada Apps, que foi criada com permissão de leitura, escrita e execução

sudo mkdir App
sudo chmod 0777 App

Para que possamos ter acesso à GPIO da RaspberryPi, é necessário que entremos em modo sudo, e indo até o caminho da pasta do código

sudo -i
cd /home/pi/App

O programa recém criado será executado na porta 5000. Ele será executado através do comando

./RaspberryPi.API

Com isso, basta que acessemos o endereço http://<IP_DA_PLACA>:5000/api/gpio/7 para mudar o status do pino 7 da GPIO, ligando caso esteja desligado, e apertando F5 para desligar.

Considerações Finais

O .Net Core é uma plataforma extremamente robusta, e a linguagem C# é simples de aprender, contando com bastante recursos e extensa documentação. Utilizaremos bastante esse tutorial no futuro, pois serão mostradas também algumas integrações com sensores e a nuvem. Caso queiram aprender mais da plataforma da Microsoft, recomendo que deem uma olhada nos sites do MSDN, com a maioria do conteúdo também em português.

Gostou? Deixe seu comentário logo abaixo.

Faça seu comentário

Acesse sua conta e participe

10 Comentários

  1. Excelente material, solucionou praticamente todas minhas dúvidas, nota 10!

  2. Por que quando instalo o Unosquare.Raspberry.IO meu visual studio não habilita o Unosquare.RaspberryIO.Gpio?

    será que falta eu instalar algum pacote de desenvolvedor?

  3. Boa tarde Alliston. Tenho uma API muito sementante a esta rodando no Visual Studio no windows 10.
    Preciso através do haspberry pi 3 enviar um post para essa API…poderia me dar um norte de como fazer isso?

  4. Existem outras placas que suportam .net core, neste modelo acima? Vi que existe uma raspberry pi zero w, mas vi gente dizendo que não rola. Saberia dizer se existe algo semelhante de outras marcas e modelos? O objetivo é conseguir algo mais compacto e se possível com WiFi embutido.

    1. Bom dia Fabio.

      Infelizmente, nada oficial… a Microsoft disponibiliza apenas para as versões 2 e 3 da placa, devido à falta de instruções armv7 nas outras (Zero W por exemplo roda armv6).
      Não conheço nada além da Raspberry que rode o .Net Core oficialmente, mas se tiver alguma placa que rode Linux com instruções armv7, é bem possível você conseguir. Se encontrar algo, posta aí pra gente!

      Abraços!

  5. è possivel implementar uma API Net core 2.1 nas rasp pi 3?

    1. É sim Samuel, nesse exemplo utilizo o .Net Core 2, mas é possível sim utilizar a versão 2.1 sem problemas.

      Abraços!

  6. Ótimo tutorial!
    Eu tive que fazer mais um step que foi usar o chmod no executável da pasta.
    Depois disso rodou de boa.
    Parabéns

  7. *,* comentando pra deixar registrado e testar mais tarde!!!!
    Valeuuu Abrsss