GroveBeginnerKit を、C++(Arduino)とRuby(ラズパイ,Rboard) で使う　GPIO編

[しまねソフト研究開発センター](https://www.s-itoc.jp)（略称 ITOC）にいます、東です。

[Grove Beginner Kit for Arduino](https://wiki.seeedstudio.com/Grove-Beginner-Kit-For-Arduino/) というものを買ったので、数回に分けて　Arduino　と　Ruby　での使用レポートを書いてみようと思います。なおキットの性質上、初心者向けの学習用記事です。

ターゲットは、以下の通り。
* Arduino　- 付属の Arduino Uno 互換機
* Ruby - Raspberry Pi + [Grove Base HAT for Raspberry Pi](https://www.seeedstudio.com/Grove-Base-Hat-for-Raspberry-Pi.html)
* mruby/c - [RBoard](https://www.sjc-inc.co.jp/service/rboard)

予定しているレポートは、以下の通りです。

1. デジタル入出力 - GPIO編 (今回)
2. [アナログ入力 - ADC編](https://qiita.com/HirohitoHigashi/items/eb79dd65243a7d27dd2b)
3. [パルス出力 - PWM編](https://qiita.com/HirohitoHigashi/items/ca9dc1eea88a6196d1df)
4. [加速度センサー編](https://qiita.com/HirohitoHigashi/items/1e8a32900fa184581c16)
5. [気圧センサー編](https://qiita.com/HirohitoHigashi/items/7d2eec5b1d7b6af8bac8)
6. [温湿度センサー編](https://qiita.com/HirohitoHigashi/items/d2366cb60f025ac08c78)
7. [OLED編](https://qiita.com/HirohitoHigashi/items/f8626f791174384012df)

今回は、デジタル入出力 (GPIO) を使ってみます。


# Hardware overview

このキットは、Arduino互換機といくつかの Grove モジュールがセットになったもので、さらにそれぞれのモジュールを切り離すことができるよう設計された一つの基板になっています。

![HardwareOverview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/8ea2ce5b-2f5e-7781-f4ca-a898d68dfec6.jpeg)
（画像は公式ページからの引用）


# 準備

## Grove Beginner Kit

キットでは、すでに中心の Arduino と、各モジュール間は配線してあります。Arduino だけで試すならばこれで良いのですが、今回は別なマイコンもつなぎたいので切り離します。

![IMG_3033.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/48c5a502-ac16-9148-597f-bf2f49b65a76.jpeg)

## Arduino

このレポート内の追試をする範囲であれば、切り離しても切り離さなくても大丈夫です。この Arduino 互換機は、Groveコネクタがたくさんついているので、切り離しても付属の Groveケーブルでセンサー類との接続が簡単にできます。
その他の Groveモジュール等を別途購入して使う場合を考えると、リソース（接続するGPIO番号など）の重複などからむしろ切り離しておいた方が良いかもしれません。

## ラズパイ

ラズパイに Grove モジュールを接続するのに便利なように、Grove Base HAT for Raspberry Pi を取り付けます。
次に、I2Cを使えるように、Raspberry Pi OSのセットアップを行います。やり方は検索するといくらでも出てきます。
以下の通り、apt を使って ruby と使用するライブラリをインストールします。レポート内では使いませんが、併せて `i2c-tools` もインストールしておくと便利かと思います。
```
sudo apt install ruby
sudo gem install mruby-sysfs-gpio
sudo gem install mruby-serialport-uart
sudo gem install mruby-linux-i2c
sudo apt install i2c-tools
```

## RBoard

2024年3月現在、公式にはまだリリースがないようですが、[mruby 共通 API](https://github.com/mruby/microcontroller-peripheral-interface-guide) を使う事ができる最新のファームバージョンで試します。
最新ファームウェアは、自分でアップデートする場合は、[RBoard 公式 github ページ](https://github.com/YoshihiroOgura/pic32mx170_mrubyc) からソースコードを取得しビルドして書き込みます。もしくはメーカーに依頼すればたぶんやってくれます。

# 1. ElChika （えるちか）

まずは、Grove - Red LED モジュールを使って、基本のエルチカをやってみます。GPIO の出力サンプルとなります。

| 外観 | 回路図 |
|:-:|:-:|
| ![grove_RedLED.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/ab8c259f-bb28-e622-90bc-a03fc597fbb7.jpeg) | ![grove_RedLED_Schema.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/3a2a35b9-9371-7f12-333a-dfb9d529a610.png)　|

（[メーカーWiki: Grove - Red LED](https://wiki.seeedstudio.com/Grove-Red_LED/) より引用）

LEDの他に少し部品がついていますが、要は Grove Digital ピンの High/Low に応じてLEDが点灯/消灯するだけです。VRにLED点灯電流を流しているのが、ちょっと気になりますね　:-P。


## 接続

![LED_Connect.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/da04f96f-520b-b13a-bb70-3dc9d732b389.jpeg)


## Arduino

`D4` 番に LEDを接続します。切り離さなければ、そこに接続されています。

```c++:ElChika.ino
void setup() {
  pinMode( 4, OUTPUT );
}

void loop() {
  digitalWrite( 4, HIGH );
  delay( 100 );
  digitalWrite( 4, LOW );
  delay( 900 );
}
```

プログラム中、ピン番号4 をマジックナンバーとして使っていますが、実用的なプログラムでは定数に定義したほうが良いです。時間待ち関数の `delay` は、単位が ms（ミリ秒） であることを覚えておかないといけないのが、ちょっとマイナスポイントですね。


## Raspberry Pi (CRuby)

Grove 端子 D5 へ接続します。
このHATは、デジタル端子の番号とGPIO番号は同じ番号で設計されているので、newの引数に5番ピンを指定します。

```ruby:ElChika.rb
require "mruby/gpio"

led = GPIO.new( 5, GPIO::OUT )

loop {
  led.write( 1 )
  sleep( 0.1 )
  led.write( 0 )
  sleep( 0.9 )
}
```

こちらは、`led` と名前をつけた変数により、ループ中で LED を操作していることが明示できています。時間待ちは　`sleep` になり、こちらは秒単位なのでわかりやすい反面、小数を使う事にためらいを感じる方もいるかもしれませんね。


## RBoard (mruby/c)

Grove 端子 Digital へ接続します。
[ピン配置図](https://yoshihiroogura.github.io/RBoardDocument/pin.html) により、16番ピンを使用することがわかります。

```ruby:ElChika.rb
led = GPIO.new( 16, GPIO::OUT )

loop {
  led.write( 1 )
  sleep( 0.1 )
  led.write( 0 )
  sleep( 0.9 )
}
```

Crubyと同じプログラムが動きます。


# 2. Button

次は、ボタン（プッシュスイッチ）を使って GPIO の入力をします。
作成するサンプルプログラムは、ボタンを押している間 LED を点灯させるプログラムを作ります。

| 外観 | 回路図 |
|:-:|:-:|
| ![grove_Button.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/b60c6146-5a51-f300-a602-556a030dc32b.jpeg) | ![grove_Button_Schema.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/bf2b4c6c-c3fb-1284-3af9-2b8295839d98.png) |

（[メーカーWiki: Grove - Button](https://wiki.seeedstudio.com/Grove-Button/) より引用）

プッシュスイッチが、10kΩの抵抗でプルアップされている回路になっています。

## 接続
![Button_Connect.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/df9003a0-6b51-0495-68ed-9d8e3ecb10ad.jpeg)

## Arduino
`D6` 番に接続します。切り離さなければ、そこに接続されています。LED は、オンボードのものを使います。

```c++:Button.ino
void setup() {
  pinMode( 6, INPUT );
  pinMode( 13, OUTPUT );  // onboard LED
}

void loop() {
  digitalWrite( 13, digitalRead( 6 ) );
}
```

## Raspberry Pi (CRuby)

ラズパイには、オンボード LED が無い（正確にはありますが、コントロール方法が違う）ので、先ほどの Grove LED を使います。

```ruby:button.rb
# connect
#  D16 (GPIO16) to Button
#  D5  (GPIO5)  to LED
require "mruby/gpio"

button = GPIO.new( 16, GPIO::IN )
led = GPIO.new( 5, GPIO::OUT )

while true
  led.write( button.read )
end
```
役者が、`button`, `led` と2人になり、名前をつけた意味がより感じられますね。

## RBoard (mruby/c)
Grove 端子 Digital へ接続します。
オンボード LED は、GPIOクラス経由でも使えますが、専用の関数 `leds_write` が用意してありますのでそれを使いました。
```ruby:button.rb
button = GPIO.new( 16, GPIO::OUT )

while true
  leds_write( button.read )
end
```

# おわりに

今回は、単純なデジタル入出力を試してみました。これだけ単純だと、各環境でほとんど差はないですね。
次回は、アナログ入力を試してみたいと思います。