目次

カラーセンサー情報取得4

 ArduinoにIICバスを2つ用意し、2個のカラーセンサーから
 情報取得するためのProcessingスケッチを考えます。

 1個のカラーセンサーの場合、次のように画面を構成していました。



 カラーセンサーは2個にするので、左右に並べて表示します。



 カラーセンサーには、次のパラメータ指定が可能です。

 感度、マスク指定は論理値で設定し、露光時間は
 1から4の整数値にします。
 これらを2個のセンサーを一緒に指定できるように
 します。



 3項目に相当するボタンを用意し、クリックすると
 キャプションの右に、現在の指定状態を表示します。

 ボタンは、クリッカブルマップで領域を指定すれば
 どの値になっているかを判定できます。

 クリッカブルマップによる領域指定を使うことに
 すると、各ボタンの絵を作成するだけになります。

 スケッチは、以下。

import processing.serial.*;

Serial cport;

PImage imgGet  ;
PImage imgExecute ;
PImage imgIdle ;
PImage imgExit ;
PImage imgSense ;
PImage imgXtime ;
PImage imgXmask ;

int FRATE = 25 ;

String stmp ;

boolean scflag ;

int loop ;
int rxa ;
int gxa ;
int bxa ;
int ixa ;
int rxb ;
int gxb ;
int bxb ;
int ixb ;

String xsense ;
String xtime ;
String xmask ;

boolean eflag ;
boolean oflag ;

PrintWriter outFN ;

boolean isRangeOk(int x,int bx,int ex)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( bx <= x && x <= ex ) { result = true ; }

  return result ;
}       

boolean isdigitx(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( '0' <= x && x <= '9' ) { result = true ; }

  return result ;
}

boolean isNcode(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( x == 'A' ) { result = true ; }
  if ( x == 'B' ) { result = true ; }
  if ( x == 'R' ) { result = true ; }
  if ( x == 'G' ) { result = true ; }
  if ( x == 'I' ) { result = true ; }
  if ( x == ':' ) { result = true ; }
  if ( x == ' ' ) { result = true ; }

  return result ;
}

boolean isNcode(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( isdigitx(x) && !isacode(x) ) {
    result = true ;
  }

  return result ;
}

void show_values(int x,int y,int z,int u,int wx)
{
  int sx = 20 ;
  int sy = 80 ;
  int lx ;
  int ly ;
  String msg_r ;
  String msg_g ;
  String msg_b ;
  String msg_ix ;
  int offset = 30 ;
  /* generate text */
  msg_r  = "AR :";
  msg_g  = "AG :";
  msg_b  = "AB :";
  msg_ix = "AIR:";
  if ( wx == 1 ) {
    msg_r  = "BR :";
    msg_g  = "BG :";
    msg_b  = "BB :";
    msg_ix = "BIR:";
  }
  msg_r  = msg_r  + nf(x,5) ;
  msg_g  = msg_g  + nf(y,5) ;
  msg_b  = msg_b  + nf(z,5) ;
  msg_ix = msg_ix + nf(u,5) ;
  /* set location */
  lx = sx ;
  ly = sy ;
  if ( wx == 1 ) { lx += 190 ; }
  /* show */
  textSize(15) ;
  text(msg_r ,lx,ly+offset*0);
  text(msg_g ,lx,ly+offset*1);
  text(msg_b ,lx,ly+offset*2);
  text(msg_ix,lx,ly+offset*3);
}

void show_bars(int x,int y,int z,int u,int wx)
{
  int rgbi ;
  int rate_r ;
  int rate_g ;
  int rate_b ;
  int rate_i ;
  int sx = 100 ;
  int sy = 70 ;
  int offset = 27 ;
  int lx ;
  int ly ;
  /* calculate ratio */
  rgbi = max(max(x,y),max(z,u)) ;
  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 ) ;
  /* calcualte location */
  lx = sx ;
  ly = sy ;
  if ( wx == 1 ) { lx = 290 ; }
  /* show bar */
  fill(255,  0,  0); rect(lx,ly+offset*0,rate_r,20);
  fill(  0,255,  0); rect(lx,ly+offset*1,rate_g,20);
  fill(  0,  0,255); rect(lx,ly+offset*2,rate_b,20);
  fill(255,255,255); rect(lx,ly+offset*3,rate_i,20);
}

