LoginSignup
0
0

More than 3 years have passed since last update.

RaspberryのDocker上でGPIOをWiringPiで使う

Last updated at Posted at 2020-04-21

はじめに

RaspberryもGPIO(というかハードウェア全般)も初心者がDockerのコンテナでタクトスイッチのオンオフをConsoleに出力するだけのお話

環境

・Raspberry
・.NetCore 3.1(開発側)
・WiringPi
・実行はDocker(インストールしておいてください)

ソースはこちら

ハマりどころ

その1

現象

.NetCoreのruntimeコンテナでGPIOのアプリを起動したいので、マイクロソフトのイメージmcr.microsoft.com/dotnet/core/runtime:3.1-bionic-arm32v7を使ったところapt-getでWiringPiがインストールできませんでした(知っている方教えてください)

対処法

DockerfileにてラインタイムイメージにコンパイラをインストールしWiringPiをビルドすることで解決

その2

現象

RaspberryでGPIOを扱う場合に登場する/dev/gpioがコンテナ上ではアクセスができなくて困った。

対処法

Docerのコマンドに--deviceといパラメータがこれを使えばいいことが判明
だけど、今度はパーミッションエラーが発生
--privilegedコマンドを使えば回避できることが判明(特権モードで実行なので慎重に)

手順

開発側

  1. TackInvokerというフォルダを作成
  2. TackInvokerフォルダに移動
  3. dotnet new console
  4. Program.csを下記のファイルで置き換える
  5. TackInvokerフォルダの上に下記のDockerfileを配置
  6. docker build -t {自身のDockerHubID}/Tackinvoker:latest .
  7. docker push {自身のDockerHubID}/Tackinvoker:latest

Raspberry側

  1. docker run -it --rm --device /dev/gpiomem --privileged {自身のDockerHubID}/Tackinvoker:latest

素材達

Program.cs

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace TackInvoker
{
    class Program
    {

        public const int INPUT = 0;
        public const int OUTPUT = 1;

        public const int INT_EDGE_FALLING = 1;
        public const int INT_EDGE_RISING = 2;

        public const int Tack_PIN = 17;

        [DllImport("wiringPi")]
        extern static int wiringPiSetupGpio();

        [DllImport("wiringPi")]
        extern static void pinMode(int pin, int mode);

        [DllImport("wiringPi")]
        extern static void digitalWrite(int pin, int mode);


        [DllImport("wiringPi")]
        extern static int wiringPiISR(int pin, int edgeType, CallbackFunc func);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void CallbackFunc();

        static void Main(string[] args)
        {
            int ret = 0;

            // wiringPiのセットアップ
            wiringPiSetupGpio();

            // GPIO をINPUTに設定する.
            pinMode(Tack_PIN, INPUT);

            CallbackFunc callBackFunc = delegate () {
                Console.WriteLine("CallbackFunc is called !");

            };

            // GPIO がONになったらコールバック関数を呼ぶ.
            ret = wiringPiISR(Tack_PIN, INT_EDGE_RISING, callBackFunc);


            // 無限に待機する.
            Thread.Sleep(Int32.MaxValue);

        }
    }
}

Dockerfile


# ビルドイメージ
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build

WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.sln .

COPY TackInvoker/*.csproj ./  TackInvoker/

# copy everything else and build app

COPY TackInvoker ./TackInvoker/
RUN dotnet restore TackInvoker

WORKDIR /app/TackInvoker
RUN dotnet publish -c Release -o out

# ランタイムイメージ
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-bionic-arm32v7

# WiringPiをインストールする
RUN apt-get update
RUN apt-get install -y libi2c-dev
RUN apt-get install -y git-core
RUN apt-get install -y sudo
RUN apt-get install -y make
RUN apt-get install -y gcc
RUN git clone https://github.com/WiringPi/WiringPi.git
WORKDIR /WiringPi
RUN ./build

WORKDIR /app

COPY --from=build /app/TackInvoker/out ./

ENTRYPOINT ["dotnet", "TackInvoker.dll"]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0