知り合いから、とある環境の温度を連続的に測定し、これをクラウドで分析したいのでアドバイスが欲しいとの依頼を受け、秋葉原で温度センサーADT7410を試しに購入してきました。
ということで、今回は、FlashAirのLuaスクリプト実行環境を使って、秋月電子通商さんのFlashAir用ブレイクアウトボード「FlashAir DIP IOボードキット」で温度センサーADT7410をI2C接続して、温度測定をしてみたいと思います。
#構成
必要なものは以下のとおりです。
- FlashAir DIP IOボードキット(秋月電子通商)
- FlashAir W-03 V3.00.01アップデート済みのもの
- ADT7410使用高精度・高分解能I2C・16bit温度センサモジュール(秋月電子通商)
- I2C接続小型キャラクタLCDモジュール 8x2行(秋月電子通商)
- ブレッドボード用マイクロBメスUSBコネクタDIP化キット(秋月電子通商)
- 3.3V 500mA 三端子レギュレーター(秋月電子通商)
- ブレッドボード
#温度センサーADT7410の接続
ADT7410はアドレス設定ピンA0、A1を2本ともオープン(未接続)のままにして0x48(書き込みアドレス0x90、読み込みアドレス0x91)に設定しています。
FlashAir DIP IOボードキットとI2C接続の2本の線(SDA、SCL)を結びます。FlashAir DIP IOボードキットの裏面のジャンパーをショートさせてプルアップしています。
ADT7410は5.0Vでも動作しますが、今回はLCDモジュールの電源供給用の3.3Vで動作させています。
#小型キャラクタLCDモジュールの接続
ADT7410とともに、LCDモジュールのI2C端子をバス接続しておきます。LCDモジュール単体ではブレッドボードに挿さらないので、ピッチ変換基盤を使うとよいでしょう。
このLCDモジュールのI2Cアドレスは、0x7C固定です。
このLCDモジュールは3.3V駆動なので、三端子レギュレータで3.3Vを作って供給しています。
#CONFIGファイルの設定
FlashAirのSD_WLANフォルダ内のCONFIGファイルに、以下のオプションを追加します。IFMODEはFlashAirのGPIOモードをONにしています。LUA_RUN_SCRIPTはFlashAirの電源投入後すぐに指定のLuaスクリプトを起動するための設定です。
LUA_RUN_SCRIPT=/adt7410_sample.lua
※SD_WLANフォルダとCONFIGファイルは不可視属性ファイルなので注意してください。
#Luaスクリプトファイル
FlashAirのルートフォルダに以下のコードを記述したテキストファイル(adt7410_sample.lua)をコピーします。
このコードでは、delaytimeに指定した時間待機して(以下のコードでは10秒)温度測定データをADT7410から受信し、LCDモジュールに表示することを繰り返します。
待機中の進捗状態がわかるように、LCDモジュールの1行目に表示される"Temp...."の"."(ドット)が1つずつ消えていくようにしています。
ADT7410はステータス情報を読み出すこともできますが、今回は省略しています。また、ADT7410は4つの測定モード(0:連続変換、1:ワンショット、2: SPS、3:シャットダウン)がありますが、今回は連続変換モードしか試していません。
-- FlashAir DIP IO Board Kit + ADT7410
local spi_init = 1
local spi_mode = 3
--温度センサーADT7410の設定値 ()はデフォルト値
local TempSensorSettingFaultQueue = 0 --(0):1フォルト、1:2フォルト、2:3フォルト、3:4フォルト
local TempSensorSettingCTPin = 0 --(0):Active Low 1:Active HIGH
local TempSensorSettingINTPin = 0 --(0):Active Low 1:Active HIGH
local TempSensorSettingCIMode = 0 --(0):割り込みモード 1:コンパレータモード
local TempSensorSettingMode = 0 --(0):連続変換、1:ワンショット、2: SPS、3:シャットダウン
local TempSensorSettingADCMode = 0 --(0):13ビット、1:16ビット
--温度センサーADT7410のアドレス設定値
local TempSensorWriteAddress = 0x90
local TempSensorReadAddress = 0x91
--温度測定周期
local delaytime = 10000 --msec
function delay(t)
sleep(t)
end
--温度センサーADT7410の初期化
function initTempSensor()
local settingVal = 0x00
settingVal = bit32.bor(settingVal, bit32.lshift(TempSensorSettingADCMode, 7))
settingVal = bit32.bor(settingVal, bit32.lshift(TempSensorSettingMode, 5))
settingVal = bit32.bor(settingVal, bit32.lshift(TempSensorSettingCIMode, 4))
settingVal = bit32.bor(settingVal, bit32.lshift(TempSensorSettingINTPin, 3))
settingVal = bit32.bor(settingVal, bit32.lshift(TempSensorSettingCTPin, 2))
settingVal = bit32.bor(settingVal, TempSensorSettingFaultQueue )
fa.spi("read")
fa.spi("cs",0)
fa.spi("write",0x00)
fa.spi("write",0x02)
fa.spi("write",TempSensorWriteAddress)
fa.spi("write",0x03)
fa.spi("write",settingVal)
fa.spi("cs",1)
end
--温度センサーADT7410から温度データを受信する
function getTempSensor()
local val = 0x00
local val1 = 0x00
local val2 = 0x00
local tmpval = 0
fa.spi("read")
fa.spi("cs",0)
fa.spi("write",0x01)
fa.spi("write",0x02)
fa.spi("write",TempSensorReadAddress)
fa.spi("cs",1)
fa.spi("read")
fa.spi("cs",0)
fa.spi("write",0x06)
val1 = fa.spi("write", 0xFF)
val2 = fa.spi("write", 0xFF)
fa.spi("cs",1)
val = bit32.bor(bit32.lshift(val1, 8), val2)
if(TempSensorSettingADCMode == 0) then
--13ビットモードの場合
val = bit32.rshift(val, 3)
tmpval = val / 16
if(val >= 4096) then
tmpval = (val - 8192) / 16
end
else
--16ビットモードの場合
tmpval = val / 128
if(val >= 32768) then
tmpval = (val - 65536) / 128
end
end
str = string.format("%6.1f", tmpval) .. string.char(0xDF) .. "C"
return str
end
--I2Cに2バイト分のデータを送信する
function write_i2c_command(addr,data1, data2)
fa.spi("read")
fa.spi("cs",0)
fa.spi("write",0x00)
fa.spi("write",0x02)
fa.spi("write",addr)
fa.spi("write",data1)
fa.spi("write",data2)
fa.spi("cs",1)
end
--I2C接続のLCDモジュールを初期化する
function lcd_init()
write_i2c_command(0x7c, 0x00, 0x38)
write_i2c_command(0x7c, 0x00, 0x39)
write_i2c_command(0x7c, 0x00, 0x14)
delay(10)
write_i2c_command(0x7c, 0x00, 0x70)
write_i2c_command(0x7c, 0x00, 0x56)
write_i2c_command(0x7c, 0x00, 0x6c)
delay(10)
write_i2c_command(0x7c, 0x00, 0x38)
write_i2c_command(0x7c, 0x00, 0x0c)
write_i2c_command(0x7c, 0x00, 0x01)
delay(10)
end
--I2C接続のLCDモジュールの画面表示をクリアする
function lcd_clear()
write_i2c_command(0x7c, 0x00, 0x01)
delay(5)
end
--I2C接続のLCDモジュールの画面に文字を表示する。LRは0:左揃え、1:右揃えの指定
function lcd_print(value, LR)
local num = string.len(value)
if (LR == 1) then
for idx = 1, 8 - num do
write_i2c_command(0x7c, 0x40, " ")
end
end
for idx = 1, num do
write_i2c_command(0x7c, 0x40, string.byte(string.sub(value, idx, idx)))
end
end
--I2C接続のLCDモジュールの画面に文字を表示する位置を指定する
function lcd_setCursor(x, y)
write_i2c_command(0x7c, 0x00, bit32.bor(0x80 , y * 0x40 + x))
end
--ここからメイン処理
fa.spi("init", spi_init)
fa.spi("mode", spi_mode)
lcd_init()
delay(100)
initTempSensor()
delay(300)
tmpdelaytime = delaytime / 4
while(1) do
lcd_setCursor(0x00, 0x00)
lcd_print("Temp....", 0)
lcd_setCursor(0x00, 0x01)
lcd_print(getTempSensor(), 1)
collectgarbage("collect")
delay(tmpdelaytime)
for delaycnt = 1, 3 do
upside_str = "Temp"
for delaycnt2 = 1, 4 - delaycnt do
upside_str = upside_str .. "."
end
for delaycnt2 = 1, delaycnt do
upside_str = upside_str .. " "
end
lcd_setCursor(0x00, 0x00)
lcd_print(upside_str, 0)
sleep(tmpdelaytime)
end
end
[注釈]fa.spi("read")の空readの必要性について
@Seg_faulさんの解析「fa.spiの挙動(秋月 FlashAir DIP IOボードキットでfa.spiが動かない問題)」に書かれている通り、秋月FlashAir DIP IOボードキットでは「CSが反映されないことがあるバグ(or仕様)」により、この空readを入れておかないと期待通りの動作になりません。
#まとめ
以上で、FlashAirと秋月FlashAir DIP IOボードキットを使って、温度センサーADT7410で温度測定ができるようになりました。今回はそこまで実装していませんが、せっかくのFlashAirですから、取得したデータを無線LANでクラウド環境にアップロードしてもよいですね。Azure IoT HubのREST APIを使ってfa.requestでデータ送信して、Power BIでグラフ化するなどしても良いのではないでしょうか。
#同人誌「宵の空」の通販始まりました
サークル「空と月」による同人誌「宵の空」(2015年12月発行、コミックマーケット89にて頒布)の通販取扱が、秋葉原の三月兎さんで始まりました。コミケに来られなかった方も、ぜひお手に取ってみてください。
お酒と電子工作について語ってみた本「宵の空」
#参考資料
FlashAir DIP IOボードキット
SC18IS600IBSデータシート
ADT7410データシート
LCDモジュールデータシート