void show_btn()
{
  image(imgGet    , 20,300);
  image(imgExecute, 80,300);
  image(imgIdle   ,140,300);
  image(imgExit   ,220,300);
  image(imgSense  ,300,200);
  image(imgXtime  ,300,240);
  image(imgXmask  ,300,280);
}

void show_caption_p()
{
  /* white */
  fill(255,255,255);
  /* size */
  textSize(12);
  /* caption */
  text("Sensivility",300,196);
  text("Exposure",300,236);
  text("Mask",300,276);
}

void clear_area()
{
  /* black */
  fill(0,0,0);
  /* clear status area */
  rect(390,200,100,100);
}

void show_caption()
{
  clear_area();
  /* white */
  fill(255,255,255);
  /* size */
  textSize(12);
  /* status */
  text(xsense,400,214);
  text(xtime ,400,254);
  text(xmask ,400,294);
}

void send_sense_cmd(boolean x)
{
  cport.write('S'); 
  if ( x ) { cport.write('1'); }
  else     { cport.write('0'); }
  cport.write('\r');
}

void send_exposure_cmd(int x)
{
  if ( 0 < x && x < 5 ) {
    cport.write('L');  
    if ( x == 1 ) { cport.write('1'); }
    if ( x == 2 ) { cport.write('2'); }
    if ( x == 3 ) { cport.write('3'); }
    if ( x == 4 ) { cport.write('4'); }
    cport.write('\r');
  }
}

void send_mask_cmd(boolean x)
{
  cport.write('M'); 
  if ( x ) { cport.write('1'); }
  else     { cport.write('0'); }
  cport.write('\r');
}

void store_status()
{
  String stmp ;
  /* clear */
  stmp = "" ;
  /* sensivility */
  if ( xsense == "HIGH" ) { stmp += "1" ; }
  else                    { stmp += "0" ; }
  /* exposure time */
  if ( xtime == "1" ) { stmp += "1" ; }
  if ( xtime == "2" ) { stmp += "2" ; }
  if ( xtime == "3" ) { stmp += "3" ; }
  if ( xtime == "4" ) { stmp += "4" ; }
  /* mask */
  if ( xmask == "YES" ) { stmp += "1" ; }
  else                  { stmp += "0" ; }
  /* file handling */
  outFN = createWriter("istatus.txt");
  outFN.println(stmp);
  outFN.close();
}

void setup()
{
  size(440,340);
  /* title caption */
  surface.setTitle("Test 05");
  /* select framerate */
  frameRate(FRATE);
  /* select back ground color with BLACK */
  background(0,0,0);
  //show serial port list (0:COM1 , 1:COM2 ... )
  //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");
  imgSense   = loadImage("sense.png");
  imgXtime   = loadImage("xtime.png");
  imgXmask   = loadImage("xmask.png");
  /* set caption */
  String[] xline = loadStrings("istatus.txt");
  char[] ss = xline[0].toCharArray();
  /* set status */
  xsense = "LOW" ;
  if ( ss[0] == '1' ) { xsense = "HIGH" ; }
  xtime = "1" ;
  if ( ss[1] == '2' ) { xtime = "2" ; }
  if ( ss[1] == '3' ) { xtime = "3" ; }
  if ( ss[1] == '4' ) { xtime = "4" ; }
  xmask  = "NO" ;
  if ( ss[2] == '1' ) { xmask = "YES" ; }
  /* first one shot */
  oflag = true ;
}

