目次
前
次
カラーセンサー関係スケッチ
各LEDの色の違いで、どの程度の波長が出ているのかを
調べるために、カラーセンサーを利用しました。
秋月電子で販売されていたカラーセンサーS9706を
変換基板に半田付けし、Arduinoに接続後RGBの各
センサーの数値を、0から4095で表示します。
センサーのデータ取得タイミングチャートを見て
変換シーケンスを考えていきます。
RANGEで感度を決め、GATEのH期間でシャッターを
開いている時間を指定しています。その後にCLK
に同期して出力されるRGBの各12ビットを取得する
ことで、センサー情報になります。
Arduinoとセンサーの接続は、以下としました。
シーケンスを、ひとつの関数に担当させることに。
void get_color(byte which,byte xd)
{
byte i ;
word rgb[3] ;
/* set RANGE */
put_range( which ) ;
/* disable GATE and CK */
put_gate(OFF);
put_ck(OFF);
/* open GATE */
put_gate( ON ) ;
delay(xd+2);
put_gate(OFF);
/* loop */
for ( i = 0 ; i < 3 ; i++ ) {
/* interval */
delayMicroseconds(4);
/* get RGB information */
*(rgb+i) = get_color_value() ;
}
/* copy */
rxdat = *(rgb+0) ;
gxdat = *(rgb+1) ;
bxdat = *(rgb+2) ;
}
void put_range(byte x)
{
if ( x == ON ) {
PORTC |= (1 << RANGE_BIT) ;
} else {
PORTC &= ~(1 << RANGE_BIT) ;
}
}
void put_gate(byte x)
{
if ( x == HD ) {
PORTC |= (1 << GATE_BIT) ;
} else {
PORTC &= ~(1 << GATE_BIT) ;
}
}
void put_ck(byte x)
{
if ( x == ON ) {
PORTC |= (1 << CK_BIT) ;
} else {
PORTC &= ~(1 << CK_BIT) ;
}
}
word get_color_value()
{
word result ;
byte i ;
/* clear */
result = 0 ;
/* loop */
for ( i = 0 ; i < 12 ; i++ ) {
/* shift */
result >>= 1 ;
/* CK : H */
put_ck( ON ) ;
/* delay */
delayMicroseconds(2);
/* get data */
if ( PINC & ON ) { result |= 0x800 ; }
/* CK : L */
put_ck( OFF ) ;
/* delay */
delayMicroseconds(2);
}
/* adjust */
result &= 0xfff ;
return result ;
}
シリアルインタフェースで制御できるように
コマンドインタプリタを用意し、操作が簡単
になるようにします。
コマンドは、次のように決めました。
- ? ヘルプ
- G センサーデータを取得し、RGBを0から4095の数値で表示
- T シャッターを開けておく時間を0から255msで指定
- R 感度指定で0で低感度、1で高感度に設定
コマンドを決めたなら、データ転送速度を9600bpsとし
スケッチを定義します。
#include <MsTimer2.h>
#define OFF 0
#define ON OFF+1
#define LD 0
#define HD 1
/* color sensor pin assignment */
#define RANGE_BIT 3
#define CLK_BIT 2
#define GATE_BIT 1
#define DOUT_BIT 0
#define TBIT 11
/* monitor LED */
#define LED_BIT 5
/* global variables */
byte bflag ;
byte uflag ;
byte sindex ;
byte sbuf[8] ;
byte xcnt ;
word rxdat ;
word gxdat ;
word bxdat ;
byte timcnt ;
void send_led(byte x)
{
if ( x ) { PORTB |= (1 << LED_BIT) ; }
else { PORTB &= ~(1 << LED_BIT) ; }
}
void update_trigger(void)
{
send_led( xcnt & ON );
xcnt++ ;
}
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *x)
{
while ( *x ) {
rs_putchar( *x ) ;
x++ ;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
byte get_hex(char x)
{
byte result ;
result = 0 ;
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
void show_digit4(word x)
{
byte j ;
char msg[4] ;
/* separate */
for ( j = 0 ; j < 4 ; j++ ) {
*(msg+3-j) = x % 10 + '0' ;
x /= 10 ;
}
/* zero suppress */
if ( *(msg+0) == '0' ) {
*(msg+0) = ' ' ;
if ( *(msg+1) == '0' ) {
*(msg+1) = ' ' ;
if ( *(msg+2) == '0' ) {
*(msg+2) = ' ' ;
}
}
}
/* show */
for ( j = 0 ; j < 4 ; j++ ) { rs_putchar( *(msg+j) ); }
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("G get data and show") ; crlf();
rs_puts("T set delay time count(1-255)") ; crlf();
rs_puts("R select range (0 or 1)") ; crlf();
}
void get_color(byte which,byte xd)
{
byte i ;
word rgb[3] ;
/* set RANGE */
put_range( which ) ;
/* disable GATE and CK */
put_gate(OFF);
put_ck(OFF);
/* open GATE */
put_gate( ON ) ;
delay(xd+2);
put_gate(OFF);
/* loop */
for ( i = 0 ; i < 3 ; i++ ) {
/* interval */
delayMicroseconds(4);
/* get RGB information */
*(rgb+i) = get_color_value() ;
}
/* copy */
rxdat = *(rgb+0) ;
gxdat = *(rgb+1) ;
bxdat = *(rgb+2) ;
}
void put_range(byte x)
{
if ( x == ON ) {
PORTC |= (1 << RANGE_BIT) ;
} else {
PORTC &= ~(1 << RANGE_BIT) ;
}
}
void put_gate(byte x)
{
if ( x == HD ) {
PORTC |= (1 << GATE_BIT) ;
} else {
PORTC &= ~(1 << GATE_BIT) ;
}
}
void put_ck(byte x)
{
if ( x == ON ) {
PORTC |= (1 << CK_BIT) ;
} else {
PORTC &= ~(1 << CK_BIT) ;
}
}
word get_color_value()
{
word result ;
byte i ;
/* clear */
result = 0 ;
/* loop */
for ( i = 0 ; i < 12 ; i++ ) {
/* shift */
result >>= 1 ;
/* CK : H */
put_ck( ON ) ;
/* delay */
delayMicroseconds(2);
/* get data */
if ( PINC & ON ) { result |= 0x800 ; }
/* CK : L */
put_ck( OFF ) ;
/* delay */
delayMicroseconds(2);
}
/* adjust */
result &= 0xfff ;
return result ;
}
void show_values()
{
byte j ;
word tmp ;
for ( j = 0 ; j < 3 ; j++ ) {
/* prompt */
if ( j == 2 ) {
rs_putchar('B') ;
tmp = gxdat ;
} else {
if ( j == 1 ) {
rs_putchar('G');
tmp = bxdat ;
} else {
rs_putchar('R');
tmp = rxdat ;
}
}
rs_puts(" = ");
show_digit4( tmp );
crlf();
}
}
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* define digital pin */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x01 ;
/* set initial state */
DDRB = 0xff ;
DDRC = 0xfe ;
DDRD = 0xfe ;
/* clear flags */
bflag = OFF ;
uflag = OFF ;
/* initialize variables */
rxdat = 0 ;
gxdat = 0 ;
bxdat = 0 ;
timcnt = 0 ;
xcnt = 0 ;
/* 250ms period */
MsTimer2::set(250,update_trigger);
/* enable */
MsTimer2::start();
}
void loop()
{
byte cmd ;
byte i ;
/* serial handling */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* get color data and show */
if ( cmd == 'G' ) {
/* color sensor handling */
get_color(bflag,timcnt);
/* show values */
show_values();
}
/* set delay time count */
if ( cmd == 'T' ) {
/* clear */
timcnt = 0 ;
/* convert */
for ( i = 0 ; i < 3 ; i++ ) {
/* judge */
if ( *(sbuf+i+1) == '\r' ) break ;
/* calcualte */
timcnt = timcnt * 10 + get_hex( *(sbuf+i+1) ) ;
}
/* echo back */
show_digit4( timcnt );
crlf() ;
}
/* set range */
if ( cmd == 'R' ) {
/* default */
bflag = OFF ;
/* get selection code */
if ( *(sbuf+1) == '1' ) { bflag = ON ; }
}
}
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
このスケッチで、赤、緑、橙、黄、青、白の
色に関係する周波数特性を把握できます。
目次
前
次