目次
前
次
カラーセンサー情報取得2
浜松ホトニクスからI2Cバスインタフェースをもつ
カラーセンサーが発売になっています。
このカラーセンサーは、3.3Vで動作するので5Vから3.3Vを
作り出す回路とプルアップ抵抗を入れる基板を半田付け
しました。3.3Vがあれば、キャパシタとプルアップ抵抗を
いれるだけですが。
電圧変換回路には、白色LEDをZennerダイオードの代わりに
使っています。
3.3Vを生成できなかったので、シリコンダイオードを入れて
3.2Vまで電圧を引き上げました。
1チャネルのI2Cバスは、ArduinoのアナログポートA5、A4に
なっています。A5(SCL)、A4(SDA)を使う場合、ライブラリ
のWireを利用します。
ピンアサインは、以下。
Arduino、中継基板、カラーセンサーを接続すると
つぎのようになります。
3.3Vを出力しているArduinoの場合、そのまま
その電圧を利用した方がよいでしょう。
1チャネルのカラーセンサー情報取得スケッチは、以下。
#include <MsTimer2.h>
#include "Wire.h"
#define OFF 0
#define ON OFF+1
#define LED_BIT 5
#define DEVICE_ID 0x2A
#define CONTROL_REG 0x00
#define NPER 1500
/* event flag */
boolean eflag ;
boolean tflag ;
boolean uflag ;
/* timing counter */
byte xcnt ;
/* serial interface */
byte cmd ;
byte sindex ;
char sbuf[4] ;
/* RGB and IR */
word xrgbi[4] ;
/* LED flashing */
void send_led(byte x)
{
if ( x ) { PORTB |= (1 << LED_BIT) ; }
else { PORTB &= ~(1 << LED_BIT) ; }
}
/* generate trigger */
void update_trigger(void)
{
/* LED flashing */
send_led( xcnt & ON );
/* trigger */
xcnt++ ;
if ( xcnt & ON ) { tflag = ON ; }
}
/* putchar on serial interface */
void rs_putchar(char x)
{
Serial.write(x);
}
/* puts on serial interface */
void rs_puts(char *x)
{
while ( *x ) {
rs_putchar( *x ) ;
x++ ;
}
}
/* new line */
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("E execute") ; crlf();
rs_puts("I idle") ; crlf();
}
void show_value(word x)
{
word tmp ;
char msg[6] ;
byte i ;
/* copy */
tmp = x ;
/* delimiter */
*(msg+5) = '\0' ;
/* separate */
for ( i = 0 ; i < 5 ; i++ ) {
/* value -> digit number */
*(msg+4-i) = (tmp % 10)+ '0' ;
/* next */
tmp /= 10 ;
}
/* zero surppress */
if ( x < 10000 ) {
*(msg+0) = ' ' ;
if ( x < 1000 ) {
*(msg+1) = ' ' ;
if ( x < 100 ) {
*(msg+2) = ' ' ;
if ( x < 10 ) {
*(msg+3) = ' ' ;
}
}
}
}
/* show */
rs_puts( msg ) ;
rs_putchar(' ') ;
}
void get_color()
{
byte i ;
word tmp ;
/*
preset gain mode exposure time (each color ch)
00 = 87.5us
01= 1.4ms
10= 22.4ms
11= 179.2ms
*/
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
Wire.write(0x83); /* reset ADC and wakeup */
Wire.endTransmission(OFF);
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
Wire.write(0x03);
Wire.endTransmission(ON);
/* total exposure time */
delay(180*4);
/* get each color value */
Wire.beginTransmission(DEVICE_ID);
Wire.write(0x03);
Wire.endTransmission(OFF);
Wire.requestFrom(DEVICE_ID,8,ON);
/* 8 x 2 x 4 */
for ( i = 0 ; i < 4 ; i++ ) {
/* upper value */
tmp = Wire.read();
/* shift */
tmp <<= 8;
/* add lower value */
tmp |= Wire.read();
/* store */
*(xrgbi+i) = tmp ;
}
}
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* set initial state */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x01 ;
/* direction */
DDRB = 0xff ;
DDRC = 0xff ;
DDRD = 0xfe ;
/* clear flags */
tflag = OFF ;
eflag = OFF ;
uflag = OFF ;
/* initialize variables */
xcnt = 0 ;
*(xrgbi+0) = 0 ; *(xrgbi+1) = 0 ;
*(xrgbi+2) = 0 ; *(xrgbi+3) = 0 ;
/* trigger period */
MsTimer2::set(NPER,update_trigger);
/* enable */
MsTimer2::start();
/* enable I2C bus interface */
Wire.begin();
}
void loop()
{
/* serial handling */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'E' ) { eflag = ON ; }
/* disable */
if ( cmd == 'I' ) { eflag = OFF ; }
}
/* timer handling */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* get color values */
get_color();
/* show */
if ( eflag == ON ) {
rs_puts("R : ") ; show_value( *(xrgbi+0) );
rs_puts("G : ") ; show_value( *(xrgbi+1) );
rs_puts("B : ") ; show_value( *(xrgbi+2) );
rs_puts("IR: ") ; show_value( *(xrgbi+3) );
crlf();
}
}
}
/* 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 ;
}
}
}
端末ソフトTeraTermを利用し、カラーセンサーの取得情報を表示させます。
利用しているカラーセンサーは、感度、露光時間を変更できるので
新たにコマンドを用意して設定変更できるようにしました。
新設コマンドは、以下。
- S 感度選択 1:高感度 0:低感度
- L 露光時間選択 パラメータは0から3で指定
- G 緑色情報のみか全色情報表示選択 1:緑色 0:全色
- M フィルタのあるかないかの指定 1:あり 0:なし
- s ステータス表示 感度、露光時間、緑表示、フィルタありの表示
ステータスに関しては、次のように1文字か数字で表現し
1行に4文字で表示。
- S = H:高感度 L:低感度
- L = 0から3
- G = Y:緑色 N:全色
- M = Y:あり N:なし
スケッチのコードは、以下。
#include <MsTimer2.h>
#include <EEPROM.h>
#include "Wire.h"
#define OFF 0
#define ON OFF+1
#define LED_BIT 5
#define DEVICE_ID 0x2A
#define CONTROL_REG 0x00
#define NPER 800
#define SCODE_ADR 0x100
#define SHOW_ADR 0x101
/* event flag */
boolean eflag ;
boolean tflag ;
boolean uflag ;
/* state flag */
boolean gflag ; /* select only green information */
boolean mflag ; /* mask flag */
/* timing counter */
byte xcnt
/* serial interface */
byte cmd ;
byte sindex ;
char sbuf[4] ;
/* RGB and IR */
word xrgbi[4] ;
/* sensor command */
byte scmd ;
/* LED flashing */
void send_led(byte x)
{
if ( x ) { PORTB |= (1 << LED_BIT) ; }
else { PORTB &= ~(1 << LED_BIT) ; }
}
/* generate trigger */
void update_trigger(void)
{
/* LED flashing */
send_led( xcnt & ON );
/* trigger */
xcnt++ ;
if ( xcnt & ON ) { tflag = ON ; }
}
/* putchar on serial interface */
void rs_putchar(char x)
{
Serial.write(x);
}
/* puts on serial interface */
void rs_puts(char *x)
{
while ( *x ) {
rs_putchar( *x ) ;
x++ ;
}
}
/* new line */
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("E execute") ; crlf();
rs_puts("I idle") ; crlf();
rs_puts("S set sensibility 1:high 0:low") ; crlf();
rs_puts("L set exposure time Length(0/1/2/3)") ; crlf();
rs_puts("G set only Green information 1:YES 0:NO") ; crlf();
rs_puts("M set mask 1:YES 0:NO") ; crlf();
rs_puts("s show staus") ; crlf();
}
void show_value(word x)
{
word tmp ;
char msg[6] ;
byte i ;
/* copy */
tmp = x ;
/* delimiter */
*(msg+5) = '\0' ;
/* separate */
for ( i = 0 ; i < 5 ; i++ ) {
/* value -> digit number */
*(msg+4-i) = (tmp % 10)+ '0' ;
/* next */
tmp /= 10 ;
}
/* zero surppress */
if ( x < 10000 ) {
*(msg+0) = ' ' ;
if ( x < 1000 ) {
*(msg+1) = ' ' ;
if ( x < 100 ) {
*(msg+2) = ' ' ;
if ( x < 10 ) {
*(msg+3) = ' ' ;
}
}
}
}
/* show */
rs_puts( msg ) ;
rs_putchar(' ');
}
void get_color()
{
byte i ;
word tmp ;
/*
preset gain mode exposure time (each color ch)
00 = 87.5us => 0.9ms
01 = 1.4ms => 2.0ms
10 = 22.4ms => 23ms
11 = 179.2ms => 180ms
*/
i = scmd & 3 ;
if ( i == 3 ) { tmp = 180 * 4; }
if ( i == 2 ) { tmp = 23 * 4; }
if ( i < 2 ) { tmp = 2 * 4; }
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
Wire.write(0x83); /* reset ADC and wakeup */
Wire.endTransmission(OFF);
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
/* set High or Low and exposure length */
Wire.write( scmd );
Wire.endTransmission(ON);
/* total exposure time */
delay(tmp);
/* get each color value */
Wire.beginTransmission(DEVICE_ID);
Wire.write(0x03);
Wire.endTransmission(OFF);
Wire.requestFrom(DEVICE_ID,8,ON);
/* 8 x 2 x 4 */
for ( i = 0 ; i < 4 ; i++ ) {
/* upper value */
tmp = Wire.read();
/* shift */
tmp <<= 8;
/* add lower value */
tmp |= Wire.read();
/* store */
*(xrgbi+i) = tmp ;
}
}
void show_yn()
{
char msg[2];
/* delimiter */
*(msg+1) = '\0' ;
/* sensibility */
{
*(msg+0) = 'L' ;
if ( scmd & 8 ) { *(msg+0) = 'H' ; }
rs_puts( msg );
}
/* exposure length */
{
rs_putchar( '0'+(scmd & 3) );
}
/* Green */
{
*(msg+0) = 'N' ;
if ( gflag == ON ) { *(msg+0) = 'Y' ; }
rs_puts( msg );
}
/* Mask */
{
*(msg+0) = 'N' ;
if ( mflag == ON ) { *(msg+0) = 'Y' ; }
rs_puts( msg );
}
/* new line */
crlf();
}
void store_param(byte which,byte x)
{
word madr ;
/* sensibility or exposure length */
if ( which < 2 ) { madr = SCODE_ADR ; }
/* Green information */
if ( which == 2 ) { madr = SHOW_ADR ; }
/* store */
EEPROM.write(madr,x);
}
void show_color(boolean x)
{
/* only Green information */
if ( x ) {
rs_puts("G :") ; show_value( *(xrgbi+1) );
}
else
/* all color informations */
{
rs_puts("R :") ; show_value( *(xrgbi+0) );
rs_puts("G :") ; show_value( *(xrgbi+1) );
rs_puts("B :") ; show_value( *(xrgbi+2) );
rs_puts("IR:") ; show_value( *(xrgbi+3) );
}
crlf();
}
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* set initial state */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x01 ;
/* direction */
DDRB = 0xff ;
DDRC = 0xff ;
DDRD = 0xfe ;
/* clear flags */
tflag = OFF ;
eflag = OFF ;
uflag = OFF ;
gflag = OFF ;
/* resume previous state */
xcnt = EEPROM.read(SCODE_ADR);
if ( xcnt == 0xff ) {
scmd = 11 ;
EEPROM.write(SCODE_ADR,scmd);
} else {
scmd = xcnt ;
}
xcnt = EEPROM.read(SHOW_ADR);
if ( xcnt != OFF ) { gflag = ON ; }
/* initialize variables */
for ( xcnt = 0 ; xcnt < 4 ; xcnt++ ) {
*(xrgbi+xcnt) = 0 ;
}
xcnt = 0 ;
/* trigger period */
MsTimer2::set(NPER,update_trigger);
/* enable */
MsTimer2::start();
/* enable I2C bus interface */
Wire.begin();
}
void loop()
{
/* serial handling */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'E' ) { eflag = ON ; }
/* disable */
if ( cmd == 'I' ) { eflag = OFF ; }
/* write sensibility state */
if ( cmd == 'S' ) {
/* set default (selct LOW) */
scmd &= 0xf7 ;
/* set flag (HIGH or LOW) */
if ( *(sbuf+1) == '1' ) { scmd |= (1 << 3) ; }
/* store EEPROM */
store_param(0,scmd);
}
/* write exposure length */
if ( cmd == 'L' ) {
/* clear */
scmd &= 0xfc ;
/* generate code */
scmd |= ((*(sbuf+1) - '0') & 3);
/* store EEPROM */
store_param(1,scmd);
}
/* write only Green information */
if ( cmd == 'G' ) {
/* default */
gflag = OFF ;
/* judge */
if ( *(sbuf+1) == '1' ) { gflag = ON ; }
/* store */
store_param(2,gflag);
}
/* write mask */
if ( cmd == 'M' ) {
/* default */
mflag = OFF ;
/* judge */
if ( *(sbuf+1) == '1' ) { mflag = ON ; }
}
/* show status */
if ( cmd == 's' ) { show_yn(); }
}
/* timer handling */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* get color values */
get_color();
/* show */
if ( eflag == ON ) { show_color(gflag) ; }
}
}
/* 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 ;
}
}
}
一度指定したパラメータは、EEPROMに格納するので
電源を切って再度入れても、前回の指定した環境で
使えるようになっています。
Arduinoに接続して、?でコマンドを確認。
sコマンドで動作環境を確認、Gコマンドで全色情報か
緑色情報のみの表示かを変更できることを確認。
端末ソフトでは、タイプする量が多いので
Processingのスケッチで操作が簡単になる
ようにします。
テストするためのProcessingのスケッチを作成しました。
import processing.serial.*;
Serial cport;
PImage imgExecute ;
PImage imgIdle ;
PImage imgExit ;
PImage imgStatus ;
int FRATE = 60 ;
int WX = 640 ;
int WY = 480 ;
int XBEGIN = 100 ;
int YBEGIN = 100 ;
int WIDTH = 150 ;
int HEIGHT = 150 ;
String stmp ;
boolean isRangeOk(int x,int bx,int ex)
{
boolean result ;
/* default */
result = false ;
/* judge */
if ( bx <= x && x <= ex ) { result = true ; }
return result ;
}
void setup()
{
size(640,480);
/* title caption */
frame.setTitle("Test 03");
/* select framerate */
frameRate(FRATE);
/* select back ground color with BLACK */
background(0,0,0);
//println(Serial.list());
String arduinoPort = Serial.list()[4];
/* initialize serial port */
cport = new Serial(this,arduinoPort,9600);
//sidx = 0 ;
scflag = false ;
/* get image */
imgExecute = loadImage("execute.png");
imgIdle = loadImage("idle.png");
imgStatus = loadImage("status.png");
imgExit = loadImage("exit.png");
/* */
stmp = "" ;
}
void draw()
{
/* button */
image(imgExecute, 20,402);
image(imgIdle ,120,402);
image(imgStatus ,240,402);
image(imgExit ,360,402);
/* serial receive */
if ( cport.available() > 4 ) {
background(0,0,0);
fill(255,0,0);
stmp = cport.readStringUntil('\n');
stmp = trim(stmp);
textSize(20);
text(stmp, 100, 100);
}
}
void mouseClicked()
{
if ( mouseButton == LEFT ) {
/* execute */
if ( isRangeOk(mouseX,20,70) &&
isRangeOk(mouseY,402,422) ) {
/* debug */
println("execute");
/* send command */
cport.write('E');
cport.write('\r');
}
/* idle */
if ( isRangeOk(mouseX,120,170) &&
isRangeOk(mouseY,402,422) ) {
/* debug */
println("idle");
/* send command */
cport.write('I');
cport.write('\r');
}
/* status */
if ( isRangeOk(mouseX,240,290) &&
isRangeOk(mouseY,402,422) ) {
/* debug */
println("Status");
/* send command */
cport.write('S');
cport.write('\r');
}
/* exit */
if ( isRangeOk(mouseX,360,390) &&
isRangeOk(mouseY,402,422) ) {
/* debug */
println("exit");
exit();
}
}
/* Exit */
if ( mouseButton == RIGHT ) {
exit();
}
}
画面は、次のようになります。
ボタンexecute、idle、status、EXITをクリックすると
指定された動作を実行します。
ボタンexecuteの機能
シリアルポートから、Arduinoにコマンド'E'を送信します。
Arduinoは、基板上のLEDを点滅させます。
点滅停止のコマンドを送信しない限り、点滅を継続します。
ボタンidleの機能
シリアルポートから、Arduinoにコマンド'I'を送信します。
Arduinoは、基板上のLED点滅を終了します。
ボタンstatusの機能
シリアルポートから、Arduinoにコマンド'S'を送信します。
Arduinoは、その時点の状態を文字列runかidleで
返してきます。
Processingでは、Arduinoが返してくる文字列を
取得し表示します。
ボタンexecuteクリック後の画面。
ボタンidleクリック後の画面。
Arduinoのように、受信割込みを使わないで
drawの中で、受信バッファに文字列があるか
を確認後、取り出して表示します。
if ( cport.available() > 0) {
background(0,0,0);
fill(255,0,0);
stmp = cport.readStringUntil('\n');
stmp = trim(stmp);
textSize(20);
text(stmp, 100, 100);
}
ボタンEXITの機能
Processingのスケッチを終了します。
Arduinoのスケッチは、以下。
#include <MsTimer2.h>
#define OFF 0
#define ON OFF+1
#define LED_BIT 5
#define NPER 500
/* event flag */
boolean eflag ;
boolean tflag ;
boolean uflag ;
/* serial interface */
byte cmd ;
byte sindex ;
char sbuf[4] ;
byte xcnt ;
char msg[5] ;
/* LED flashing */
void send_led(byte x)
{
if ( x ) { PORTB |= (1 << LED_BIT) ; }
else { PORTB &= ~(1 << LED_BIT) ; }
}
/* generate trigger */
void update_trigger(void)
{
tflag = ON ;
}
/* putchar on serial interface */
void rs_putchar(char x)
{
Serial.write(x);
}
/* puts on serial interface */
void rs_puts(char *x)
{
while ( *x ) {
rs_putchar( *x ) ;
x++ ;
}
}
/* new line */
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("E execute") ; crlf();
rs_puts("I idle") ; crlf();
rs_puts("S status") ; crlf();
}
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* set initial state */
PORTB = 0x00 ;
PORTC = 0x08 ;
PORTD = 0x01 ;
/* direction */
DDRB = 0xff ;
DDRC = 0xff ;
DDRD = 0xfe ;
/* clear flags */
tflag = OFF ;
eflag = OFF ;
uflag = OFF ;
/* */
xcnt = 0 ;
/* trigger period */
MsTimer2::set(NPER,update_trigger);
/* enable */
MsTimer2::start();
}
void loop()
{
/* serial handling */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'E' ) { eflag = ON ; }
/* disable */
if ( cmd == 'I' ) { eflag = OFF ; }
/* show status */
if ( cmd == 'S' ) {
/* default */
strcpy(msg,"idle");
/* check */
if ( eflag == ON ) { strcpy(msg,"run "); }
/* show message */
rs_puts( msg );
crlf();
}
}
/* timer handling */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* default */
send_led( OFF );
/* judge */
if ( eflag == ON ) {
if ( xcnt & ON ) { send_led( ON ); }
}
/* update */
xcnt++ ;
}
}
/* 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 ;
}
}
}
ProcessingとArduino間で、情報交換できるようになったので
ProcessingスケッチをRGBおよび輝度の数値と比率をバーで
表示できるようにします。
受信バッファに入れられている情報を活用するには
次の内容を処理します。
- 文字列から必要な情報(数値)を取得
- 数値を利用しバー表示
必要な情報を取得できるように、Arduinoスケッチに
コマンド'C'を用意します。
コマンド'C'を送信すると、その時点のカラーセンサー
の情報を取得してProcessingスケッチに返します。
この機能をいれたArduinoスケッチは、以下。
#include <MsTimer2.h>
#include <EEPROM.h>
#include "Wire.h"
#define OFF 0
#define ON OFF+1
#define LED_BIT 5
#define DEVICE_ID 0x2A
#define CONTROL_REG 0x00
#define NPER 800
#define SCODE_ADR 0x100
#define SHOW_ADR 0x101
/* event flag */
boolean eflag ;
boolean tflag ;
boolean uflag ;
/* state flag */
boolean gflag ; /* select only green information */
boolean mflag ; /* mask flag */
/* timing counter */
byte xcnt ;
/* serial interface */
byte cmd ;
byte sindex ;
char sbuf[4] ;
/* RGB and IR */
word xrgbi[4] ;
/* sensor command */
byte scmd ;
/* LED flashing */
void send_led(byte x)
{
if ( x ) { PORTB |= (1 << LED_BIT) ; }
else { PORTB &= ~(1 << LED_BIT) ; }
}
/* generate trigger */
void update_trigger(void)
{
/* LED flashing */
send_led( xcnt & ON );
/* trigger */
xcnt++ ;
if ( xcnt & ON ) { tflag = ON ; }
}
/* putchar on serial interface */
void rs_putchar(char x)
{
Serial.write(x);
}
/* puts on serial interface */
void rs_puts(char *x)
{
while ( *x ) {
rs_putchar( *x ) ;
x++ ;
}
}
/* new line */
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("E execute") ; crlf();
rs_puts("I idle") ; crlf();
rs_puts("C one shot") ; crlf();
rs_puts("S set sensibility 1:high 0:low") ; crlf();
rs_puts("L set exposure time Length(0/1/2/3)") ; crlf();
rs_puts("G set only Green information 1:YES 0:NO") ; crlf();
rs_puts("M set mask 1:YES 0:NO") ; crlf();
rs_puts("s show staus") ; crlf();
}
void show_value(word x)
{
word tmp ;
char msg[6] ;
byte i ;
/* copy */
tmp = x ;
/* delimiter */
*(msg+5) = '\0' ;
/* separate */
for ( i = 0 ; i < 5 ; i++ ) {
/* value -> digit number */
*(msg+4-i) = (tmp % 10)+ '0' ;
/* next */
tmp /= 10 ;
}
/* zero surppress */
if ( x < 10000 ) {
*(msg+0) = ' ' ;
if ( x < 1000 ) {
*(msg+1) = ' ' ;
if ( x < 100 ) {
*(msg+2) = ' ' ;
if ( x < 10 ) {
*(msg+3) = ' ' ;
}
}
}
}
/* show */
rs_puts( msg ) ;
rs_putchar(' ');
}
void get_color()
{
byte i ;
word tmp ;
/*
preset gain mode exposure time (each color ch)
00 = 87.5us => 0.9ms
01 = 1.4ms => 2.0ms
10 = 22.4ms => 23ms
11 = 179.2ms => 180ms
*/
i = scmd & 3 ;
if ( i == 3 ) { tmp = 180 * 4; }
if ( i == 2 ) { tmp = 23 * 4; }
if ( i < 2 ) { tmp = 2 * 4; }
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
Wire.write(0x83); /* reset ADC and wakeup */
Wire.endTransmission(OFF);
Wire.beginTransmission(DEVICE_ID);
Wire.write(CONTROL_REG);
/* set High or Low and exposure length */
Wire.write( scmd );
Wire.endTransmission(ON);
/* total exposure time */
delay(tmp);
/* get each color value */
Wire.beginTransmission(DEVICE_ID);
Wire.write(0x03);
Wire.endTransmission(OFF);
Wire.requestFrom(DEVICE_ID,8,ON);
/* 8 x 2 x 4 */
for ( i = 0 ; i < 4 ; i++ ) {
/* upper value */
tmp = Wire.read();
/* shift */
tmp <<= 8;
/* add lower value */
tmp |= Wire.read();
/* store */
*(xrgbi+i) = tmp ;
}
}
void show_yn()
{
char msg[2];
/* delimiter */
*(msg+1) = '\0' ;
/* sensibility */
{
*(msg+0) = 'L' ;
if ( scmd & 8 ) { *(msg+0) = 'H' ; }
rs_puts( msg );
}
/* exposure length */
{
rs_putchar( '0'+(scmd & 3) );
}
/* Green */
{
*(msg+0) = 'N' ;
if ( gflag == ON ) { *(msg+0) = 'Y' ; }
rs_puts( msg );
}
/* Mask */
{
*(msg+0) = 'N' ;
if ( mflag == ON ) { *(msg+0) = 'Y' ; }
rs_puts( msg );
}
/* new line */
crlf();
}
void store_param(byte which,byte x)
{
word madr ;
/* sensibility or exposure length */
if ( which < 2 ) { madr = SCODE_ADR ; }
/* Green information */
if ( which == 2 ) { madr = SHOW_ADR ; }
/* store */
EEPROM.write(madr,x);
}
void show_color(boolean x)
{
/* only Green information */
if ( x ) {
rs_puts("G :") ; show_value( *(xrgbi+1) );
}
else
/* all color informations */
{
rs_puts("R :") ; show_value( *(xrgbi+0) );
rs_puts("G :") ; show_value( *(xrgbi+1) );
rs_puts("B :") ; show_value( *(xrgbi+2) );
rs_puts("IR:") ; show_value( *(xrgbi+3) );
}
crlf();
}
void setup()
{
/* initialize serial port */
Serial.begin(9600);
sindex = 0 ;
/* set initial state */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x01 ;
/* direction */
DDRB = 0xff ;
DDRC = 0xff ;
DDRD = 0xfe ;
/* clear flags */
tflag = OFF ;
eflag = OFF ;
uflag = OFF ;
gflag = OFF ;
/* resume previous state */
xcnt = EEPROM.read(SCODE_ADR);
if ( xcnt == 0xff ) {
scmd = 11 ;
EEPROM.write(SCODE_ADR,scmd);
} else {
scmd = xcnt ;
}
xcnt = EEPROM.read(SHOW_ADR);
if ( xcnt != OFF ) { gflag = ON ; }
/* initialize variables */
for ( xcnt = 0 ; xcnt < 4 ; xcnt++ ) {
*(xrgbi+xcnt) = 0 ;
}
xcnt = 0 ;
/* trigger period */
MsTimer2::set(NPER,update_trigger);
/* enable */
MsTimer2::start();
/* enable I2C bus interface */
Wire.begin();
}
void loop()
{
/* serial handling */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf();
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help() ; }
/* enable */
if ( cmd == 'E' ) { eflag = ON ; }
/* disable */
if ( cmd == 'I' ) { eflag = OFF ; }
/* one shot */
if ( cmd == 'C' ) {
/* get color values */
get_color();
/* show */
show_color(gflag);
}
/* write sensibility state */
if ( cmd == 'S' ) {
/* set default (selct LOW) */
scmd &= 0xf7 ;
/* set flag (HIGH or LOW) */
if ( *(sbuf+1) == '1' ) { scmd |= (1 << 3) ; }
/* store EEPROM */
store_param(0,scmd);
}
/* write exposure length */
if ( cmd == 'L' ) {
/* clear */
scmd &= 0xfc ;
/* generate code */
scmd |= ((*(sbuf+1) - '0') & 3);
/* store EEPROM */
store_param(1,scmd);
}
/* write only Green information */
if ( cmd == 'G' ) {
/* default */
gflag = OFF ;
/* judge */
if ( *(sbuf+1) == '1' ) { gflag = ON ; }
/* store */
store_param(2,gflag);
}
/* write mask */
if ( cmd == 'M' ) {
/* default */
mflag = OFF ;
/* judge */
if ( *(sbuf+1) == '1' ) { mflag = ON ; }
}
/* show status */
if ( cmd == 's' ) { show_yn(); }
}
/* timer handling */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* get color values */
get_color();
/* show */
if ( eflag == ON ) { show_color(gflag) ; }
}
}
/* 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 ;
}
}
}
Processingで情報の表示は、次のようにします。
ArduinoからRGBと輝度の情報は、5桁の数字で送信されます。
R、G、B、IRの文字列を探し出して、RGBの数字に分解すれば
バー表示に必要な数値に変換できそうです。
この処理には、Stringからcharに変換して対応しました。
stmp = trim(cport.readStringUntil('\n'));
char[] ss = stmp.toCharArray();
textSize(20);
text(stmp,20,40);
loop = rx = gx = bx = ix = 0 ;
for (char ch : ss) {
/* check entry */
if ( ch == ':' ) { loop++ ; }
/* calculate */
if ( isAcode(ch) == true ) {
if ( loop == 1 ) { rx = rx * 10 + (ch-'0') ; }
if ( loop == 2 ) { gx = gx * 10 + (ch-'0') ; }
if ( loop == 3 ) { bx = bx * 10 + (ch-'0') ; }
if ( loop == 4 ) { ix = ix * 10 + (ch-'0') ; }
}
}
もう少しうまい方法がありそうですが、確実に動くことが優先です。
RGBと輝度の値がわかれば、画面表示とバー表示の関数を作成します。
void show_values(int x,int y,int z,int u)
{
int sx = 20 ;
int sy = 120 ;
int offset = 30 ;
/* select size */
textSize(15) ;
/* write */
text("R :"+nf(x,5),sx,sy+offset*0);
text("G :"+nf(y,5),sx,sy+offset*1);
text("B :"+nf(z,5),sx,sy+offset*2);
text("IR:"+nf(u,5),sx,sy+offset*3);
}
void show_bars(int x,int y,int z,int u)
{
int rgbi = max(max(x,y),max(z,u));
int rate_r ;
int rate_g ;
int rate_b ;
int rate_i ;
int sx = 100 ;
int sy = 110 ;
int offset = 26 ;
/* calculate ratio */
rate_r = (int)( (x * 100.0) / rgbi ) ;
rate_g = (int)( (y * 100.0) / rgbi ) ;
rate_b = (int)( (z * 100.0) / rgbi ) ;
rate_i = (int)( (u * 100.0) / rgbi ) ;
/* show bar */
fill(255, 0, 0); rect(sx,sy+offset*0,rate_r,20);
fill( 0,255, 0); rect(sx,sy+offset*1,rate_g,20);
fill( 0, 0,255); rect(sx,sy+offset*2,rate_b,20);
fill(255,255,255); rect(sx,sy+offset*3,rate_i,20);
}
まとめると、次のようになります。
import processing.serial.*;
Serial cport;
PImage imgGet ;
PImage imgExecute ;
PImage imgIdle ;
PImage imgExit ;
int FRATE = 25 ;
String stmp ;
boolean scflag ;
int loop ;
int rx ;
int gx ;
int bx ;
int ix ;
boolean isRangeOk(int x,int bx,int ex)
{
boolean result ;
/* default */
result = false ;
/* judge */
if ( bx <= x && x <= ex ) { result = true ; }
return result ;
}
boolean isAcode(char x)
{
boolean result ;
/* default */
result = false ;
/* judge */
if ( x != 'R' && x != 'G' && x != 'B' &&
x != ':' && x != 'I' && x != ' ' ) {
result = true ;
}
return result ;
}
void show_values(int x,int y,int z,int u)
{
int sx = 20 ;
int sy = 120 ;
int offset = 30 ;
/* select size */
textSize(15) ;
/* write */
text("R :"+nf(x,5),sx,sy+offset*0);
text("G :"+nf(y,5),sx,sy+offset*1);
text("B :"+nf(z,5),sx,sy+offset*2);
text("IR:"+nf(u,5),sx,sy+offset*3);
}
void show_bars(int x,int y,int z,int u)
{
int rgbi = max(max(x,y),max(z,u)) ;
int rate_r ;
int rate_g ;
int rate_b ;
int rate_i ;
int sx = 100 ;
int sy = 110 ;
int offset = 26 ;
/* calculate ratio */
rate_r = (int)( (x * 100.0) / rgbi ) ;
rate_g = (int)( (y * 100.0) / rgbi ) ;
rate_b = (int)( (z * 100.0) / rgbi ) ;
rate_i = (int)( (u * 100.0) / rgbi ) ;
/* show bar */
fill(255, 0, 0); rect(sx,sy+offset*0,rate_r,20);
fill( 0,255, 0); rect(sx,sy+offset*1,rate_g,20);
fill( 0, 0,255); rect(sx,sy+offset*2,rate_b,20);
fill(255,255,255); rect(sx,sy+offset*3,rate_i,20);
}
void setup()
{
size(440,340);
/* title caption */
surface.setTitle("Test 04");
/* select framerate */
frameRate(FRATE);
/* select back ground color with BLACK */
background(0,0,0);
// シリアルポートのリスト取得
// println(Serial.list());
String arduinoPort = Serial.list()[4];
/* initialize serial port */
cport = new Serial(this,arduinoPort,9600);
cport.clear();
cport.bufferUntil('\n');
scflag = false ;
/* get image */
imgGet = loadImage("get.png");
imgExecute = loadImage("execute.png");
imgIdle = loadImage("idle.png");
imgExit = loadImage("exit.png");
}
void draw()
{
/* button */
image(imgGet , 20,300);
image(imgExecute, 80,300);
image(imgIdle ,140,300);
image(imgExit ,220,300);
/* serial receive */
if ( scflag == true ) {
scflag = false ;
background(0,0,0);
fill(255,255,255);
stmp = trim(cport.readStringUntil('\n'));
char[] ss = stmp.toCharArray();
textSize(20);
text(stmp,20,40);
loop = rx = gx = bx = ix = 0 ;
for (char ch : ss) {
/* check entry */
if ( ch == ':' ) { loop++ ; }
/* calculate */
if ( isAcode(ch) == true ) {
if ( loop == 1 ) { rx = rx * 10 + (ch-'0') ; }
if ( loop == 2 ) { gx = gx * 10 + (ch-'0') ; }
if ( loop == 3 ) { bx = bx * 10 + (ch-'0') ; }
if ( loop == 4 ) { ix = ix * 10 + (ch-'0') ; }
}
}
// print('\n');
// print(str(rx)+" "+str(gx)+" "+str(bx)+" "+str(ix));
print('\n');
/* show values */
show_values(rx,gx,bx,ix);
/* draw bars */
int rate_rgbi = max(max(rx,gx),max(bx,ix));
if ( rate_rgbi > 0 ) { show_bars(rx,gx,bx,ix); }
}
}
void mouseClicked()
{
if ( mouseButton == LEFT ) {
/* get */
if ( isRangeOk(mouseX, 20, 70) &&
isRangeOk(mouseY,300,320) ) {
/* debug */
println("Get");
/* send command */
cport.write('C');
cport.write('\r');
}
/* execute */
if ( isRangeOk(mouseX, 80,130) &&
isRangeOk(mouseY,300,320) ) {
/* debug */
println("Execute");
/* send command */
cport.write('E');
cport.write('\r');
}
/* idle */
if ( isRangeOk(mouseX,140,190) &&
isRangeOk(mouseY,300,320) ) {
/* debug */
println("Idle");
/* send command */
cport.write('I');
cport.write('\r');
}
/* exit */
if ( isRangeOk(mouseX,220,390) &&
isRangeOk(mouseY,300,320) ) {
/* send command */
cport.write('I');
cport.write('\r');
/* debug */
println("exit");
exit();
}
}
/* Exit */
if ( mouseButton == RIGHT ) {
/* send command */
cport.write('I');
cport.write('\r');
exit();
}
}
void serialEvent(Serial p)
{
scflag = true ;
}
このProcessingスケッチは、受信割込みを使っています。
受信バッファに、1レコード分のデータが格納されたなら
イベントフラグでdraw()の中にある、対応ブロックに通知
しています。
目次
前
次