概要
Arduino UNO R3のI2C通信機能を使って、カラーセンサモジュール(S11059-02DT/浜松フォトニクス)
から情報を取得するためのコードを書いた。センサモジュールとArduinoの間に電圧変換のモジュールが必要だったものの、I2C通信は問題なくできた。しかし、カラーフィルターの機能確認としてはイマイチ。色味よりも輝度で値が大きく変わってしまったため、機能確認は別の機会に譲りたい。
背景
-
ArduinoのI2C通信でデバイスのレジスタにアクセスする。
で記載した方法が実用に耐えうるかどうか確認したかった。 - 手元に1つぐらいは、まともに動かせるセンサーが欲しかった。
想定読者
- 身近にあるマイコンを使ってI2Cデバイスをお手軽に制御したい人。(後に、あんまりお手軽な方法ではないことがわかる。)
目的
- Arduinoを使ってセンサにI2C通信をすること。
実験環境
参考情報
ソースコード
コードはArduinoのI2C通信でデバイスのレジスタにアクセスする。で記載した内容を基本に、本アプリケーションに合わせて実装している。I2C通信として使い回す部分以外、つまりアプリケーション毎に異なる実装になる部分は、アプリケーション層として定義すべきだと思うが、そこまで賢い実装にはなっていない。でも、1つのセンサーに書き込む/読み込むだけであれば、この程度の実装で十分。
# include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
}
int i=0; //initiarize
int w=119;
int r=114;
int DeviceAddress = 0x2A; // 0b0101010 42
int Address[100]={
0x00, // Control
0x00, // Control
//0x01, //
//0x02, //
0x03, // Red MSB
0x04, // Red LSB
0x05, // Green MSB
0x06, // Green LSB
0x07, // Blue MSB
0x08, // Blue LSB
0x09,
0x0A
};
int Value[100]={
0x8F, // ADC reset, awake
0x0B, // Control initialize 0B:correct
//0x0C,
//0x30,
0x00, // Red MSB initialize
0x00, // Red LSB initialize
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
void loop() {
delay(100);
Serial.println("Please send command either w or r");
delay(1000);
Serial.print("Serial.available()=");
Serial.println(Serial.available());
if(Serial.available()>0){
Serial.println("Serial avalable!");
int x=0;
x = Serial.read();
Serial.print("x=");
Serial.println(x,HEX);
if(x==w){
Serial.println("Write");
WriteReg();
}
if(x==r){
Serial.println("Read");
ReadReg();
}
}
}
void WriteReg(){
for (i=0; i<10; i++) {
Wire.beginTransmission(DeviceAddress);
Wire.write(Address[i]);
Wire.write(Value[i]);
Wire.endTransmission(false);
Insert0x0(Address[i]);
Serial.print(Address[i],HEX);
Serial.print("=");
Insert0x0(Value[i]);
Serial.println(Value[i],HEX);
delay(0);
} // while(1){}//finalize
}
void ReadReg(){
for (i=0; i<10; i++) {
Wire.beginTransmission(DeviceAddress);
Wire.write(Address[i]);
Wire.endTransmission(false);
Wire.requestFrom(DeviceAddress, 1,true);
Value[i] = Wire.read();
Insert0x0(Address[i]);
Serial.print(Address[i],HEX);
Serial.print("=");
Insert0x0(Value[i]);
Serial.println(Value[i],HEX);
delay(0);
} // while(1){}//finalize
}
void Insert0x0(int num){
Serial.print("0x");
if (num<16){ Serial.print("0"); }
else Serial.print("");
}
結果1:I2C通信できた
Writeでカラーセンサーの各アドレスにデータを格納
(0x00には0x0Bを格納、0x03~0x0Aは初期化で0x00を格納)し、
Readで値を確認
(0x00を呼び出すと0x0Bが格納されていて、0x03~0x0Aにはセンサから読み込んだ値が格納されている。)
Write
0x00=0x0B
0x03=0x00
0x04=0x00
0x05=0x00
0x06=0x00
0x07=0x00
0x08=0x00
0x09=0x00
0x0A=0x00
Read
0x00=0x0B
0x03=0x0D
0x04=0x5F
0x05=0x03
0x06=0x64
0x07=0x01
0x08=0xC3
0x09=0x01
0x0A=0xD0
結果2
// 何もかざしていない時
0x03=0x11
0x04=0xB4
// 赤い下敷きをかざしたとき
0x03=0x0D
0x04=0xE7
// iPhoneのLEDで光を当てたとき
0x03=0x58
0x04=0x14
// 赤い下敷きをかざしてiPhoneのLEDで光を当てたとき
0x03=0x27
0x04=0x54
赤い下敷きをかざす方が暗くなるから、結果の値が小さくなる。。。
この程度の実験では、カラーセンサの機能が十分に果たせているかわからないため、同じ輝度で、緑、青の値も比較して見る必要がありそうだ。
考察1:ADCの初期化
ADCの初期化は自分の理解通りに動いていない。アドレス:0x00にデータ:0x0Bを書き込んで初期化しているのだが、データシートの指示通りであれば、0x0Fを書き込んでも正しく動作するはずと理解している。根本原因は不明。本検討では、センサーにI2Cアクセスすることを目的にしているので、初期化の細かい検討は不問に止めるが、今後の検討で理由を明らかにしていきたいと思っている。これでは全く考察になっていないのだが、考察できるほどの材料が揃っていないのが実際のところ。考察を揃えるためには、まず、カラーセンサーの動作検証環境を整備する必要があると考えている。今の所、カラー光源にまともなものがないため、I2通信していること以外は、センサーがどのように動いているか詳細な動きが理解できていない。まずは、環境を整えたい。しかし、初期化の検討をしているので、カラー光源なんぞなんでも関係ない、というツッコミもまた一理あり。
結論
- カラーセンサにI2C通信できた。
- 正確なカラー値が取得可否の確認ができなかった。
所感
- 実験していると、往々にして本来の目的外の部分でハマる。本来の目的に立ち戻って、まずは目的達成しているかどうか確認して、一歩一歩進める方が吉。
- 問題にぶつかったら、散歩するなり、時間を置くなりして問題と距離を置くことが有効。散歩すると足の血流が良くなり、脳の働きにも好影響を及ぼすらしい。
- 世の中の人々は、どうやってI2Cデバイスを動かしているのだろうか。もちろん、やり方は色々あるのは知っているのだが、Aruduino使ってセンサにアクセスする方法の説明はあまりない。SoCレベルであればベンダーからのサポート資料などありそうだが、エンジニアの手元で起きることに対するソリューションとして、こういった検討を続けていきたい。
*この記事は若手もくもく会@クラウドワークスへ、台湾からのリモート参加中に実験した内容をもとに執筆しました(^^)