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が使えるようになれば,魅力的ではある.