UIAPduinoでI2C


AHT10という温度と湿度を読み取れるセンサーを,UIAPduinoを使ってI2Cから読み取って,Serialに出力させるプログラムを作ってみた. センサーの使い方を調べていたら,ArduinoにAdafruitのライブラリがあって,データシートを読むよりも,これを参考にやってみることにした.

まずは,UIAPduinoの環境でAdafruit_AHT10を使ってやってみようとしたら,プログラムはコピペですぐに書けたが,プログラムのサイズがflashに入らないとエラーが出た. 噂には聞いていたが,WCHのArduinoはかなり大きくなってしまう. それではと,Adafruitのライブラリを外して,SerialとWireを初期化して,コンパイルしたら,もうサイズがギリギリになっている. センサーに初期化コマンドを送るところまで書いたら,サイズオーバーである.

仕方が無いので,ch32funを使うのはややこしいので,AlexanderManderaさんの環境を使うことにした. I2Cの使い方は,標準的なArduinoとは違うのだが, ~/.arduino15/packages/alexandermandera/hardware/wch/0.0.2/cores/arduino/hal にI2Cのサブルーチンがあり, ~/.arduino15/packages/alexandermandera/hardware/wch/0.0.2/examples/CH32V003-I2C-1 にある例を参考にしたら,それほど苦労せずにプログラムすることができる. それより,AHT10のライブラリを読み解いて,移植する方が面倒かな. 湿度と温度を読み取ってシリアルに出力すプログラムを書いて,コンパイルしたら12kバイトぐらいである. 思ったよりも大きくなったが,十分なサイズである.

そのプログラムが以下のものである. calibrationはうまくいかなかったので,その終了判定はコメントアウトしている.

#include "hal/wch-hal-i2c.h"

#define AHT10_I2CADDR_DEFAULT 0x38   ///< AHT10 default i2c address
#define AHT10_CMD_CALIBRATE 0xE1     ///< Calibration command
#define AHT10_CMD_TRIGGER 0xAC       ///< Trigger reading command
#define AHT10_CMD_SOFTRESET 0xBA     ///< Soft reset command
#define AHT10_STATUS_BUSY 0x80       ///< Status bit for busy
#define AHT10_STATUS_CALIBRATED 0x08 ///< Status bit for calibrated

#define LED_BUILTIN 2

uint8_t data[10] = {0};

void setup()
{
  delay(20);
  Serial.begin(115200);
  delay(20);
  Serial.print("starting"); delay(20);
  i2c_init(80000, I2C_DutyCycle_16_9, 0x02, I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
  delay(50);
  i2c_write_bit(AHT10_I2CADDR_DEFAULT, AHT10_CMD_SOFTRESET);
  delay(20);
  data[0]=AHT10_CMD_CALIBRATE;
  data[1]=0x08;
  data[2]=0x00;
  i2c_write(AHT10_I2CADDR_DEFAULT, data ,3);
  delay(20);
  while ( i2c_read_bit(AHT10_I2CADDR_DEFAULT) & AHT10_STATUS_BUSY ) delay(10);
  //while ( i2c_read_bit(AHT10_I2CADDR_DEFAULT) & AHT10_STATUS_CALIBRATED ) delay(10);

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  data[0]=AHT10_CMD_TRIGGER;
  data[1]=0x33;
  data[2]=0x00;
  i2c_write(AHT10_I2CADDR_DEFAULT, data ,3);
  while ( i2c_read_bit(AHT10_I2CADDR_DEFAULT) & AHT10_STATUS_BUSY ) delay(10);
  i2c_read(AHT10_I2CADDR_DEFAULT, data ,6);
  uint32_t h = data[1];
  h <<= 8;
  h |= data[2];
  h <<= 4;
  h |= data[3] >> 4;
  float humidity = ((float)h * 100) / 0x100000;
  uint32_t tdata = data[3] & 0x0F;
  tdata <<= 8;
  tdata |= data[4];
  tdata <<= 8;
  tdata |= data[5];
  float temperature = ((float)tdata * 200 / 0x100000) - 50;
  digitalWrite(LED_BUILTIN, LOW);

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.println(" %");

  delay(1000);
}

AlexanderManderaさんの環境の有用性を感じたのだが,実装されていない機能がそれなりにあり,開発がしばらく止っているこの環境をメインに使うのは,不安である. 次世代のUIAPduinoでは,flashの大きなCH32V006を使う計画のようで,それを使えばWCHのArduinoでも,サイズの問題は気にしないで良いかも知れない. AlexanderManderaさんの環境を改良していくというのも方法であるが,古いch32funを新しくして,ADCやPWMなどのコードを書いてとなると,敷居が高い. Arduinoのhardwareの作り方も良く知らないし. でも,この環境でUSBが使えるようになれば,魅力的ではある.