FlashAirでIOエキスパンダMCP23017を制御してみた

#FlashAir W-03に新しいLua関数が追加された！
　2015年10月27日にFlashAir W-03シリーズのファームウェアがバージョンV3.00.01にアップデートされました。更新履歴には特に記載がありませんが、W-03発売当初から搭載されたLuaスクリプト環境においても、バージョンアップがされ、新しい関数が追加されました。
　バージョンV3.00.01リリース当初はFlashAir DevelopersサイトでLua関数リファレンスが更新されず、新しい関数の使い方は試行錯誤が求められましたが、12月4日ころ、ついにLua関数リファンレンスが更新され、新しい関数の使い方が公開されました。

　[Lua関数リファレンス](https://flashair-developers.com/ja/documents/api/lua/reference/)

　Lua関数リファレンスの更新公開以前に、新しい関数のひとつであるsharedmemory関数については試行錯誤の末、使い方を解析していました。

　[Luaスクリプトから共有メモリを利用する](https://flashair-developers.com/ja/support/forum/#/discussion/64)

　今回は、新しい関数の一つであるfa.spi関数を使って、FlashAirからソフトウェアSPIで、Airio RPとI2C接続したIOエキスパンダMCP23017を制御してみます。

#構成
　必要なものは以下のとおりです。

- Airio RP （[スイッチサイエンス](https://www.switch-science.com/catalog/2373/) 、[マルツーパーツ](http://www.marutsu.co.jp/pc/i/557784/)）
- FlashAir W-03 V3.00.01アップデート済みのもの
- MCP23017 （[秋月電子通商](http://akizukidenshi.com/catalog/g/gI-09486/)）
- 抵抗（10KΩ）２個（I2Cラインのプルアップ用）
- ブレッドボード
- 動作確認用のLEDと抵抗

![airiorp_mcp23017.jpg](https://qiita-image-store.s3.amazonaws.com/0/89137/f1a899bc-5751-7a67-5ea5-18611a2c8114.jpeg)

　今回、MCP23017はアドレス設定ピンA0〜2を３本ともGNDに接続して0x20に設定しています。また、MCP23017のGPIOの動作確認用にGPIOAとGPIOBの代表ピンにLEDを接続しています。
　I2C接続の２本の線（SDA、SCL）は、10KΩ抵抗でプルアップしてあります。

#CONFIGファイルの設定
　FlashAirのSD_WLANフォルダ内のCONFIGファイルに、以下のオプションを追加します。IFMODEはFlashAirのGPIOモードをONにしています。LUA_RUN_SCRIPTはFlashAirの電源投入後すぐに指定のLuaスクリプトを起動するための設定です。
```IFMODE=1
LUA_RUN_SCRIPT=/mcp23017sample.lua
```

　※SD_WLANフォルダとCONFIGファイルは不可視属性ファイルなので注意してください。

#Luaスクリプトファイル
　FlashAirのルートフォルダに以下のコードを記述したテキストファイル（mcp23017sample.lua）をコピーします。
　このコードでは、MCP23017のGPIOAとGPIOBの各8本のGPIOピンを交互に１秒ずつHIGHとLOWを切り替えています。GPIOAとGPIOBのGPIOピンにLEDを接続すれば、１秒ずつ交互に点滅するようになります。

(2015/12/8追記)fa.spi("init", N)について
　fa.spi("init", N)のN値について、@Seg_Faulさんが[解析してくれた](https://twitter.com/Seg_Faul/status/674197300592312320)ので、代表的な値＝SPI周波数値で動作確認してみました。結果は以下の通りとなりました。

- 26400000＝約1Hz・・・動作しない
- 528000＝約50Hz・・・以下全て動作した
- 253000＝約100Hz
- 25900＝約1kHz
- 3000＝約8.8kHz
- 2225＝約10kHz
- 1000＝約26kHz（default）
- 645＝約20kHz
- 245＝約100kHz
- 67＝約300kHz
- 32＝約500kHz
- 12＝約800kHz
- 5＝約1MHz
- 1＝約1.2MHz


```mcp23017sample.lua
-- FlashAir AirioRP
-- I2C IO Expander MCP23017
function write_i2c_command(addr,data1, data2)
	fa.spi("cs",0)
	fa.spi("write",0x00)  --I2Cコマンド送信
	fa.spi("write",0x02)  --2バイト指定
	fa.spi("write",addr)  --I2Cデバイスのアドレス＋0
	fa.spi("write",data1)
	fa.spi("write",data2)
	fa.spi("cs",1)
end

fa.spi("init", 1) --Airio RPは1〜528000の代表値で動作確認済み
fa.spi("mode", 2) --Airio RPは2で動作確認済み

write_i2c_command(0x40, 0x00, 0x00) --GPIOAをOutputに指定
write_i2c_command(0x40, 0x01, 0x00) --GPIOBをOutputに指定

while(1) do
	write_i2c_command(0x40, 0x12, 0xFF) --GPIOAをすべてHIGHに指定
	sleep(1000)
	write_i2c_command(0x40, 0x12, 0x00) --GPIOAをすべてLOWに指定
	sleep(1000)
	write_i2c_command(0x40, 0x13, 0xFF) --GPIOBをすべてHIGHに指定
	sleep(1000)
	write_i2c_command(0x40, 0x13, 0x00) --GPIOBをすべてLOWに指定
	sleep(1000)
end
```

#まとめ
　以上で、FlashAirからAirio RP上のSPI-I2Cブリッジ（CP2120）を使って、ソフトウェアSPIでI2CデバイスであるMCP23017のGPIOピンのHIGH/LOWを制御することができました。これで、FlashAirに一気に16本のGPIOを増設することができて、応用の幅が大きく広がりますね。また、同じようにIOエキスパンダ以外のI2Cデバイスも制御できるのではないかと思います。

#参考資料
　Airio RPについて
　[FlashAirプロトタイピングボード「Airio RP」](https://flashair-developers.com/ja/documents/resources/airiorp/)

　MCP23017について
　[MCP23017データシート](http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf)