ESP8266(ESP-WROOM-02)でアナログ値を見るには？


# ESP8266でアナログ値を調べたいのだが、癖があるのでいろいろ試してみた。

ESP8266にもADCがデフォルトで付いている。TOUT端子を使用してデータが取得できる。ただし、測定電圧は0V-1Vである点に注意が必要である。抵抗で分圧する等で測定する電圧に注意が必要となる。

TOUTを使用しない場合には外部のA/Dコンバータ(以下ADC) ICを接続してデータを取得することとなる。今回はi2c接続とspi接続のものをそれぞれ試してみた。試したデバイスは以下の3種類で、いずれも秋月電子で購入できる。

 - MCP3002 (spi)
 - MCP3008 (spi)
 - MCP3425 (i2c)

# TOUTを使用してアナログデータを取得する

普通にTOUTに調べたい回路を接続することで、データが取得できる。取得できる値は10bitの精度(0-1023)で、測定電圧の範囲は0.0v - 1.0v。ESP8266の電源電圧3.3vと異なるため、必要に応じて抵抗を使用して分圧する必要がある点に注意が必要。

 ```cpp
analogRead(A0);
```

# MCP3002を使用してアナログデータを取得する

外付けのADCとして、秋月で簡単に入手できるMCP3002/3004/3008を紹介する。これらは精度は10bit(0-1023)、SPI接続と基本的な部分は一緒であるが、MCP3002とMCP3004/3008はSPIのプロトコルが異なるため、ここではまず、MCP3002を紹介し、あとでMCP3004/3008を紹介する。

MCP3002/3004/3008の違いは接続プロトコルがSPIで一緒ではあるが、持っているADCのチャネル数が異なる。MCP3002が2チャンネル、MCP3004が4チャンネル、MCP3008が8チャンネルである。また、先にも書いたが接続プロトコルが異なるため、MCP3002↔MCP3004/3008を交換した場合、回路を変えただけでは動かずプログラムも修正が必要な点は注意したい。

MCP3002とESP8266はSPIで接続する。本プログラムではCSはio15としたが、この場合にはプログラム起動処理のためにio15をpulldown(io15-抵抗(10kΩ)-GND)しておく必要がある。pulldown回路がない場合には、プログラムが動作しない点注意が必要である。pinに余裕があればCSについてはio15以外に設定し、pulldownのないpinを指定することも可能である(※注 その場合にはサンプルコードのマクロ 【CS】の15の値を変える必要がある)。


## ESP8266とMCP3002の接続ピンの関係
|ESP8266|MCP3002|description|
|:---------|:---------|:------------|
| io14|clk(7) |SCK|
| io12|dout(6) |MISO|
| io13|din(5) |MOSI|
| io15|cs(1) |CS|

## サンプルコード

```cpp
  #define CS 15

  void loop(){
      SPI.begin();

      digitalWrite(CS, LOW);
      byte highbyte = SPI.transfer(0b01101000);
//      byte highbyte = SPI.transfer(0b01111000); ch1から読み込む場合はこちらのコード
      byte lowbyte = SPI.transfer(0x00);
      digitalWrite(CS, HIGH);
      
      SPI.end();
      unsigned int data = ((highbyte << 8) + lowbyte) & 0x03FF';
  }
```

## MCP3002の仕様書

[MCP3002の仕様書](http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf)


# MCP3004/MCP3008を使用してアナログデータを取得する

MCP3004/3008を使用した接続およびプログラムを示す。
ここでもESP8266のCSはio15を指定しているが他のPINに変更も可能である。

## ESP8266とMCP3004/MCP3008の接続ピンの関係

|ESP8266|MCP3004|MCP3008|description|
|:---------|:---------|:---------|:------------|
| io14|clk(11) |clk(13) |SCK|
| io12|dout(10) |dout(12) |MISO|
| io13|din(9) |din(11) |MOSI|
| io15|cs(8) |cs(10) |CS|


## サンプルソース

コードはMCP3004/MCP3008も同じ。

```cpp
  #define CS 15

   /**
   * @param ch 0-7 読み込むチャネル
   **/
   void readAdc( byte ch){
      SPI.begin();

      digitalWrite(CS, LOW);
      SPI.transfer(0x01); // send startbit
      byte highbyte = SPI.transfer(((8+ch)<<4));
      byte lowbyte = SPI.transfer(0x00);
      digitalWrite(CS, HIGH);
      
      SPI.end();
      unsigned int data = ((highbyte << 8) + lowbyte) & 0x03FF';
   }
```
## MCP3004/3008の仕様書

[MCP3004/3008の仕様書](http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf)

# MCP3425を使用してアナログデータを取得する

MCP3425は、i2cで接続してADCデータを取得できるデバイスであり、MCP3002/3004/3008より簡単にESP8266に接続できるが、ADCチャネルは1チャネルしかない点注意が必要である。精度はMCP300Xより高い16bitと高い。

i2cで接続するi2cチャネルは秋月のMCP3425を使用する場合0x68になる。

SCL/SDAは本来pullupすべきであるが、秋月から入手したMCP3425ではサボっても問題なかったので今のところあえてpullupはしてません...(各自、自己責任で...)

## ESP8266とMCP3425の接続ピンの関係

|ESP8266|MCP3425|description|
|:---------|:---------|:------------|
| io5|clk(3) |SCL|
| io4|sda(4) |SDA|


## サンプルコード

[MCP342Xライブラリ](https://github.com/uChip/MCP342X) を使用したサンプルを示す。

```cpp
MCP342X adc = MCP342X(address);
void setup(){
  adc.configure( MCP342X_MODE_CONTINUOUS |
                   MCP342X_CHANNEL_1 |
                   MCP342X_SIZE_16BIT |
                   MCP342X_GAIN_1X
                 );
}

void loop(){
      int16_t val;
      adc.startConversion();
      adc.getResult(&val);
}

```
## MCP3425の仕様書

[MCP3425の仕様書](http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf)