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

#FlashAir W-03のLuaスクリプト実行環境
　FlashAir W-03シリーズでは、SDカード上でLuaスクリプトを実行できます。Luaスクリプトでは、FlashAirのGPIO機能を使って、ソフトウェアSPI（fa.spi関数）によりSPIデバイスを制御することができます。
　前回、[Airio RPとI2C接続したIOエキスパンダMCP23017を制御](http://qiita.com/ayasehiro/items/cd81cfd8c0635407ffef)しましたが、今回は、FlashAirと直結したIOエキスパンダMCP23S17（SPIインターフェース）を制御してみます。

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

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

- FlashAir W-03 V3.00.01アップデート済みのもの
- MCP23S17 （[マルツオンライン](http://www.marutsu.co.jp/pc/i/110438/)）
- SDカードスロット
- 3.3V定電圧レギュレータ（[秋月電子通商](http://akizukidenshi.com/catalog/g/gI-00538/)）
- ブレッドボード
- 動作確認用のLEDと抵抗
- ACアダプタ（5V）:手持ちのものを利用

更新した検証構成（2015/12/13追記）
![flashair_mcp23S17_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/89137/f5d1d281-c115-08dc-3c4c-e348ea1d1563.jpeg)

当初検証構成
![flashair_mcp23S17.jpg](https://qiita-image-store.s3.amazonaws.com/0/89137/97d04e14-4f5b-7150-472d-de7dac5a7630.jpeg)

###MCP23S17の接続
　今回、MCP23S17はアドレス設定ピンA0〜2を３本ともGNDに接続して0x20に設定しています。また、MCP23S17のGPIOの動作確認用にGPIOAとGPIOBの代表ピンにLEDを接続しています。

###SDカードスロット
　SDカードスロットはなんでも構いませんが、FlashAirでソフトウェアSPI（fa.spi関数）を使う場合、SDカードの2番、7番、8番、9番ピンを引き出せる必要があります。
　当初検証構成では、秋月のDIP化モジュールのチップ抵抗を外して改造したものを利用していました。これは9番ピンが引き出されていませんので、自分でワイヤーを接続する必要があります。またFlashAirは3.3V駆動ですので、外部電源が今回のように5Vの場合は、3.3Vに変換する必要があります。秋月のDIP化モジュールには3.3V定電圧レギュレータが搭載されているので、これを利用しました。（手元に3.3VのACアダプタがなかったので外部電源が5Vになりました）
（以下2015/12/13追記）
　更新した検証構成では、SDカードスロットを[カードソケットSD-N0940](http://www.aitendo.com/product/1194)を使ってDIP化を自作しました。これはFlashAirとMCP23S17のSPI接続のワイヤー長を極力短くするためです。

###FlashAirとMCP23S17の接続
　FlashAirとMCP23S17のSPI接続は、以下の表に示す対応通りに接続します。
![FlashAir_MCP23S17_pinasign.png](https://qiita-image-store.s3.amazonaws.com/0/89137/76d539ff-5acb-b63f-cc2f-b3f704dc015a.png)


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

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

#Luaスクリプトファイル
　FlashAirのルートフォルダに以下のコードを記述したテキストファイル（mcp23S17sample.lua）をコピーします。
　このコードでは、MCP23S17のGPIOAとGPIOBの各8本のGPIOピンを交互に１秒ずつHIGHとLOWを切り替えています。GPIOAとGPIOBのGPIOピンにLEDを接続すれば、１秒ずつ交互に点滅するようになります。
　以下のコードではfa.spi("init", 645)と比較的低い周波数を指定しています。これは高い周波数だと動作しなかったためです。MCP23S17の仕様上では10MHzまでサポートされていますので、fa.spi("init", 1)でも理論的には動作するはずですが、写真にあるように今回の構成ではFlashAirとMCP23S17を直結するワイヤーの長さが長いため高い周波数では動作しなかったものと思われます。
（以下2015/12/13追記）
　更新した検証構成では、fa.spi("init", 1)でも動作することを確認しました。やはり高い周波数にするにはSPI接続部分のワイヤー長を極力短くする必要があるようです。

```mcp23S17sample.lua
-- FlashAir AirioRP
-- I2C IO Expander MCP23017
function write_command(addr,data1, data2)
	fa.spi("cs",0)
	fa.spi("write",addr)
	fa.spi("write",data1)
	fa.spi("write",data2)
	fa.spi("cs",1)
end

fa.spi("init", 1) --MCP23S17で動作確認済み
fa.spi("mode", 0) --MCP23S17で動作確認済み
sleep(500) --ちょっと待つ。待たないと次のGPIOAのOutput指定が失敗しているような感じ。検証が必要。
write_command(0x40, 0x00, 0x00) --GPIOAをOutputに指定
write_command(0x40, 0x01, 0x00) --GPIOBをOutputに指定
while(1) do
	write_command(0x40, 0x12, 0xFF) --GPIOAをすべてHIGHに指定
	sleep(1000)
	write_command(0x40, 0x12, 0x00) --GPIOAをすべてLOWに指定
	sleep(1000)
	write_command(0x40, 0x13, 0xFF) --GPIOBをすべてHIGHに指定
	sleep(1000)
	write_command(0x40, 0x13, 0x00) --GPIOBをすべてLOWに指定
	sleep(1000)
end
```

#まとめ
　以上で、FlashAirからソフトウェアSPI（fa.spi関数）を使ってSPIデバイスであるMCP23S17のGPIOピンのHIGH/LOWを制御することができました。理論的にはI2C接続であるMCP23017よりも速く制御ができるはずです。
　これで、FlashAirに一気に16本のGPIOを増設することができて、応用の幅が大きく広がりますね。

#参考資料
　[MCP23S17データシート](http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf)
　[FlashAir Developers Lua関数リファレンス](https://flashair-developers.com/ja/documents/api/lua/reference/)