-Arduino Nano1から続く-
2 Arduino Nano I2Cセンサー読み取り、表示編
AHT25は温湿度センサーです。格安で秋月で売っています。
アドレスは0x38です。
まずはAHT25のinit設定関数から、
void init_aht25(void){
delay(100);
Wire.beginTransmission(AHT25_ADDRESS);
Wire.write(0x71);
Wire.endTransmission();
delay(10);
}
これはAHT25の初期関数です。AHT25に0x71を書き込むだけです。setup(){...}の中に書き込みます。
次にAHT25の読み取り関数です。インターネットのあちこちからかき集めて試行錯誤して作ったものです。
unsigned char dig0;
uint32_t dig1;
uint32_t dig2;
uint32_t dig3;
uint32_t dig33;
uint32_t dig4;
uint32_t dig5;
unsigned char dig6;
void readData(void){
int i = 0;
long int x;
byte digraw[6];
char tempera[15];
char humidi[15];
char data_t[] = "Temp:";
char data_h[] = "Humi:";
char data2;
char data3 = "dC";
char par = "%";
uint32_t hum_low, temp_low;
double T;
double H;
char t_data[5];
char h_data[5];
Wire.beginTransmission(AHT25_ADDRESS); // AHT25と交信
始めます。
Wire.write(0xAC);
Wire.write(0x33);
Wire.write(0x00);
Wire.endTransmission();
do {
delay(80);
Wire.requestFrom(AHT25_ADDRESS, 7); // 8個データを受けます。
if (Wire.available() >= 7){
for(i = 0; i < 7; i++){digraw[i] = Wire.read();}
}
} while((digraw[0] & 0x80) != 0);
hum_low = ((uint32_t)digraw[1] << 12) | ((uint32_t)digraw[2] << 4) |
(((uint32_t)digraw[3] >> 4) & 0x0F); // 湿度データーを統合します。
temp_low = (((uint32_t)digraw[3] & 0x0F) << 16) | ((uint32_t)digraw[4] << 8)
| (uint32_t)digraw[5]; // 温度データーを統合します。
T = ((temp_low / 1048576.0) * 200) - 50;
H = (hum_low / 1048576.0) * 100;
dtostrf(T,3,1,t_data); // 温度の小数点以下も含め文字化
dtostrf(H,3,1,h_data); // 湿度の小数点以下も含め文字化
sprintf(tempera, "T:%sdC H:%s%s ", t_data, h_data, "%");
// LCDの一行目にT,Hデータtemperaを書き込む
writeCommand(0x02);
for (i = 0; i < sizeof(tempera); i++) {writeData(tempera[i]); }
}
センサーが2つ入っているので結構めんどくさいです。一発で関数に纏めるには、時間が掛かりました。
バグってはまったところが幾つかありました。
hum_lowとtemp_lowはI2Cで読み取った8ビット束を組み合わせて1つの整数値にするとこですが、かってにいろいろいじって見ましたがうまく行きません。マニュアル通りが一番です。
Tの計算中1048576.0を1048576で計算するとバグり良い数値が出てきません。
同様にHの計算も1048576.0を1048576で計算するとバグり良い数値が出てきません。
長いこと悩みました。
もう一つprintf()で引っかかりました。今までのコンパイラでは、sprintf()一つでLCD書式まで一発で書き込めたのですが、nanoのコンパイラにはなく、もう一行dtostrf()が必要でした。たった一行ですが知っていないと長いことはまります。
ちなみに後で書きますが、raspberry pi picoのコンパイラではprintf()だけで表示出来ました。
ついでにもう一つセンサー読み取りをやります。ADT7410は温度のみのセンサーなのであまり難しくありませんが、I2Cから読み取った数値の再構築、定数計算はついて回ります。
void readData74(void){
int i;
byte digraw0;
byte digraw1;
uint16_t Temp74;
int iTemp74;
float fTemp74;
char t_T74[5];
char tempera2[15];
Wire.requestFrom(ADT7410_ADDRESS, 2); // 2回読み込む
digraw0 = Wire.read();
digraw1 = Wire.read();
Temp74 = ((uint16_t)digraw0 << 8) | (uint16_t)digraw1;
Temp74 = Temp74 >> 3; // これで復元
if(Temp74 & 0x1000){iTemp74 = Temp74 - 0x2000;}
else{iTemp74 = Temp74;}
fTemp74 = (float)iTemp74 / 16.0; // ここまでが必要な手続き。
dtostrf(fTemp74,3,2,t_T74); // 小数点以下の数値も文字にします。
sprintf(tempera2, "T74-T: %sdC ", t_T74); // 表示用に文字を整えます。
for (i = 0; i < sizeof(tempera2); i++) { // LCDの2段目に書き込みます。
writeCommand(0x80+0x40+i);
writeData(tempera2[i]);
}
これはそのまんまでちゃんと動きました。2つのセンサーは数値は一致しませんがだいたいこんなとこかという数値を示しています。