LoginSignup
5
0

組込Linux(など)で動く mruby peripheral interface guide 互換の gem を作りました

Posted at

しまねソフト研究開発センター(略称 ITOC)にいます、東です。
これは Ruby Advent Calendar 2023 の記事です。

Abstract

結論

作りました。

うれしいこと

  • CRuby でも、IoT ができる。Raspberry Pi をはじめとして、組込 Linux ボードで CRuby使って IoT とか、よさそうじゃない?
  • もっと「小さく」「低コストに」「省電力に」したくなったら、マイコンボードに mruby か mruby/c を載せて、同じ Ruby プログラムをうごかすんだ。

そんなわけで、ガイドラインのうち、Linux のデバイスドライバレベルでサポートされている4種類、"GPIO", "I2C", "SPI", "UART" の rubygem ライブラリを作りました。
ラズベリーパイ4 と、アットマークテクノの Armadillo-IoT G3 で動作確認をしています。

GPIO クラスについて

GPIOは、General-purpose input/output の略で、汎用の入出力です。1ビット単位の入力または出力ができます。
入力の代表的な例はプッシュスイッチのON/OFF 状態など、出力の代表的な例は、LEDの点灯などです。

ガイドライン

実装

Linux の sysfs を使っています。GPIO の sysfs は既に使用が非推奨になっていますが、新しい仕組みが使いたいボード類で十分出そろったら、そのときに考えます。

ElChika(えるちか)サンプル

require "mruby/gpio"   # or "mruby/gpio/sysfs"

led = GPIO.new(26, GPIO::OUT)  # GPIO26番ピンを出力に設定し、そのインスタンスを得る
while true
  led.write( 1 )           # 出力1 -> LED点灯
  sleep 1
  led.write( 0 )           # 出力0 -> LED消灯
  sleep 1
end

プッシュスイッチとLED(入出力)のデモ

ソースコード
https://github.com/HirohitoHigashi/mruby-mio/blob/main/mruby-sysfs-gpio/test/led5sw1_polling.rb

実行結果
led_anim.gif

未実装

プルアップ、プルダウンの機能などについては、sysfs にその機能が無いのでサポートできていません。

I2Cクラス, SPI クラス

I2C, SPI は、両方ともシリアル入出力バスの規格で、主にセンサーや小型ディスプレイの接続などに使用されます。

ガイドライン

実装

いずれも、Linux device driver の ioctl だけを使って PureRubyで書いています。perl ゆずり(と思われる)pack / unpack を駆使しますが、もう少しマシな方法が欲しいと思いますよね。

気圧センサ LPS25H 読み取りサンプル

require "mruby/i2c"

# create instance
i2c = I2C.new("/dev/i2c-1")

# Write to device at address 0x5c, data 0x20, 0x90.
i2c.write( 0x5c, 0x20, 0x90 )

# Read 5 bytes from the device at address 0x5c.
# Outputs 0xa8 before reading.
s = i2c.read( 0x5c, 5, 0xa8 )

加速度センサで重力方向を検出するデモ

ソースコード
https://github.com/HirohitoHigashi/mruby-mio/blob/main/mruby-linux-spi/test/ADXL345_Accelerometer.rb

実行結果
adxl345_demo-2.gif

未実装

I2Cの 低レベルメソッドは、実装していません。

UART クラス

UART クラスは、通常1対1のシリアル通信をサポートする規格で、RF通信モジュールをはじめとし、様々なデバイスが接続できます。

ガイドライン

実装

このクラスだけは、下層に serialport gem を使用します。汎用的に作ろうとすると、どうしてもC拡張が必要になりそうだったので、よくできている gem に頼りました。

サンプル Echo server

require "mruby/uart"   # or "mruby/uart/serialport"

uart = UART.new("/dev/serial0")
while true
  s = uart.read(1)
  uart.write s
  print s
end

おわりに

ADC と PWM については、マイコンボードの種類ごとにハードウェアを直接たたくコードを書くしかなさそうです。また、現在は LinuxOS のサポートだけですが、FreeBSD も I2C等のデバイスドライバが用意されているので、そちらへの対応もしたいと考えています。

それでは、Happy Holidays!

5
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
5
0