void draw()
{
  /* first one shot */
  if ( oflag ) {
    oflag = false ;
    /* sensivility */
    if ( xsense == "HIGH" ) { send_sense_cmd(true); }
    else                    { send_sense_cmd(false); } 
    /* exposure time */
    send_exposure_cmd(int(xtime));
    /* mask */
    if ( xmask == "YES" ) { send_mask_cmd(true); }
    else                  { send_mask_cmd(false); }
  }
  /* button */
  show_btn();
  /* caption */
  show_caption_p();
  show_caption();
  /* serial receive */
  if ( scflag == true ) {
    scflag = false ;
    /* check */
    stmp = trim(cport.readStringUntil('\n'));
    /* separate */
    char[] ss = stmp.toCharArray();
    loop = stmp.indexOf("BR :");
    /* judge */
    eflag = true ;
    if ( loop < 40 ) { eflag = false ; }
    /* show */
    if ( eflag ) {
      /* clear area */
      background(0,0,0);
      /* show */
      textSize(20);
      text(stmp.substring(0,loop-1),20,40);
      text(stmp.substring(loop,stmp.length()),20,60);
      /* clear */
      loop = 0 ; 
      rxa = gxa = bxa = ixa = 0 ;
      rxb = gxb = bxb = ixb = 0 ;
      for (char ch : ss) {
        /* check entry */
        if ( ch == ':' ) { loop++ ; }
        /* calculate */
        if ( isNcode(ch) == true ) {
          if ( loop == 1 ) { rxa = rxa * 10 + (ch-'0') ; }
          if ( loop == 2 ) { gxa = gxa * 10 + (ch-'0') ; }
          if ( loop == 3 ) { bxa = bxa * 10 + (ch-'0') ; }
          if ( loop == 4 ) { ixa = ixa * 10 + (ch-'0') ; }
          if ( loop == 5 ) { rxb = rxb * 10 + (ch-'0') ; }
          if ( loop == 6 ) { gxb = gxb * 10 + (ch-'0') ; }
          if ( loop == 7 ) { bxb = bxb * 10 + (ch-'0') ; }
          if ( loop == 8 ) { ixb = ixb * 10 + (ch-'0') ; }
        }
      }
      print('\n');
      /* clear information */
      fill(0,0,0);
      rect(10,70,300,200);
      fill(255,255,255);
      /* show values */
      show_values(rxa,gxa,bxa,ixa,0);
      show_values(rxb,gxb,bxb,ixb,1);
      /* draw bars */
      int rate_rgbi ;
      rate_rgbi = max(max(rxa,gxa),max(bxa,ixa));
      if ( rate_rgbi > 0 ) { show_bars(rxa,gxa,bxa,ixa,0); }
      rate_rgbi = max(max(rxb,gxb),max(bxb,ixb));
      if ( rate_rgbi > 0 ) { show_bars(rxb,gxb,bxb,ixb,1); }
    } 
  }
}

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');
      /* status */
      store_status();
      exit();
    }
    /* sensivility (HIGH) */
    if ( isRangeOk(mouseX,301,339) &&
         isRangeOk(mouseY,200,220)    ) {
      /* send command */
      send_sense_cmd(true);
      /* update */
      xsense = "HIGH" ;
    }
    /* sensivility (LOW) */
    if ( isRangeOk(mouseX,341,379) &&
         isRangeOk(mouseY,200,220)    ) {
      /* send command */
      send_sense_cmd(false);
      /* update */
      xsense = "LOW" ;
    }
    /* xtime (1) */
    if ( isRangeOk(mouseX,301,319) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(1);
      /* update */
      xtime = "1" ;
    }
    /* xtime (2) */
    if ( isRangeOk(mouseX,321,339) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(2);
      /* update */
      xtime = "2" ;
    }
    /* xtime (3) */
    if ( isRangeOk(mouseX,341,359) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(3);
      /* update */
      xtime = "3" ;
    }
    /* xtime (4) */
    if ( isRangeOk(mouseX,361,379) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(4);
      /* update */
      xtime = "4" ;
    }
    /* xmask (YES) */
    if ( isRangeOk(mouseX,301,339) &&
         isRangeOk(mouseY,280,300)    ) {
      /* send command */
      send_mask_cmd(true);
      /* update */
      xmask = "YES" ;
    }
    /* xmask (NO) */
    if ( isRangeOk(mouseX,341,379) &&
         isRangeOk(mouseY,280,300)    ) {
      /* send command */
      send_mask_cmd(false);
      /* update */
      xmask = "NO" ;
    }
  } 
  /* Exit */
  if ( mouseButton == RIGHT ) {
    /* send command */
    cport.write('I'); 
    cport.write('\r');
    store_status();
    exit();
  } 
}

