I2C (mruby/c)
はじめに
教育ボードに搭載されている液晶ディスプレイ (LCD) とリアルタイムクロック (RTC) を使う. 下記で述べるように, プログラムを穴埋め形式にしているので, データシートから必要な情報を読み取って それを埋めることを試みて欲しい.
プロジェクトの準備
基本的に ESP-IDF 環境と同じなので, ESP-IDF 環境がインストールされているディレクトリ (ここでは $HOME/esp) 以下にプロジェクト用のディレクトリを作る. GitHub から j5_es_2020 ブランチを git clone する. なお, このブランチは make menuconfig で機能を設定することはできないので注意すること.
$ cd ~/esp $ git clone -b j5_es_2020 https://github.com/gfd-dennou-club/iotex-esp32-mrubyc.git mrubyc-04-i2c $ cd mrubyc-04-i2c
プログラムの作成
LCD に最初の 10 秒間 "Hello!! from ESP" と表示させ, その後に時刻を表示させるようにする.
プログラムの中身については, データシートとプログラム中の注釈を参照のこと. なお, プログラムに対する詳細なコメントは Arduino IDE 版に付けたので, そちらも参照して欲しい.
- 液晶ディスプレイ(LCD) AQM0802A-RN-GBW
- リアルタイムクロック (RTC) RC-8035SA 日本語, 英語
mrblib/loops/master.rb
1 # coding: utf-8-hfs 2 3 #I2C 初期化 4 i2c = I2C.new(0, 22, 21) 5 i2c.driver_install 6 7 # LCD 初期化 8 lcd = AQM0802A.new(i2c) 9 lcd.setup 10 11 # LCD に "Hello World" 表示 12 lcd.cursor(1, 0) 13 lcd.write_string("Hello!") 14 lcd.cursor(0, 1) 15 lcd.write_string("from ESP") 16 sleep(10) 17 18 # RTC 初期化. 時刻設定 (2020/03/31 23:59:50 に手動で設定) 19 rtc = RC8035SA.new(i2c) 20 rtc.write([0x20, 0x03, 0x31, 1, 0x23, 0x59, 0x50]) #年(下2桁), 月, 日, 曜日, 時, 分, 秒 21 22 while true 23 # 時刻表示 24 tt = rtc.read 25 lcd.cursor(0, 0) 26 lcd.write_string(sprintf("%02x-%02x-%02x", tt[0], tt[1], tt[2])) 27 lcd.cursor(0, 1) 28 lcd.write_string(sprintf("%02x:%02x:%02x", tt[4], tt[5], tt[6])) 29 sleep(1) 30 end
mrblib/models/i2c.rb
1 class I2C 2 def initialize(port, scl, sda) 3 @port = port 4 @scl = scl 5 @sda = sda 6 end 7 end
[穴埋め問題] mrblib/models/aqm0802a.rb
1 # AQM0802A-RN-GBW 2 # 3 # I2C address : 0x3e 4 5 class AQM0802A 6 7 def initialize(i2c) 8 @i2c = i2c 9 end 10 11 def setup 12 @i2c.write(0x3e, []) # データシートから適切なコントロールバイト, データバイトを与えよ 13 sleep(1) 14 @i2c.write(0x3e, []) # データシートから適切なコントロールバイト, データバイトを与えよ 15 end 16 17 def clear 18 @i2c.write(0x3e, []) # データシートから適切なコントロールバイト, データバイトを与えよ 19 end 20 21 def cursor(x, y) 22 @i2c.write(0x3e, []) # データシートから適切なコントロールバイト, データバイトを与えよ 23 end 24 25 def write_string(s) 26 a = Array.new 27 a.push(0x40) # コントロールバイト (0x40 は書き込み) を配列に追加 28 s.length.times do |n| 29 a.push(s[n].ord) # データバイトを配列に追加 30 end 31 @i2c.write(0x3e, a) # I2C アドレスと, コントロールバイト・データバイトの配列を与える 32 end 33 34 end
- 7-9 行目 : コンストラクタ
- 11-15 行目 : 初期化メソッド.
- 12, 14 行目 : I2C 通信の中核部分 (C 言語のライブラリの読み出し部分). 引数として I2C アドレス (0x3e) と, コントロールバイトとデータバイトから成る配列を与える.
- 17-19 行目 : LCD の画面のクリアするメソッド
- 21-23 行目 : LCD の画面のカーソルを指定の場所に移動させるメソッド
- x は左から何番目かを示す (x = 0..7). y は行数を示す (y = 0 or 1)
- 25-32 行目 : LCD に文字列を書くメソッド
[穴埋め問題] mrblib/models/rc8035sa.rb
1 # coding: utf-8 2 # RTC: EPSON RC-8035SA 3 # 4 # I2C address : 0x32 5 6 class RC8035SA 7 def initialize(i2c) 8 @i2c = i2c 9 @i2c.write(0x32, []) # データシートから適切な値を与えよ 10 sleep 0.1 11 end 12 13 def read 14 a = @i2c.read(0x32, 8) # 8 バイト分読み込み 15 ctrl2 = a.shift 16 return [a[6], a[5], a[4], a[3], 0x3f & a[2], a[1], a[0], ctrl2] 17 end 18 19 def write(date) 20 @i2c.write(0x32, []) # 時刻の設定部分をデータシートから考えてみよ 21 sleep 0.1 22 @i2c.write(0x32, [0xF0, 0x00]) 23 sleep 0.1 24 end 25 end
- 7-11 行目: コンストラクタ
- 9 行目: 初期化プロセスも同時に行っている. レジスタ Eh, Fh をゼロクリアする命令を書き加えよ.
- 13-17 行目: 読み出しメソッド.
- 8 バイト分読み出し, それぞれを配列に格納する (配列の各要素が「年」, 「月」, ... を表す).
- 16 行目 : なぜ 0x3f との AND を取っているかデータシートを元に考えてみよ.
- 19-24 行目: 書き込みメソッド
- 20 行目: 時刻の設定.
- mrblib/loops/master.rb の 20 行目と対応させて考えてみよ.
- 20 行目: 時刻の設定.
コンパイルと実行
コンパイルと実行を行う.
$ make $ make flash monitor