I2C通信温湿度センサーモジュールAM2320をESPr Developerで使う

#能書き
秋月電子で衝動買いしたAM2320ですが、ネットに転がってるコードがどうも微妙なので自前でドライバ?ライブラリ?を書きました。

#環境
- ESPr Developer
 - https://www.switch-science.com/catalog/2500/
- AM2320
 - http://akizukidenshi.com/catalog/g/gM-08663/

#使い方
ESPr Developerとセンサーを繋ぎます。プルアップ抵抗等は不要です。
AM2320のピン配置はデータシート参照。
ESPr側はSDAが4、SCLが5だった気がする。不安なら指定しておきましょう。

GitHubに上げておきました。
https://github.com/ihatomorio/AM2320

#コード解説
1. `CWireAM2320 sensor`でオブジェクト生成。
2. `sensor.init()`で`Wire.begin`をします。
 - `sensor.init(4, 5)`と書くと`Wire.begin(4, 5)`となりI2C通信におけるSDAピンとSCLピンを指定できます。
3. `sensor.fetch()`でセンサーから温度と湿度を拾います。拾った温度と湿度はメンバ変数`sensor.humid`、`sensor.temp`に格納されています。

#サンプルコード
以下の3つのコードを同じフォルダ`AM2320test`に入れるとArduino IDEで動くと思います。

```c++:AM2320test.ino
#include "WireAM2320.h"

CWireAM2320 sensor;

void setup() {
  Serial.begin(115200); //for debug

  sensor.init();
}

void loop() {
  sensor.fetch();
  
  Serial.print("  Humidity=");
  Serial.print(sensor.humid, 1);
  Serial.print("   ");
  Serial.print("  Temperature=");
  Serial.println(sensor.temp, 1);

  delay(5000);
}
```

```c++:WireAM2320.h
#ifndef WIREAM2320_H
#define WIREAM2320_H

#include <Arduino.h>

enum AM2320_Register  : word {
  HUMI_MSB = 0x00,
  HUMI_LSB = 0x01,
  TEMP_MSB = 0x02,
  TEMP_LSB = 0x03,
  MODEL_MSB = 0x08,
  MODEL_LSB = 0x09,
  VER_NUM = 0x0A,
  STATUS_AM2320 = 0x0F,
  USER_REG_MSB = 0x10,
  USER_REG_LSB = 0x11,
  USER_REG2_MSB = 0x12,
  USER_REG2_LSB = 0x13
};

enum AM2320_Function : word {
  READ = 0x03, //Read multiple registers
  WRITE = 0x10 //Write multiple registers
};

class CWireAM2320
{
  public:
    CWireAM2320();
    
    void init();
    void init(int pinSDA, int pinSCL);

    int fetch(); //refresh sensor value

    float humid; //Humidity
    float temp; //Temperature

  private:
    word addr = 0x5c;
    static const int AM2320_ADDR = 0x5C;
    unsigned long lastFetchTime = 0;
};

#endif
```

```c++:WireAM2320.cpp
#include "WireAM2320.h"

#include <Arduino.h>
#include <Wire.h>

CWireAM2320::CWireAM2320() {
  humid = 0.0;
  temp = 0.0;
}

void CWireAM2320::init() {
  Wire.begin();
}

void CWireAM2320::init(int pinSDA, int pinSCL) {
  Wire.begin(pinSDA, pinSCL);
}

int CWireAM2320::fetch() {
  //minimal interval 2s 
  unsigned long elapsed = millis() - lastFetchTime;
  if (elapsed < 2000) delay(2000 - elapsed); //wait for 2s max
  lastFetchTime = millis(); //get last fetch time

  //Wake Sensor
  Wire.beginTransmission(AM2320_ADDR); //START + addr (+ wait 800us-3ms (auto?))
  Wire.endTransmission(); //STOP

  //Send the read command or send written instructions
  Wire.beginTransmission(AM2320_ADDR);//START + addr + W
  Wire.write(READ); //function code
  Wire.write(HUMI_MSB); //start address
  Wire.write(4); //number of registers
  int nEnd = Wire.endTransmission(); //STOP

  if (nEnd != 0) {
    return -1;
  }

  //To return the data read or confirmation signal
  delayMicroseconds(1500); //delay at least 1.5ms
  int ans = Wire.requestFrom(AM2320_ADDR, 6); //START + addr + R
  delayMicroseconds(30);

  if ( ans != 6) {
    return -1;
  }

  int H1, H2, T1, T2 = 0;
  for (int i = 1; i <  ans + 1; i++) {
    int c = Wire.read();
    switch (i) {
      case 3:
        H1 = c;
        break;
      case 4:
        H2 = c;
        break;
      case 5:
        T1 = c;
        break;
      case 6:
        T2 = c;
        break;
      default:
        break;
    }
  }
  humid = (H1 * 256 + H2) / 10.0;
  temp = (T1 * 256 + T2) / 10.0;

  return 0;
}
```