C#でもIoTできるんだって！！RaspberryPiとC#使ってラジコン？的なの作る。

# 突然ですが皆さん「ロボット」好きですよね？

### はい！すきです！
良い返事ありがとうございます。

## C#好きですよね？
###...ハイ好きです。

すみません....
嘘です。
まだC#書き始めて一月ちょいしかたっていないので
すげぇとは思いつつまだ愛せていないです。。。

とはいえC#書けるようになると色んな事が出来るようになるよ！！ってのはお伝えしたくなったので
僕が愛してるIoT的なハードウェア的なものと絡めてふーんなんかこんな感じなんだ？
くらいをふわっと伝えられればいいなーと思います。

## ちなみにC#勉強してみたいんだよねーって人にはまず。

[オブジェクト指向でなぜつくるのか](https://www.amazon.co.jp/dp/B00ISP0QB2/)
をまず読んでオブジェクト指向の変な先入観を取り払って
[スラスラわかるC#](https://www.amazon.co.jp/dp/B07HR9PLQ2/)
を読んで弄り始めてみると楽しくなると思います！！

取っ付き難いと苦手意識持っている人も多いかもですけど意外にやってみると
やっぱりプログラミングって楽しいゾ

こういう人も居ますしある日いきなりホルス神が送られてくればやってみたくなるかもしれない。
https://qiita.com/sngazm/items/c27b7745fb68139213c2


#ということで
世に居るロボット好きでC#好きで物作りが好きな人が増えて行くそんな記事を書きたい（願望）

ちなみにこんなのを作る事が出来るようになるさわりのお話し。
![DSC04035.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336684/427e0fd3-e570-bca2-c238-529a2e05ef2d.jpeg)


# まずは環境構築から。

とりあえずRaspberry Piの初期設定は終わっていてリモート操作はできる状態までいった前提で話していく。
その辺はここを見て貰うのが早い
[Raspberry Pi 初期設定](https://qiita.com/HeRo/items/c1c30d7267faeb304538)

基本的に下記コマンドはRaspberry Pi上のターミナルに打っている。
コードはWindows10にインストールしているVisual Studio2019で書いてbuildしている。

samba導入するとWindowsの共有フォルダが使えるのでファイル共有が少し楽。

```
sudo apt-get install samba
```

apt-getをアップデートしないと404エラーでインストールできないことがある

```
sudo apt-get update
```

「Windowsの機能の有効化または無効化」でSMB 1.0/CIFSのClientとServerをチャックマーク付けて
有効にしないとWindows10だとネットワーク共有に表示されない。

```:smb.conf
[Raspberry-Pi]
path = /home/pi/Public
read only = No
browsable = no
guest ok = yes
force user = pi
```

```
sudo /etc/init.d/samba restart
```

SSH接続でファイル転送するのもあり。

遠隔ソフトにはこれ
RealVNCをダウンロードインストール
[Download VNC Viewer for Windows \| VNC® Connect](https://www.realvnc.com/en/connect/download/viewer/windows/)

※日本語版とかいうのはくそ古いので注意
デフォルトのログインパスワードは
pi
raspberry


##ここから今回のメインインストール作業
.NET Coreのインストール

[GitHub - dotnet/core: Home repository for .NET Core](https://github.com/dotnet/core)

ここのARM/Linux用のSDKをダウンロード
直接DLするならRasberryPiでwgetするといい
100M位容量がある
俺のどんなときもWi-Fiだとくそ遅い。

```
wget https://download.visualstudio.microsoft.com/download/pr/67766a96-eb8c-4cd2-bca4-ea63d2cc115c/7bf13840aa2ed88793b7315d5e0d74e6/dotnet-sdk-3.1.100-linux-arm.tar.gz
```
SDKはホームディレクトリ ~/ に入れておくこと
後の作業でそこから解凍する。
あとSDKインストールの前に以下のコマンドでアップデートとライブラリのインストールを行っておく。

```
sudo apt-get update
sudo apt-get install libunwind8 gettext apt-transport-https
```

ホームディレクトリにdotnetフォルダを作りそこにさっきwgetでダウンロードしてきたファイルを解凍する
※もしDLしてきたファイルがバージョン違ったりするならファイル名を変えてください

```
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-3.1.100-linux-arm.tar.gz -C $HOME/dotnet
```

次にPATHを通す必要があるので

```
sudo nano ~/.bashrc
```
nanoで.bashrc開いて最後の行に以下を挿入

```bash:.bashrc
DOTNET_ROOT=$HOME/dotnet
PATH=$PATH:$HOME/dotnet
```

保存したら下記コマンドで再読込

```
. ~/.bashrc
```

これでバージョンが出ればインストール成功

```
dotnet --version
3.1.100
```


## とりあえずあるあるなLチカ（LEDをちかちかさせる。）をやってみる。
Raspberry PiはLEDを付けるときに抵抗が必要なのでプラス側でもマイナス側でもどっちでもいいので
200Ωくらいの抵抗を適当にかますとLEDが燃えない。
いきなり燃えるわけではないけどそのまま付けると負荷が大きくて点かなくなる！

マイナス側はRaspberry PiのGNDのどこでもいいので付ける
プラス側は今回はコードでGPIO4を使うのでそこに付ける。

###### ちなみにこの回路図は僕が今作ってる[IoTHubTools](https://iothub.tools/iothubtools/)というサービスで自動生成した（まだ非常に見にくい....）

<img width="641" alt="コメント 2019-12-17 235855.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336684/004212cd-b636-d3b2-8d3b-e410590c995e.png">


コードはこんな感じGPIOピンの初期化を行い
1秒ごとにON/OFFを繰り返す感じになっている。

```c#:Program.cs
using System;
using System.IO;
using System.Threading;

namespace RasPiCtrlLED
{
    class Program
    {
        // GPIOピンの初期設定を行う.
        public static void initGPIOPin(int gpio)
        {
            if (Directory.Exists("/sys/class/gpio/gpio" + gpio) == false)
            {
                ///sys/class/gpio/exportにGPIOピン番号を書き込む.
                using (var writer = new StreamWriter("/sys/class/gpio/export"))
                {
                    writer.WriteLine(gpio.ToString());
                }
            }

            System.Threading.Thread.Sleep(100);
            // /sys/class/gpio/gpioX/direction
            using (var writer = new StreamWriter("/sys/class/gpio/gpio" + gpio + "/direction"))
            {
                writer.WriteLine("out");
                writer.Close();
            }
        }

        // GPIOのON/OFFを制御する.
        public static void switchGPIO(int gpio, int level)
        {
            // /sys/class/gpio/gpioX/valueの内容が0/1でOFF/ONが求まる.
            using (var writer = new StreamWriter("/sys/class/gpio/gpio" + gpio + "/value"))
            {
                writer.WriteLine(level.ToString());
                writer.Close();
            }
        }

        static void Main(string[] args)
        {
            // GPIO4を初期化する.
            initGPIOPin(4);
            while (true)
            {
                // LEDを点灯する.(GPIO4をONにする)
                switchGPIO(4, 1);
                // 1秒待機.
                Thread.Sleep(1000);
                // LEDを消灯する.(GPIO4をOFFにする)
                switchGPIO(4, 0);
                // 1秒待機.
                Thread.Sleep(1000);
            }
        }
    }
}
```

### 動画はこんな感じ

[![動画はこんな感じ](http://img.youtube.com/vi/O56GV7dKsoY/0.jpg)](http://www.youtube.com/watch?v=O56GV7dKsoY)

めっちゃごちゃごちゃしているがこれは作ってみたラジコン的な奴に色々ついてるのでケーブルがごちゃついている。

作った奴に使っているのは
##### タイヤとかキャタピラとかをこいつで
[タミヤ 楽しい工作シリーズ No.100 トラック&ホイールセット](https://www.amazon.co.jp/dp/B001VZJDY2/)
##### 車体をこれで作ってRaspberry Piもこの上に乗っける
[タミヤ 楽しい工作シリーズ No.157 ユニバーサルプレート 2枚セット](https://www.amazon.co.jp/dp/B001VZHRXG/)
##### 前後と左右回転させるためにモーターが二つ入っている奴をチョイス
[楽しい工作シリーズ No.168 ダブルギヤボックス 左右独立4速タイプ](https://www.amazon.co.jp/dp/B001Q13BIU/)

### こいつを組み上げて作って行くぅ！

## んでできたのがこいつ。（ごちゃぁ）
![DSC04034.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336684/92983159-3a7d-5208-bc79-4f1df673ac8b.jpeg)
![DSC04035.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336684/f4f52c56-94af-2c2b-a3b2-19c4d98f7eae.jpeg)


モーターを動かすためにはRaspberry Piに直接繋げることはできなくて
モータードライバーという物と電源が別に必要になってくる。

ほんとは色々遠隔操作できるようにすると面白いけど多くなりすぎるのでとりあえずモーターを動かすって所までやってみようと思う。

<img width="724" alt="2019-12-18020143.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336684/536e965e-93f0-6a11-bd65-5780a2767c62.png">

まずモータードライバーというのがこれ
[TA7291Pデータ](https://www.marutsu.co.jp/contents/shop/marutsu/datasheet/ta7291.pdf)
こいつを使ってモーター制御を行う。

こいつを使うとモーターを右回り、左回り、ブレーキ、回転速度の制御ができる。
[詳しくはこの素晴らしい記事をご覧頂くのが良い](https://qiita.com/gpioblink/items/d9addbe2851b91e538ac)

|端子記号	|ピン番号|		||
|---|---|---|---|
|Vcc	|7	|ロジック側電源端子	|マイコンや回路の最大出力電圧を接続
|Vs	|８	|出力側電源端子	|モーターで使用する電源のプラスを接続
|Vref	|４	|端子電源端子	|モーターに流す電圧を決定する電圧を接続
|GND	|１	|GND	|マイコンのGND端子とモータで使用する電源のマイナスを接続
|IN1	|５|	入力端子	|命令表にしたがって操作を選択するHighまたはLowを接続
|IN2	|６	|入力端子	|命令表にしたがって操作を選択するHighまたはLowを接続
|OUT1	|２	|出力端子	|モーターの片側を接続
|OUT2	|１０	|出力端子	|モーターのもう片側を接続

上記のようなピンの仕様になっている。

今回は

|TA7291P|RaspberryPi|RaspberryPiのピン番号|
|---|---|---|
|GND|GND|6|
|Vref|GPIO18|12|
|IN1|GPIO14|8|
|IN2|GPIO15|10|
|VCC|5V|2|
|Vs|none|電源のプラス端子|

こんな感じで配線を行った。

```c#:Program.cs
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace DCMotorPWMCtrl
{
    class Program
    {
        public const int PWM_MODE_MS = 0;

        public const int INPUT = 0;
        public const int OUTPUT = 1;
        public const int PWM_OUTPUT = 2;
        [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 void pwmWrite(int pin, int value);

        static void Main(string[] args)
        {
            // wiringPiのセットアップ
            wiringPiSetupGpio();
            // GPIO 14をOUTPUT(1)に設定する.
            pinMode(14, OUTPUT);
            // GPIO 15をOUTPUT(1)に設定する.
            pinMode(15, OUTPUT);
            // GPIO 18をPWM_OUTPUT(2)に設定する.
            pinMode(18, PWM_OUTPUT);
            // 初期状態としてモーターを停止する.
            digitalWrite(14, 0);
            digitalWrite(15, 0);
            // モーターを正転する.
            digitalWrite(14, 1);
            digitalWrite(15, 0);
            // 回転数を1/4に設定する
            pwmWrite(18, 256);
            // 3秒待機する.
            Thread.Sleep(3000);
            // 回転数を1/2に設定する
            pwmWrite(18, 512);
            // 3秒待機する.
            Thread.Sleep(3000);
            // 回転数を最大に設定する
            pwmWrite(18, 1024);
            // 3秒待機する.
            Thread.Sleep(3000);
            // モーターをブレーキする.
            digitalWrite(14, 1);
            digitalWrite(15, 1);

        }
    }
}

```

このコードでモーターを一つ制御できる。
二つ制御する場合はこれを二つ書けば良い。

この先でやることは
二つのモーターをコントロールさせるために
TA7291Pを二つ繋げてそれをコントロールするコードを
さっきのコードを元に書く。
例えば左側のモーターを正転させて右側のモーターを逆転させれば車体を右に回転させることができたりする。

C#ならこのコードを一つの言語でフロントと繋げてブラウザからコントロールさせるとかもできるが
一つの記事でまとめると流石に書くのが大変すぎたのでやめた。

一通りやるとこんな感じの動作ができる。

[![動画はこんな感じ](http://img.youtube.com/vi/QacJsCQR4ds/0.jpg)](http://www.youtube.com/watch?v=QacJsCQR4ds)

## 一旦まとめ
ひとまずだだーと勢いでここまで書いたけど
こういうハードウェアってココをオンにするオフにするといった感じのすごく単純なコードを書くだけで
制御自体は結構簡単にできてしまう。
それに付随するハードウェア自体のコントロール（今回使っているのだとPWM制御とか）がちょっと理解するのに時間かかったりするが
それも中高レベルの物理がなんとなく分かればそんなに難しくないのでハードウェアちょっとやってみたいんだけど
難しそうだよねってまだチャレンジしていない人がいたら是非やってみて欲しい。
そしてどんどんアウトプットして下さい！

1人でも多くのハードもできるエンジニアができることを願って。。

#### 以上！


参考記事
https://codezine.jp/article/detail/11677