FlashAirでD/AコンバータMCP4922を制御してみた

あけましておめでとうございます。今年もよろしくお願いします。
新年早々の電子工作初めは、FlashAirでD/Aコンバータを制御してみました。

#FlashAir W-03のLuaスクリプト実行環境
　FlashAir W-03シリーズでは、SDカード上でLuaスクリプトを実行できます。Luaスクリプトでは、FlashAirのGPIO機能を使って、ソフトウェアSPIによりSPIデバイスを制御することができます。
　これまで、[IOエキスパンダMCP23017](http://qiita.com/ayasehiro/items/cd81cfd8c0635407ffef)や[IOエキスパンダMCP23S17](http://qiita.com/ayasehiro/items/778d15bb4ee1c2a218c8)を制御してみましたが、今回は、FlashAirでD/AコンバータMCP4922を制御してみます。

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

- FlashAir W-03 V3.00.01アップデート済みのもの
- MCP4922 （[秋月電子通商](http://akizukidenshi.com/catalog/g/gI-02090/)）
- SDカードスロット（[カードソケットSD-N0940](http://www.aitendo.com/product/1194)をDIP化）
- 3.3V定電圧レギュレータ（[秋月電子通商](http://akizukidenshi.com/catalog/g/gI-00538/)）
- ブレッドボード
- 動作確認用のLEDと抵抗
- ACアダプタ（5V）:手持ちのものを利用

![IMG_6653s.jpg](https://qiita-image-store.s3.amazonaws.com/0/89137/cd6a1e47-304b-93fc-84c4-eb15d8cef88c.jpeg)

###SDカードスロット
　SDカードスロットはなんでも構いませんが、今回はSDカードの1番、2番、7番、8番ピンを引き出せる必要があります。

###FlashAirとMCP4922の接続
　FlashAirとMCP4922の接続は、以下の表に示す通りに接続します。

![FlashAir_MCP4922_pinasign copy.png](https://qiita-image-store.s3.amazonaws.com/0/89137/44b7a24b-23f2-504d-eb85-cfd128de30ef.png)


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

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

#Luaスクリプトファイル
　FlashAirのルートフォルダに以下のコードを記述したテキストファイル（mcp4922sample.lua）をコピーします。
　このコードでは、MCP4922のVOUTAとVOUTBの出力を徐々に上げていくようにしています。接続されたLEDは、交互に徐々に明るくなります。

　今回試したMCP4922はSPI接続対応ではありますが、単純に接続するだけではなく、制御するためにはLDACピンのHIGH/LOWを制御する必要があります。SPIで16ビットのデータを送信した後、LDACピンをLOWにすることで、VREFAまたはVREFBにかかっている電圧に基づき書き込んだ値（0〜4096）に応じてVOUTAまたはVOUTBの出力値が変化します。

　MCP4922に送信する16ビットのデータは以下のようになっています。
　15ビット：VOUTA/VOUTBの選択（0:VOUTA、1:VOUTB）
　14ビット：VREF入力のバッファ制御有無（0:なし、1:あり）
　13ビット：出力ゲインの選択（0:VREFA/Bの2倍、1:VREFA/Bの1倍）
　12ビット：シャットダウン制御有無（0:アナログ出力あり、1:アナログ出力なし）
　11〜0ビット：出力値の指定（4096段階：0x000[0]〜0xFFF[4095]）

　また、本当はFlashAirのSPI用のLuaスクリプト関数であるfa.spi関数を使って制御したかったのですが、うまくいかず、とりあえず今回はfa.pio関数を使って制御しています。fa.pio関数はそのままでは使いづらいので、@Seg_Faulさんが公開しているライブラリ[FlashAirのPIOをArduino風に扱う](https://sites.google.com/site/gpsnmeajp/electricmemo/flashairnopiowoarduino-fengni-xiu)を利用しています。pioduino.luaをダウンロードして、mcp4922sample.luaと同じフォルダに配置してください。


```mcp4922sample.lua
-- FlashAirでD/AコンバータMCP4922を制御する
require("pioduino")

MCP4922_OUTA = 0
MCP4922_OUTB = 1
DA_SDI  = 0  --0x01 SD-pin 2
DA_SCK  = 1  --0x02 SD-pin 7
DA_CS   = 2  --0x04 SD-pin 8
--DA_SDO  = 3  --0x08 SD-pin 9 --未使用
DA_LDAC = 4  --0x10 SD-pin 1

function MCP4922DataSend(value)
  digitalWrite(DA_SDI, value)
  digitalWrite(DA_SCK, HIGH)
  digitalWrite(DA_SCK, LOW)
end

function MCP4922CommandSend(outab, value)
  --コマンドデータの出力
  digitalWrite(DA_LDAC,HIGH) --LDACピンをHIGHに
  digitalWrite(DA_CS,LOW)    --CSピンをLOWに
  --出力ピン(VOUTA/VOUTB)を指定
  if (outab == 0) then
    MCP4922DataSend(LOW)  --VOUTA
  else
    MCP4922DataSend(HIGH) --VOUTB
  end
  
  MCP4922DataSend(LOW)  --VREFバッファ制御なし
  MCP4922DataSend(HIGH) --出力ゲインは1倍
  MCP4922DataSend(HIGH) --アナログ出力あり
  --12ビット分のデータを出力
  for i=11, 0, -1 do
    if (bit32.band(bit32.rshift(value, i), 0x01) == 1) then
      MCP4922DataSend(HIGH)
    else
      MCP4922DataSend(LOW)
    end
  end
  digitalWrite(DA_CS,HIGH)  --CSピンをHIGHに
  digitalWrite(DA_LDAC,LOW) --LDACピンをLOWに
end

pinMode(DA_SCK, OUTPUT)
pinMode(DA_SDI, OUTPUT)
pinMode(DA_CS,  OUTPUT)
pinMode(DA_LDAC,OUTPUT)
digitalWrite(DA_SCK,LOW)
delay(1000) --ここでちょっと待たないと上手く動かない。
while(1) do
  MCP4922CommandSend(MCP4922_OUTB, 0)
  for cnt = 0, 4000, 100 do
    MCP4922CommandSend(MCP4922_OUTA, cnt)
    delay(100)
  end
  MCP4922CommandSend(MCP4922_OUTA, 0)
  for cnt = 0, 4000, 100 do
    MCP4922CommandSend(MCP4922_OUTB, cnt)
    delay(100)
  end
  collectgarbage("collect") --定期的にお掃除
end
```

#まとめ
　以上で、FlashAirからfa.pio関数を使ってD/AコンバータMCP4922を制御することができました。
　これで、FlashAirにアナログ出力を増設することができました。さらに応用の幅が大きく広がりますね。

#参考資料
　[DAコンバータ　MCP4922(SPI)を利用しD/A変換を行う](http://www.geocities.jp/zattouka/GarageHouse/micon/circuit/D_A.htm)
　[MCP4922データシート](http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf)
　[FlashAirのPIOをArduino風に扱う](https://sites.google.com/site/gpsnmeajp/electricmemo/flashairnopiowoarduino-fengni-xiu)
　[FlashAir Developers Lua関数リファレンス](https://flashair-developers.com/ja/documents/api/lua/reference/)