void serialEvent(Serial p)
{
  scflag = true ;
}

 表示は、次のようになります。



 スケッチの内容に関し、次の5項目に分けて説明します。

 通信処理

  通信処理は、受信割込みと文字列処理の2ブロックで構成します。

  受信割込みは単純で、'\n'が来たならイベントフラグscflagをセットし
  関数draw()に通知。

    void serialEvent(Serial p)
    {
      scflag = true ;
    }

  関数draw()の中で、イベントフラグscflagによる通知で
  受信バッファに保存されている情報を扱います。

  受信バッファに40文字以上保存されていた場合だけ
  文字列を処理します。


  if ( scflag == true ) {
    scflag = false ;
    /* check */
    stmp = trim(cport.readStringUntil('\n'));
    /* separate */
    char[] ss = stmp.toCharArray();
    loop = stmp.indexOf("BR :");
    /* judge */
    eflag = true ;
    if ( loop < 40 ) { eflag = false ; }
    /* show */
    if ( eflag ) {
      /* clear area */
      background(0,0,0);
      /* show */
      textSize(20);
      text(stmp.substring(0,loop-1),20,40);
      text(stmp.substring(loop,stmp.length()),20,60);
      /* clear */
      loop = 0 ; 
      rxa = gxa = bxa = ixa = 0 ;
      rxb = gxb = bxb = ixb = 0 ;
      for (char ch : ss) {
        /* check entry */
        if ( ch == ':' ) { loop++ ; }
        /* calculate */
        if ( isNcode(ch) == true ) {
          if ( loop == 1 ) { rxa = rxa * 10 + (ch-'0') ; }
          if ( loop == 2 ) { gxa = gxa * 10 + (ch-'0') ; }
          if ( loop == 3 ) { bxa = bxa * 10 + (ch-'0') ; }
          if ( loop == 4 ) { ixa = ixa * 10 + (ch-'0') ; }
          if ( loop == 5 ) { rxb = rxb * 10 + (ch-'0') ; }
          if ( loop == 6 ) { gxb = gxb * 10 + (ch-'0') ; }
          if ( loop == 7 ) { bxb = bxb * 10 + (ch-'0') ; }
          if ( loop == 8 ) { ixb = ixb * 10 + (ch-'0') ; }
        }
      }
      print('\n');
      /* clear information */
      fill(0,0,0);
      rect(10,70,300,200);
      fill(255,255,255);
      /* show values */
      show_values(rxa,gxa,bxa,ixa,0);
      show_values(rxb,gxb,bxb,ixb,1);
      /* draw bars */
      int rate_rgbi ;
      rate_rgbi = max(max(rxa,gxa),max(bxa,ixa));
      if ( rate_rgbi > 0 ) { show_bars(rxa,gxa,bxa,ixa,0); }
      rate_rgbi = max(max(rxb,gxb),max(bxb,ixb));
      if ( rate_rgbi > 0 ) { show_bars(rxb,gxb,bxb,ixb,1); }
    } 
  }


  String型からchar型に文字列を変換し、チャネルA、Bの
  2行に分割します。それぞれのRGBおよびIR情報から各色の
  数値に分割変換します。数値に変換するのは、バーを表示
  するときに、要求されるからです。

  RGBおよびIR情報は、「:」で区切られているので、何度目かの
  出現かを判断し、文字列を数値に変換します。

  文字列を1文字ずつスキャンしていくのに、for文を使っています。
  for文を使うと、1文字ずつのバラけた状態になるので、数字か英字の
  どちらかを判定して、数字だったなら、10進数になるように計算。

  数字かスキップする英字かを判断するため、専用関数を定義しています。

boolean isdigitx(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( '0' <= x && x <= '9' ) { result = true ; }

  return result ;
}

