🌡️

PicoRuby R2P2とI2C通信で室温測定してみた

に公開

はじめに

この記事はRaspberry Pi PicoでR2P2をインストールし、温度センサーモジュールから室内温度を出すまでの話です。

筆者はWebエンジニアですが、RubyKaigi2025PicoRubyの存在を知り、普段触っているRubyで組み込みができる事にワクワクし今回チャレンジしてみました。
Raspberry Pi Pico(以下:ラズパイ)へのセットアップやシリアル通信はWindows 11環境で行っています。

R2P2をインストール

今回はすでにビルドしてあるものを使います。
https://github.com/picoruby/R2P2/releases/tag/0.4.1

上記からダウンロードして解凍します。uf2 という拡張子のファイルがあるので、ブートモードで起動したら .uf2ファイルをドラッグ&ドロップすると自動で書き込み・再起動されます。
すると、自動で再起動されR2P2 のストレージがマウントされます。

さらに、シリアル通信の確認でWindowsのデバイスマネージャーでポートが追加されていることを確認します。

デバイスマネージャ

シリアル通信のクライアントソフトは色々あるようですが、今回はTera Term を使います。
シリアル通信の設定は以下のようにしました。

「Starting shell...」やPicoRubyのタイトルも見ることができます。$>が出てきたらコマンド入力が可能です。irb も入っていて色々試せそうです。

温度センサーモジュールをラズパイに接続

今回は秋月電子でADT7410温度センサーモジュールを買いました。

https://akizukidenshi.com/catalog/g/g106675/

このセンサーモジュールとラズパイをI2C通信で接続し、温度情報を取得します。
I2Cは複数のノードを並列で接続することができ、それぞれ固有のアドレスを持ちます。
上記商品は4ピンあり、電源(VDD)、SCL、SDA、GNDとあります。
SCLとSDAがI2C通信用でSCLがクロック信号、SDAがデータ信号として使われます。ラズパイ側は物理ピン1番と2番を使います。VDDやGNDもラズパイの3VとGNDを使います。


引用元 - Pico-series Microcontrollers

とりあえず動かしたいので、ブレッドボードに刺してありあわせのケーブルで接続しています。

R2P2 irbでデバイス確認

irbを使ってまずはI2C通信でデバイスが認識できているか確認します。

$> irb
irb> require 'i2c'
=> true
irb> i2c = I2C.new(unit: :RP2040_I2C0, sda_pin: 0, scl_pin: 1)
=> #<I2C:2000b6a8>

RP2040 というのはラズパイで使われているマイクロコントローラチップ名です。
I2C通信を行う今回のピン番号を入れてI2Cクラスをnewします。
I2Cデバイスにはそれぞれユニークなアドレスが割り当てられる仕様で、この製品のデフォルトの設定 0x48 を使います。

irb> i2c.scan
I2C device found at 7-bit address 0x48 (0b1001000) +R
=> nil

scanメソッドをつかい現在I2Cバス上に存在するデバイスのアドレスが取得できます。今回は、0x48がかえってくる事を期待しています。とりあえず認識できてそうです。

温度データを受信する

詳細は割愛しますが、ADT7410では13bit(分解能0.0625℃)で温度情報を取得してセルシウス度(℃)が算出できるようです。(16bit分解能に変更することも可能)
0.5秒間隔で受信して、そのままシリアルコンソールに出力するようにします。
Windows のエクスプローラーで /home を開き、adt7410_sample.rb を新規作成し、VSCodeで編集しました。

class ADT7410
  def initialize
    @i2c = I2C.new(
      unit:      :RP2040_I2C0,
      sda_pin:   0,
      scl_pin:   1
    )
  end

  def read_13bit(addr)
    @i2c.write(addr, 0x00)
    msb, lsb = @i2c.read(addr, 2).bytes
    row = (msb << 8) | lsb

    adc = row >> 3
    # マイナス値の場合
    adc -= 0x2000 if adc & 0x1000 != 0

    adc / 16.0
  end
end

adt = ADT7410.new

loop do
  tmp_c = adt.read_13bit(0x48)
  puts "Temperature: #{tmp_c} ℃"
  sleep 0.5
end

実行結果

以下のように、cdコマンドで/home へ移動し./[rubyファイル] でスクリプトが実行できます。

$> cd /home
$> ./adt7410_sample.rb
Temperature: 28.2500 ℃
Temperature: 28.2500 ℃
Temperature: 28.3125 ℃
Temperature: 28.2500 ℃

0.5秒ごとに温度が表示されました。指を当てると表示温度は上昇しセンサーもきいているようです。

おわりに

普段触っているRubyで動かしてみたい、かつLチカだけだと物足りなさを感じて今回I2C通信を扱った記事を書いてみました。I2C通信もgemとして提供されているのがありがたいです。Rubyでビット操作する機会もあまりないので新鮮ですね。
今後はキャラクタLCDに表示させたり、WiFi通信させたりと、チャレンジしてみようと思います。

Discussion