micro:bitでカラーセンサーを使ってみる

![IMG_8692.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/acc0669d-7802-9ae6-b7db-ff538d095aca.jpeg)
光センサーには可視光用・赤外線用など種類があり、電子工作でよく使う光センサー（フォトトランジスタ、CDS)は可視光の強弱を取得できるものです。また赤外線センサーは測距や人感センサー、テレビなどのリモコンにも使われています。
可視光のRGB別に強弱を取得して、色の識別ができるようにしたのがカラーセンサーで生産工程の品質管理や、液晶モニターの自動カラーバランスなどの用途に使われています。

カラーセンサーは色を識別できますので、読み取った色の違いを利用してコンピュータに命令をすることができます。例えば、ロボットに赤い色を見たら止まれ、緑を見たら進めと命令したり、色によって物品を分類することもできます。
教材としても面白いのですが、micro:bit用に特化した製品は無いようなので作ってみることにしました。
# 浜松ホトニクスのS11059-02DTを使う
### カラーセンサーの種類
カラーセンサーはGrove、M5Stackなどのモジュール化されたものからチップ単体まで各種の製品があります。
今回はmicro:Maqueenの裏面に取り付けて、色で動作を制御したいという目的があるため、極力小さくするためにチップ単体品を使用しました。
チップ単体品にはアナログセンサとI2C接続のデジタルセンサがあります。アナログセンサはRGBそれぞれの光量を電圧で出力するだけなので、RGBごとに電圧の増幅、AD変換をする部分を作る必要があります。
一方のデジタルセンサは、ワンチップにAD変換までの処理を内蔵しているので、RGBの明るさを数値で出力してくれます。

デジタルセンサも沢山製品がありますが、入手のしやすさと国産で日本語資料があるところから[浜松ホトニクスのS11059-02DT](https://www.hamamatsu.com/content/dam/hamamatsu-photonics/sites/documents/99_SALES_LIBRARY/ssd/s13683-03dt_-04ds_kpic1106j.pdf)を使うことにしました。単体ではチップのフットプリントが独特の寸法のため、[秋月電子通商で販売されている4ピンSIPモジュール](https://akizukidenshi.com/catalog/g/g108316/)が便利です。ピンヘッダやジャンパーケーブルをハンダ付けすれば、ブレッドボードやロボットカーに取り付けて使えます。

### I2Cの使い方
micro:bitのI2C接続は、若干コツがありますが基本は他のマイコンボードと同じで、
・アドレスの指定
・コントロールレジスタへのコマンドの送信
・データ用レジスタからのデータの取得
の繰り返しになります。

S11059-02DTのデータシートによるとレジスタは以下のような構成です。
![s13683-registers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/aa77442e-0499-5c49-a98f-d6a46c0792f6.png)
８ビットのコントロールレジスタは、ビットごとに機能を選択し、８ビット全体を数値とみなして送信します。
RGBの明るさを示すセンサのデータは、16ビットのデータを上位バイト、下位バイトの8ビットずつ取得し、結合して16ビット整数にして使います。

面倒くさそうですが、データシートにはサンプルの設定が載っているので、とりあえずこの通りに設定すれば使うことができます。
![s13683-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/d42b87e7-4956-efbe-893e-627b18cb3390.png)
上のサンプルに従うと、実際のプログラムの流れは、
#### 最初に初期設定をします。
I2Cのアドレス0x2Aを指定、続けてコントロールレジスタのアドレス0x00を指定します。
次のコマンド0x89を与えます。これはレジスタマップによると、リセット・スリープ解除・Highゲイン指定・積分時間1.4msにする設定です。
続けて再度、アドレス0x2Aのコントロールレジスタ0x00に対して、0x09のコマンドを与えます。これは直前のコマンドと同じ条件で、リセットを解除して動作をスタートさせるコマンドです。

#### 動作が始まると、
積分時間のサイクルでデータ用のレジスタにRGBと赤外のデータが入ってきますので、これを取得する処理になります。
アドレス0x2Aの0x03はRデータの上位バイトのレジスタですが、ここを指定して連続的に読み出すと、RGBと赤外のデータが、それぞれ上位バイト、下位バイトの順で自動的に読み出されます。

### micro:bitで使う例
上記の手順をMakecodeにした例です。
![s13683-makecode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/1ebc8980-5cae-d2db-1210-04ef4e6f7066.png)
#### 「最初だけ」ブロックが初期設定の部分です。
2つのI2Cの送信ブロックを使っていますが、最初のブロックは前述のリセットを行い、2つ目のブロックが動作スタートのコマンドになります。
どちらもI2Cアドレス42（0x2A）を設定します。
1つ目のブロックでは、送信する数値は、レジスタアドレスとコマンドの0x00,0x8B（積分時間179.2msの設定）の２バイト分を16ビット整数にしてから10進数に変換した139を送信します。
この2つのコマンドをまとめて16ビット整数にして送るのが、micro:bitのコツというかクセの有る仕様で、8ビットずつ別々に送ると動作しません。
データの形式は符号なし16ビット整数で、上位バイトから送るためビッグエンディアンになりますので、UInt16BEという形式になります。
「つづく」は後続のデータがなければ「偽」あれば「真」にします。

初期化の後半も同様に、動作スタートのコマンド全体を16ビットにまとめた11という数値を送信します。

#### 「ずっと」のループがデータのレジスタ読み出しのプログラムです。
最初にI2Cアドレス42と、データレジスタを指定する0x03を送信しますが、この場合は1バイトだけのデータなので、形式はUInt8BEになります。

データの取得は、RGBごとにデータを入れる変数を用意しておき、またI2Cアドレスを指定してレジスタを読み出して行きます。
読み出しは16ビットデータで、上位、下位バイトをまとめて取得するため、データ形式はUInt16BEを選択する必要があります。

マップ関数が入っていますが、RGBの感度には差があるので、色の識別に使う場合は生データを補正してホワイトバランスを取るために入れてあります。

# micro:Maqueenを制御してみる
ロボットカー（micro maqueen）に取り付けて走らせた例がこちら。緑色で左に方向転換、赤色で停止するようにしたものです。
[クリックで動画](https://www.youtube.com/shorts/mraQv-NaNkE)
![s13683-maqeen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/fdbcf71c-16d6-fb4b-1e1d-b0894f2dc5e8.png)
以上