boolean isacode(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( x == 'A' ) { result = true ; }
  if ( x == 'B' ) { result = true ; }
  if ( x == 'R' ) { result = true ; }
  if ( x == 'G' ) { result = true ; }
  if ( x == 'I' ) { result = true ; }
  if ( x == ':' ) { result = true ; }
  if ( x == ' ' ) { result = true ; }

  return result ;
}

boolean isNcode(char x)
{
  boolean result ;
  /* default */
  result = false ;
  /* judge */
  if ( isdigitx(x) && !isacode(x) ) {
    result = true ;
  }

  return result ;
}

 ボタン操作

  ボタン操作は、クリッカブルマップ処理をしています。

  クリッカブルマップ処理は、マウスカーソルがボタンアイコンの
  占有する範囲にあるかを判定して、その範囲なら該当する動作を
  実行します。

  ボタンは、Arduinoの動作を指定する類とそれ以外になりますが
  Arduinoの動作を指定するコマンドと1対1に対応する処理は
  以下。

    /* sensivility (HIGH) */
    if ( isRangeOk(mouseX,301,339) &&
         isRangeOk(mouseY,200,220)    ) {
      /* send command */
      send_sense_cmd(true);
      /* update */
      xsense = "HIGH" ;
    }
    /* sensivility (LOW) */
    if ( isRangeOk(mouseX,341,379) &&
         isRangeOk(mouseY,200,220)    ) {
      /* send command */
      send_sense_cmd(false);
      /* update */
      xsense = "LOW" ;
    }
    /* xtime (1) */
    if ( isRangeOk(mouseX,301,319) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(1);
      /* update */
      xtime = "1" ;
    }
    /* xtime (2) */
    if ( isRangeOk(mouseX,321,339) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(2);
      /* update */
      xtime = "2" ;
    }
    /* xtime (3) */
    if ( isRangeOk(mouseX,341,359) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(3);
      /* update */
      xtime = "3" ;
    }
    /* xtime (4) */
    if ( isRangeOk(mouseX,361,379) &&
         isRangeOk(mouseY,240,260)    ) {
      /* send command */
      send_exposure_cmd(4);
      /* update */
      xtime = "4" ;
    }
    /* xmask (YES) */
    if ( isRangeOk(mouseX,301,339) &&
         isRangeOk(mouseY,280,300)    ) {
      /* send command */
      send_mask_cmd(true);
      /* update */
      xmask = "YES" ;
    }
    /* xmask (NO) */
    if ( isRangeOk(mouseX,341,379) &&
         isRangeOk(mouseY,280,300)    ) {
      /* send command */
      send_mask_cmd(false);
      /* update */
      xmask = "NO" ;
    }

  Arduinoに与えるコマンドを実現する関数は、以下のように定義しました。

    void send_sense_cmd(boolean x)
    {
      cport.write('S'); 
      if ( x ) { cport.write('1'); }
      else     { cport.write('0'); }
      cport.write('\r');
    }

    void send_exposure_cmd(int x)
    {
      if ( 0 < x && x < 5 ) {
        cport.write('L');  
        if ( x == 1 ) { cport.write('1'); }
        if ( x == 2 ) { cport.write('2'); }
        if ( x == 3 ) { cport.write('3'); }
        if ( x == 4 ) { cport.write('4'); }
        cport.write('\r');
      }
    }

    void send_mask_cmd(boolean x)
    {
      cport.write('M'); 
      if ( x ) { cport.write('1'); }
      else     { cport.write('0'); }
      cport.write('\r');
    }

 テキスト描画

  テキスト描画は、一度画面に出力すると変更なしの場合と
  状況により変更して再表示する場合があります。
  どちらにも対応できるように、関数を分割して定義しました。

    void show_values(int x,int y,int z,int u,int wx)
    {
      int sx = 20 ;
      int sy = 80 ;
      int lx ;
      int ly ;
      String msg_r ;
      String msg_g ;
      String msg_b ;
      String msg_ix ;
      int offset = 30 ;
      /* generate text */
      msg_r  = "AR :";
      msg_g  = "AG :";
      msg_b  = "AB :";
      msg_ix = "AIR:";
      if ( wx == 1 ) {
        msg_r  = "BR :";
        msg_g  = "BG :";
        msg_b  = "BB :";
        msg_ix = "BIR:";
      }
      msg_r  = msg_r  + nf(x,5) ;
      msg_g  = msg_g  + nf(y,5) ;
      msg_b  = msg_b  + nf(z,5) ;
      msg_ix = msg_ix + nf(u,5) ;
      /* set location */
      lx = sx ;
      ly = sy ;
      if ( wx == 1 ) { lx += 190 ; }
      /* show */
      textSize(15) ;
      text(msg_r ,lx,ly+offset*0);
      text(msg_g ,lx,ly+offset*1);
      text(msg_b ,lx,ly+offset*2);
      text(msg_ix,lx,ly+offset*3);
    }

    void show_caption_p()
    {
      /* white */
      fill(255,255,255);
      /* size */
      textSize(12);
      /* caption */
      text("Sensivility",300,196);
      text("Exposure",300,236);
      text("Mask",300,276);
    }

    void clear_area()
    {
      /* black */
      fill(0,0,0);
      /* clear status area */
      rect(390,200,100,100);
    }

    void show_caption()
    {
      clear_area();
      /* white */
      fill(255,255,255);
      /* size */
      textSize(12);
      /* status */
      text(xsense,400,214);
      text(xtime ,400,254);
      text(xmask ,400,294);
    }

    関数show_valuesは、RGBおよびIRの数値と2チャネルのどちらかを
  指定すると、画面に各色の情報を数字で表示します。

  関数show_caption_pとshow_captionは、一度画面表示すると変更が
  ない文字列を表示します。

  関数clear_areaは、過去に画面に表示した数字を、矩形領域の
  黒による塗り潰しで消します。

 バー描画

  バー描画は、通信処理で生成した数値情報を
  関数に与えることで、バーとします。

    関数には、RGBおよびIRの数値と2チャネルのどちらを
  描画するのかをパラメータとして与えます。

    void show_bars(int x,int y,int z,int u,int wx)
    {
      int rgbi ;
      int rate_r ;
      int rate_g ;
      int rate_b ;
      int rate_i ;
      int sx = 100 ;
      int sy = 70 ;
      int offset = 27 ;
      int lx ;
      int ly ;
      /* calculate ratio */
      rgbi = max(max(x,y),max(z,u)) ;
      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 ) ;
      /* calcualte location */
      lx = sx ;
      ly = sy ;
      if ( wx == 1 ) { lx = 290 ; }
      /* show bar */
      fill(255,  0,  0); rect(lx,ly+offset*0,rate_r,20);
      fill(  0,255,  0); rect(lx,ly+offset*1,rate_g,20);
      fill(  0,  0,255); rect(lx,ly+offset*2,rate_b,20);
      fill(255,255,255); rect(lx,ly+offset*3,rate_i,20);
    }

  関数内で、各色の最大値を決めておきます。
  最大値をもつ色は、200ピクセルのバーにしておき、他の色は
  その何分の1なのかでバーの長さを指定します。

 ファイル処理

  ファイル内の情報は、カラーセンサーの次の項目を指定します。

  テキストファイルには、感度とマスク指定を1か0の論理値で
  露光時間コードは、1から4の自然数として格納します。

  各指定の並びは、感度、露光時間コード、マスク指定の順で
  1行にまとめます。

  テキストファイル名は、「istatus.txt」としています。

  ファイルから情報を取得する場合は、関数setupの中に
  次の処理を書いて対応。

    xsense = "LOW" ;
    if ( ss[0] == '1' ) { xsense = "HIGH" ; }
    xtime = "1" ;
    if ( ss[1] == '2' ) { xtime = "1" ; }
    if ( ss[1] == '3' ) { xtime = "2" ; }
    if ( ss[1] == '4' ) { xtime = "3" ; }
    xmask  = "NO" ;
    if ( ss[2] == '1' ) { xmask = "YES" ; }
    /* first one shot */
    oflag = true ;

  ファイルへ情報を保存する場合、専用関数store_statusを使います。

    void store_status()
    {
      String stmp ;
      /* clear */
      stmp = "" ;
      /* sensivility */
      if ( xsense == "HIGH" ) { stmp += "1" ; }
      else                    { stmp += "0" ; }
      /* exposure time */
      if ( xtime == "1" ) { stmp += "1" ; }
      if ( xtime == "2" ) { stmp += "2" ; }
      if ( xtime == "3" ) { stmp += "3" ; }
      if ( xtime == "4" ) { stmp += "4" ; }
      /* mask */
      if ( xmask == "YES" ) { stmp += "1" ; }
      else                  { stmp += "0" ; }
      /* file handling */
      outFN = createWriter("istatus.txt");
      outFN.println(stmp);
      outFN.close();
    }

  関数store_statusを呼び出すのは、スケッチを終了する
  場合に限定しています。

  ファイルから情報を読込んだときに、Arduinoにコマンドを
  出力するため、1回だけコマンドを送信するようにoflagを
  使い、関数drawに通知。

  関数draw内では、通知フラグoflagを判断してコマンドを
  1回だけ発行するように定義します。

    if ( oflag ) {
      oflag = false ;
      /* sensivility */
      if ( xsense == "HIGH" ) { send_sense_cmd(true); }
      else                    { send_sense_cmd(false); }
      /* exposure time */
      send_exposure_cmd(int(xtime));
      /* mask */
      if ( xmask == "YES" ) { send_mask_cmd(true); }
      else                  { send_mask_cmd(false); }
    }

 ここから先は、備忘録としての記述です。

 Processingは、Javaの言語仕様に影響を受けているので
 文字列処理はStringオブジェクトを使うのが基本。

 Stringオブジェクトは、文字列を簡単に扱うことを考えて
 設計されています。char型で充分な処に、オブジェクトを
 使うのは面倒なので、Arduinoが送信してきた文字情報を
 char型に変換して扱います。

 String型からchar型の変換は、メソッドtoCharArrayに
 任せておき、char型になった文字列を、スキャンして
 数字から数値に変換しました。

      loop = 0 ; 
      rxa = gxa = bxa = ixa = 0 ;
      rxb = gxb = bxb = ixb = 0 ;
      for (char ch : ss) {
        /* check entry */
        if ( ch == ':' ) { loop++ ; }
        /* calculate */
        if ( isNcode(ch) == true ) {
          if ( loop == 1 ) { rxa = rxa * 10 + (ch-'0') ; }
          if ( loop == 2 ) { gxa = gxa * 10 + (ch-'0') ; }
          if ( loop == 3 ) { bxa = bxa * 10 + (ch-'0') ; }
          if ( loop == 4 ) { ixa = ixa * 10 + (ch-'0') ; }
          if ( loop == 5 ) { rxb = rxb * 10 + (ch-'0') ; }
          if ( loop == 6 ) { gxb = gxb * 10 + (ch-'0') ; }
          if ( loop == 7 ) { bxb = bxb * 10 + (ch-'0') ; }
          if ( loop == 8 ) { ixb = ixb * 10 + (ch-'0') ; }
        }
      }

 RGBおよびIR情報を表現する数字には、区別しやすい
 ように、IDコード(AR、BRなど)がついています。

 IDコードの次に数字の開始を意味するマーカー「:」が
 あるので、マーカーを見つけたなら、最大5文字の数字
 を数値に変換するカラクリを作りました。

 数字であれば数値に変換し、10進数の数値情報を
 組み上げることを8回繰り返します。

 ひとつの色を表現する文字列は最大5文字で、数字と
 スペースで構成されているので、スペースをスキップ
 しています。

 forでは、文字列を1文字ごとに分割してしまうので
 スキップする文字は、スペースだけではなく、以下の
 文字としてあります。
   'A' 'B' 'R' 'G' 'I' ':'

 スキップする文字と数字の区別ができれば、色情報の
 文字列を10進数で計算するため、重みの10を乗算する
 処理と1桁の数字から数値に変換する処理を組合わせ
 色情報の数値に仕立てます。


目次

inserted by FC2 system