14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

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

はい!すきです!

良い返事ありがとうございます。

C#好きですよね?

###...ハイ好きです。

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

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

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

オブジェクト指向でなぜつくるのか
をまず読んでオブジェクト指向の変な先入観を取り払って
スラスラわかるC#
を読んで弄り始めてみると楽しくなると思います!!

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

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

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

ちなみにこんなのを作る事が出来るようになるさわりのお話し。
DSC04035.JPG

まずは環境構築から。

とりあえずRaspberry Piの初期設定は終わっていてリモート操作はできる状態までいった前提で話していく。
その辺はここを見て貰うのが早い
Raspberry Pi 初期設定

基本的に下記コマンドは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

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

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

GitHub - dotnet/core: Home repository for .NET 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開いて最後の行に以下を挿入

.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というサービスで自動生成した(まだ非常に見にくい....)
コメント 2019-12-17 235855.png

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

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);
            }
        }
    }
}

動画はこんな感じ

動画はこんな感じ

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

作った奴に使っているのは

タイヤとかキャタピラとかをこいつで

タミヤ 楽しい工作シリーズ No.100 トラック&ホイールセット

車体をこれで作ってRaspberry Piもこの上に乗っける

タミヤ 楽しい工作シリーズ No.157 ユニバーサルプレート 2枚セット

前後と左右回転させるためにモーターが二つ入っている奴をチョイス

楽しい工作シリーズ No.168 ダブルギヤボックス 左右独立4速タイプ

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

んでできたのがこいつ。(ごちゃぁ)

DSC04034.JPG
DSC04035.JPG

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

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

2019-12-18020143.png

まずモータードライバーというのがこれ
TA7291Pデータ
こいつを使ってモーター制御を行う。

こいつを使うとモーターを右回り、左回り、ブレーキ、回転速度の制御ができる。
詳しくはこの素晴らしい記事をご覧頂くのが良い

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

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

今回は

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

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

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

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

動画はこんな感じ

一旦まとめ

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

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

以上!

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

14
15
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
14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?