後輩たちのためのEV3rt講座番外編(HiTechnicカラーセンサーについて)

#はじめに…
~~これは高校生プログラマーの私が備忘録的に記したものです。
需要は少ないかと思いますが、参考になれば幸いです。~~

【'18/09/10追記】この記事を「後輩たちのためのEV3rt講座シリーズ」に組み込むこととしました。

【'19/06/13追記】細かな編集含め大改訂しました。

#開発環境
前提として、EV3rtはOSによる差は基本的にありません。

- Macbook Air(Mid2011)/macOS High Sierra
- 最新版→TOPPERS EV3rt β7.2(2018年8月17日現在)

Hitechnicカラーセンサーを使用する場合は、β7.1以降である必要があります。
HiTechnicカラーセンサーを使用しない場合は、β7.1より前のver.でも大丈夫です。
ただ、β6よりファイル構成等大幅変更が施されているので、β6以上を推奨します。
その他情報はリリースノートを御覧ください。

#各センサーの使い方
詳しいことはReferenceを見ましょう。
http://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/#EV3RTCAPIリファレンス

##EV3 Color Sensorの使い方
今回は値を取得し、ファイルに書き込むこととします。

```app.c
#include "ev3api.h"
#include "app.h"

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif

int color=0;//カラーセンサーの値を保存する変数

rgb_raw_t rgb_val;//カラーセンサーの値を保存するために必要な変数(必須)

int red=0;
int green=0;
int blue=0;
//RGB分解値を保存するために変数

void main_task(intptr_t unused)
{
ev3_sensor_config (0,COLOR_SENSOR);
//『ポート番号1をEV3 Color Sensorに設定するよ〜』という宣言のようなもの

color=ev3_color_sensor_get_color(0);
//カラーモードでの値取得方法。『0』はポート番号

ev3_color_sensor_get_rgb_raw(0,&rgb_val);
//RGBでの値取得方法。『0』はポート番号、『&rgb_val』は先程定義した変数名

red=rgb_val.r;
green=rgb_val.g;
blue=rgb_val.b;
//先程rgb_valに代入された値を『R値』『G値』『B値』に分解して変数に保存

FILE *file;//構造体の定義
file=fopen("log.txt","a");//log.txtという名前のファイルを作成し、書き込みます
fprintf(file,"Color:%d\n",color);//カラーモードの値を入力
fprintf(file,"Red:%d\n",red);//RGBモードの『R値』を入力
fprintf(file,"Green:%d\n",green);//RGBモードの『G値』を入力
fprintf(file,"Blue:%d\n",blue);//RGBモードの『B値』を入力
fclose(file);
}
```



##NXT HiTechnic Color Sensorの使い方
β7.1からの新機能です。
NXTと出ていますが、EV3でも使用可能です。

HiTechnic Color Sensorではカラーモード・RGBモードを使用できます。
カラーモードは0〜17の対応した色で値を返します。
![17816_2-05.png](https://qiita-image-store.s3.amazonaws.com/0/183170/8b8869e8-8d4b-c198-c1c2-e838d610376d.png)
RGBモードはEV3カラーセンサーのRGBモードと全く同じです。以下、使用方法を記しておきます。
EV3 Color Sensor同様に値を取得し、ファイルに書き込むこととします。

```app.c
#include "ev3api.h"
#include "app.h"

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif

int color=0;//カラーセンサーの値を保存する変数

rgb_raw_t rgb_val;//カラーセンサーの値を保存するために必要な変数(必須)

int red=0;
int green=0;
int blue=0;
//RGB分解値を保存するために変数

void main_task(intptr_t unused)
{
ev3_sensor_config (0,HT_NXT_COLOR_SENSOR);
//『ポート番号1をHiTechnic Color Sensorに設定するよ〜』という宣言のようなもの

ht_nxt_color_sensor_measure_color(0,&color);
//カラーモードでの値取得方法。『0』はポート番号

ht_nxt_color_sensor_measure_rgb(0,&rgb_val);
//RGBでの値取得方法。『0』はポート番号、『&rgb_val』は先程定義した変数名

red=rgb_val.r;
green=rgb_val.g;
blue=rgb_val.b;
//先程rgb_valに代入された値を『R値』『G値』『B値』に分解して変数に保存

FILE *file;//構造体の定義
file=fopen("log.txt","a");//log.txtという名前のファイルを作成し、書き込みます
fprintf(file,"Color:%d\n",color);//カラーモードの値を入力
fprintf(file,"Red:%d\n",red);//RGBモードの『R値』を入力
fprintf(file,"Green:%d\n",green);//RGBモードの『G値』を入力
fprintf(file,"Blue:%d\n",blue);//RGBモードの『B値』を入力
fclose(file);
}
```
###【追記】β7でのHiTechnic Color Sensorの使用方法#
β7ではHiTechnic Color Sensorはサポートされていませんが、少し手を加えればHiTechnic Color Sensorを使用することができます。
基本的にはβ7.1以上を使用してください。
どうしても、という方は自己責任でお願いします。
`hrp2/sdk/common/ev3api/src/`を開くと`ev3api_sensor.c`と`ev3api_sensor.h`があると思います。
それぞれ以下のソースを書き加えてください。

```ev3api_sensor.c
bool_t ht_nxt_color_sensor_measure_color(sensor_port_t port, uint8_t *color) {
    ER ercd;
    
    CHECK_PORT(port);
    CHECK_COND(ev3_sensor_get_type(port) == HT_NXT_COLOR_SENSOR, E_OBJ);
    CHECK_COND(*pI2CSensorData[port].status == I2C_TRANS_IDLE, E_OBJ);
    
    *color = pI2CSensorData[port].raw[0];
    
    ercd = start_i2c_transaction(port, 0x1, "\x42", 1, 1);
    assert(ercd == E_OK);
    
    return true;
    
error_exit:
    syslog(LOG_WARNING, "%s(): ercd %d", __FUNCTION__, ercd);
    return false;
}

bool_t ht_nxt_color_sensor_measure_rgb(sensor_port_t port, rgb_raw_t *val) {
    ER ercd;
    
    CHECK_PORT(port);
    CHECK_COND(ev3_sensor_get_type(port) == HT_NXT_COLOR_SENSOR, E_OBJ);
    CHECK_COND(*pI2CSensorData[port].status == I2C_TRANS_IDLE, E_OBJ);
    
    val->r = pI2CSensorData[port].raw[0];
    val->g = pI2CSensorData[port].raw[1];
    val->b = pI2CSensorData[port].raw[2];
    
    ercd = start_i2c_transaction(port, 0x1, "\x43", 1, 3);
    assert(ercd == E_OK);
    
    return true;
    
error_exit:
    syslog(LOG_WARNING, "%s(): ercd %d", __FUNCTION__, ercd);
    return false;
}
```

```app.h
/**
 * \~English
 * \brief        Measure color with a HiTechnic NXT color sensor (NCO1038).
 * \details      When an invalid sensor support number is specified, always returns false (error log is output)
 * \param port   Sensor port to be inquired
 * \param color  Pointer to store color number (0-17)
 * \retval true  color is updated
 * \retval false color is unchanged due to I2C busy
 *
 * \~Japanese
 * \brief        カラーセンサ（HiTechnic社製）でカラーを測定する．
 * \details      不正のセンサポート番号を指定した場合，常に \a false を返す（エラーログが出力される）．
 * \param  port  センサポート番号
 * \param  color カラーの番号（0-17）を格納するためのポインタ
 * \retval true  colorは更新された
 * \retval false colorは変更されなかった（前回のI2C操作が完成していない）
 */
bool_t ht_nxt_color_sensor_measure_color(sensor_port_t port, uint8_t *color);

/**
 * \~English
 * \brief        Measure RGB raw value with a HiTechnic NXT color sensor (NCO1038).
 * \details      When an invalid sensor support number is specified, always returns false (error log is output)
 * \param port   Sensor port to be inquired
 * \param val    Pointer to store RGB raw value
 * \retval true  val is updated
 * \retval false val is unchanged due to I2C busy
 *
 * \~Japanese
 * \brief        カラーセンサ（HiTechnic社製）でRGB Raw値を測定する．
 * \details      不正のセンサポート番号を指定した場合，常に \a false を返す（エラーログが出力される）．
 * \param  port  センサポート番号
 * \param  val   RGB Raw値を格納するためのポインタ
 * \retval true  valは更新された
 * \retval false valは変更されなかった（前回のI2C操作が完成していない）
 */
bool_t ht_nxt_color_sensor_measure_rgb(sensor_port_t port, rgb_raw_t *val);
```

#2つのセンサーの違いについて
同じColor Sensorという名前ですが、中身は全然違います。
これ↓がEV3 Color Sensor
![0000000002162.png](https://qiita-image-store.s3.amazonaws.com/0/183170/60eb097d-80b6-05e2-5a99-a1dc901ef5c2.png)
そしてこれ↓がHiTechnic Color Sensor
![Color Sensor W1.jpg](https://qiita-image-store.s3.amazonaws.com/0/183170/20455f6c-dc6c-d560-fabd-d97694b2a298.jpeg)

##主な違い
- 反応速度(測定周期)がEV3のほうが早く、HiTechnicは遅い(短時間の連続測定に向かない)
- 測定可能距離がEV3が約0.5〜1.5cmに対し、HiTechnicは約5cm程度まで(ただし信頼出来る限界は約3cm)
- カラーモードでの戻り値がEV3は0〜7、HiTechnicは0〜17
- EV3はセンサー自ら発する光の反射を読み取り測定する(周りの光に影響されにくい)
- EV3は上記測定法のため、斜め照射は出来ず、光がちゃんと跳ね返ってくる物しか測定できない
- HiTechnicはいわゆる『周辺光』の測定となる(周りの光に影響されやすい)
- HiTechnicは上記測定法のため、斜め照射も出来る。

大きな違いとしては上記のような点です。

##通信方式
Hitechnic Color SensorはI2Cのシリアル通信であるのに対し、
EV3 Color Sensor はUARTのシリアル・パラレル切り替え方式です。

両者ともに良い点、悪い点あるので、自分の状況下において最適なセンサーを選ぶと良いでしょう。