目次

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

 浜松ホトニクスのI2Cバスインタフェースカラーセンサーを
 2個、Arduinoに接続してみます。



 基板に回路を半田付けすると、次のようになります。



 デジタルインタフェースがあるので、その2ビットを利用して
 動作させることも可能ですが、AVRチップ内蔵ハードウエアを
 利用して信頼度を確保します。

 アナログスイッチを利用して、2個のカラーセンサーとの
 接続を切り替えます。しかし、この方法では、うまく動作
 しませんでした。

 カラーセンサーは3.3Vで動作するため、プルアップしても
 Arduinoが5V動作が前提であるため、電圧のレベル変換が
 必要でした。

 秋月電子で販売されている双方向電圧レベル変換モジュール
 を利用して、対応しました。



 このモジュールを利用して動作確認するために
 作成したスケッチは、以下。

#include <MsTimer2.h>
#include <EEPROM.h>

#define OFF 0
#define ON  OFF+1

#define MSCL_BIT 3
#define MSDA_BIT 2

#define MASK80  0x80
#define IIC_CNT 32

#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 m_iic_wait(void)
{
  byte i ;
  /* wait */
  for ( i = 0 ; i < IIC_CNT ; i++ ) ;
}

void m_iic_scl(byte x)
{
  /* impress */
  if ( x ) { PORTC |=  (1 << MSCL_BIT) ; }
  else     { PORTC &= ~(1 << MSCL_BIT) ; }
  /* delay */
  m_iic_wait();
}

void m_iic_start(void)
{
  /* both H */
  PORTC |= (3 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SDA */
  PORTC &= ~(1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SCL */
  PORTC &= ~(1 << MSCL_BIT) ;
}

void m_iic_stop(void)
{
  /* set level */
  PORTC |=  (1 << MSCL_BIT) ;
  PORTC &= ~(1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 1 -> SDA */
  PORTC |= (1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
}

byte m_iic_write(byte x)
{
  byte i   ;
  byte tmp ;
  /* load raw data */
  tmp = x ;
  /* transfer data with write code */
  for ( i = 0 ; i < 8 ; i++ ) {
    /* send bit datum */
    PORTC &= ~(1 << MSDA_BIT) ;
    if ( tmp & MASK80 ) { PORTC |= (1 << MSDA_BIT) ; }
    /* 1 -> SCL */
    m_iic_scl(ON);
    /* shift */
    tmp <<= 1 ;
    /* 0 -> SCL */
    m_iic_scl(OFF);
  }
  PORTC &= ~(1 << MSDA_BIT) ;
  /* change inupt */
  DDRC  &= ~(1 << MSDA_BIT) ;
  /* 1 -> SCL */
  m_iic_scl(ON);
  /* get acknowledge */
  tmp = (PINC & (1 << MSDA_BIT)) >> 2 ;
  /* 0 -> SCL */
  m_iic_scl(OFF);
  /* change output */
  DDRC |= (1 << MSDA_BIT) ;

  return tmp ;
}

byte m_iic_read(byte x)
{
  byte i;
  byte result ;
  /* change inupt */
  PORTC &= ~(1 << MSDA_BIT) ;
  DDRC  &= ~(1 << MSDA_BIT) ;
  /* default */
  result = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    /* shift */
    result <<= 1 ;
    /* 1 -> SCL */
    m_iic_scl(ON);
    /* get bit datum */
    if ( PINC & (1 << MSDA_BIT) ) { result |= ON ; } 
    /* 0 -> SCL */
    m_iic_scl(OFF);
  }
  /* change output */
  DDRC |= (1 << MSDA_BIT) ;
  if ( x ) { PORTC |=  (1 << MSDA_BIT); }
  else     { PORTC &= ~(1 << MSDA_BIT); }
  /* 1 -> SCL */
  m_iic_scl(ON);
  /* 0 -> SCL */
  m_iic_scl(OFF);

  return result ;
}

void get_color()
{
  byte i ;
  byte j ;
  word tmp ;
  byte xx[8] ;
  /*
    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; }
  /* */
  j = DEVICE_ID ;
  j <<= 1 ;
  j &= 0xFE ;
  /* initialize */
  m_iic_start();
  m_iic_write(j);
  m_iic_write(CONTROL_REG);
  m_iic_write(0x83);
  m_iic_start();
  m_iic_write(j);
  m_iic_write(CONTROL_REG);
  /* set High or Low and exposure length */
  m_iic_write(0x03);
  m_iic_stop();
  /* wait */
  delay( tmp ) ;
  /* read */
  m_iic_start();
  m_iic_write(j);
  m_iic_write(0x03);
  m_iic_start();
  m_iic_write(j | ON);
  /* get */
  j = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    if ( i == 7 ) { j = 1 ; }
    *(xx+i) = m_iic_read(j);
  }
  /* stop */
  m_iic_stop();
  /* store */
  for ( i = 0 ; i < 4 ; i++ ) {
    j = (i << 1);
    tmp = *(xx+j) ;
    tmp <<= 8 ; 
    tmp |= *(xx+j+1) ;
    *(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 = 0x0C ;
  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 */
  xcnt = 0 ;
  for ( xcnt = 0 ; xcnt < 4 ; xcnt++ ) { *(xrgbi+xcnt) = 0 ; }
  /* trigger period */
  MsTimer2::set(NPER,update_trigger);
  /* enable */ 
  MsTimer2::start(); 
}

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 ;
    }
  }
}

 Arduinoでは、A5、A4にSCL、SDAがアサインされています。
 汎用I/OでIICバスの処理を実現するため、専用関数を5種
 ほど用意して対応しました。

 IICのインタフェースは、次の項目を実現する関数の定義を
 考えました。

 6種の関数を定義できますが、カラーセンサーを扱うのに
 すべての関数が必要かをデータシートを使って確認します。
 タイミングチャートを見てみます。



 タイミングチャートからわかることを見ていきます。

 8ビットをリードする場合、IICバスマスターから
 acknowledgeを与えますが、1か0かを指定する時
 があります。

 8ビットをライトする場合、IICバススレーブから
 必ずacknowledgeの0を確認しています。

 ArduinoのポートCのA5、A4は、ライブラリで処理する
 として、A3、A2にSCL、SDAを割り当てて、必要な関数
 を定義します。

 5種類の関数を定義していきます。

 start condtion

  start condtionは、次のタイミングチャートに従い
  SCLが'H'のときに、SDAを'H'から'L'に変化させます。



  SCL、SDAをともに'H'にした後、SDAを'L'にします。
  さらにSCLを'L'にして終了です。

    void m_iic_start(void)
    {
      /* both H */
      PORTC |= (3 << MSDA_BIT) ;
      /* delay */
      m_iic_wait();
      /* 0 -> SDA */
      PORTC &= ~(1 << MSDA_BIT) ;
      /* delay */
      m_iic_wait();
      /* 0 -> SCL */
      PORTC &= ~(1 << MSCL_BIT) ;
    }

 IICバス用ディレイ

  SCL、SDAを変化させたときには、少しの間
  待ち時間を入れた方が、動作が安定します。
  ディレイを定義します。

    #define IIC_CNT 32

    void m_iic_wait(void)
    {
      byte i ;
      /* wait */
      for ( i = 0 ; i < IIC_CNT ; i++ ) ;
    }

 stop condtion

  stop condtionは、次のタイミングチャートに従い
  SCLが'H'のときに、SDAを'L'から'H'に変化させます。



  SCL、SDAをともに'L'にした後、SDAを'H'にします。
  さらにSCLを'H'にして終了です。

    void m_iic_stop(void)
    {
      /* set level */
      PORTC |=  (1 << MSCL_BIT) ;
      PORTC &= ~(1 << MSDA_BIT) ;
      /* delay */
      m_iic_wait();
      /* 1 -> SDA */
      PORTC |= (1 << MSDA_BIT) ;
      /* delay */
      m_iic_wait();
    }

 write 1byte with acknowledge

  タイミングチャートを確認します。



  SCL、SDAを利用して、8ビット分のデータを転送後
  スレーブの出力する'L'を確認します。

    byte m_iic_write(byte x)
    {
      byte i   ;
      byte tmp ;
      /* load raw data */
      tmp = x ;
      /* transfer data with write code */
      for ( i = 0 ; i < 8 ; i++ ) {
        /* send bit datum */
        PORTC &= ~(1 << MSDA_BIT) ;
        if ( tmp & MASK80 ) { PORTC |= (1 << MSDA_BIT) ; }
        /* 1 -> SCL */
        m_iic_scl(ON);
        /* shift */
        tmp <<= 1 ;
        /* 0 -> SCL */
        m_iic_scl(OFF);
      }
      PORTC &= ~(1 << MSDA_BIT) ;
      /* change inupt */
      DDRC  &= ~(1 << MSDA_BIT) ;
      /* 1 -> SCL */
      m_iic_scl(ON);
      /* get acknowledge */
      tmp = (PINC & (1 << MSDA_BIT)) >> 2 ;
      /* 0 -> SCL */
      m_iic_scl(OFF);
      /* change output */
      DDRC |= (1 << MSDA_BIT) ;

      return tmp ;
    }

 SCLレベル指定と遅延

  SCLは、H、Lを頻繁に変えるときがあり、さらに
  パルス幅も必要なので、論理レベルを指定する
  関数を定義しておきます。

    void m_iic_scl(byte x)
    {
      /* impress */
      if ( x ) { PORTC |=  (1 << MSCL_BIT) ; }
      else     { PORTC &= ~(1 << MSCL_BIT) ; }
      /* delay */
      m_iic_wait();
    }

 read 1byte with acknowledge

  SDAを入力に設定して、SCLでパルスを与え8ビット分のデータを
  リードします。さらに、acknowledgeを与えます。

    byte m_iic_read(byte x)
    {
      byte i;
      byte result ;
      /* change inupt */
      PORTC &= ~(1 << MSDA_BIT) ;
      DDRC  &= ~(1 << MSDA_BIT) ;
      /* default */
      result = 0 ;
      for ( i = 0 ; i < 8 ; i++ ) {
        /* shift */
        result <<= 1 ;
        /* 1 -> SCL */
        m_iic_scl(ON);
        /* get bit datum */
        if ( PINC & (1 << MSDA_BIT) ) { result |= ON ; } 
        /* 0 -> SCL */
        m_iic_scl(OFF);
      }
      /* change output */
      DDRC |= (1 << MSDA_BIT) ;
      if ( x ) { PORTC |=  (1 << MSDA_BIT); }
      else     { PORTC &= ~(1 << MSDA_BIT); }
      /* 1 -> SCL */
      m_iic_scl(ON);
      /* 0 -> SCL */
      m_iic_scl(OFF);

      return result ;
    }

 初期状態設定

  IICバスをまったく利用しない場合は、SCL、SDAは
  ともに'H'になります。これをsetup()の中で設定
  します。

    PORTC = 0x0C ;

 利用する関数を定義できたので、処理シーケンスを
 考えます。

 データシートでは、次のように処理シーケンスを規定。



 シーケンスを3処理に分割し、3処理を詳細に見て
 Arduinoスケッチで使うコードを決めていきます。

 initialize

  初期化あるいはフォーマットと呼ばれる処理で
  センター感度や変換に必要な時間を決めます。

start condition    m_iic_start();
send ID(0x2A+'0')  m_iic_write((0x2a << 1));
send 0x00          m_iic_write(0x00);
send 0x84          m_iic_write(0x84);
start condition    m_iic_start();
send ID(0x2A+'0')  m_iic_write((0x2a << 1));
send 0x00          m_iic_write(0x00);
send 0x04          m_iic_write(0x04);
stop condition     m_iic_stop();

 wait

  センサーがR、G、Bおよび輝度の情報を取得するには
  時間がかかります。Arduinoのライブラリを使った時
  に使った計算式で、WAITの時間を決めます。

  /*
    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; }

  変数scmdでは、センサーの感度を決める場合に
  指定するので、それに沿った値を計算して代入
  します。

 read

  センサーからの情報取得なので、規定されている
  シーケンスを見て、動作を記述します。

start condition            m_iic_start();
send ID(0x2A+'0')          m_iic_write((0x2a << 1));
send 0x03                  m_iic_write(0x03);
start condition            m_iic_start();
send ID(0x2A+'1')          m_iic_write((0x2a << 1) | ON);
read upper data(red)       rx = m_iic_read(0); rx <<= 8 ;
read lower data(red)       rx |= m_iic_read(0);
read upper data(green)     gx = m_iic_read(0); gx <<= 8 ;
read lower data(green)     gx |= m_iic_read(0);
read upper data(blue)      bx = m_iic_read(0); bx <<= 8 ;
read lower data(blue)      bx |= m_iic_read(0);
read upper data(intensity) ix = m_iic_read(0); ix <<= 8 ;
read lower data(intensity) ix |= m_iic_read(1);
stop condition             m_iic_stop();

 シーケンスがわかったので、ひとつの関数にまとめます。

    void get_color()
    {
      byte i ;
      byte j ;
      word tmp ;
      byte xx[8] ;
      /*
        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; }
      /* */
      j = DEVICE_ID ;
      j <<= 1 ;
      j &= 0xFE ;
      /* initialize */
      m_iic_start();
      m_iic_write(j);
      m_iic_write(CONTROL_REG);
      m_iic_write(0x83);
      m_iic_start();
      m_iic_write(j);
      m_iic_write(CONTROL_REG);
      /* set High or Low and exposure length */
      m_iic_write(0x03);
      m_iic_stop();
      /* wait */
      delay( tmp ) ;
      /* read */
      m_iic_start();
      m_iic_write(j);
      m_iic_write(0x03);
      m_iic_start();
      m_iic_write(j | ON);
      /* get */
      j = 0 ;
      for ( i = 0 ; i < 8 ; i++ ) {
        if ( i == 7 ) { j = 1 ; }
        *(xx+i) = m_iic_read(j);
      }
      /* stop */
      m_iic_stop();
      /* store */
      for ( i = 0 ; i < 4 ; i++ ) {
        j = (i << 1);
        tmp = *(xx+j) ;
        tmp <<= 8 ; 
        tmp |= *(xx+j+1) ;
        *(xrgbi+i) = tmp ;
      }
    }

 端末で動作を確認してみました。



 問題なくカラーセンサーの情報を取得できています。

 ハードウエアとソフトウエアの道具が揃ったので
 2つのカラーセンサーから情報取得するスケッチ
 を定義しました。

#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 

#define MASK80  0x80
#define IIC_CNT 32

#define MSCL_BIT 3
#define MSDA_BIT 2

/* 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[8] ;

/* sensor command */
byte scmd ;

/* which */
byte state ;

/* 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 m_iic_wait(void)
{
  byte i ;
  /* wait */
  for ( i = 0 ; i < IIC_CNT ; i++ ) ;
}

void m_iic_scl(byte x)
{
  /* impress */
  if ( x ) { PORTC |=  (1 << MSCL_BIT) ; }
  else     { PORTC &= ~(1 << MSCL_BIT) ; }
  /* delay */
  m_iic_wait();
}

void m_iic_start(void)
{
  /* both H */
  PORTC |= (3 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SDA */
  PORTC &= ~(1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SCL */
  PORTC &= ~(1 << MSCL_BIT) ;
}

void m_iic_stop(void)
{
  /* set level */
  PORTC |=  (1 << MSCL_BIT) ;
  PORTC &= ~(1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
  /* 1 -> SDA */
  PORTC |= (1 << MSDA_BIT) ;
  /* delay */
  m_iic_wait();
}

byte m_iic_write(byte x)
{
  byte i   ;
  byte tmp ;
  /* load raw data */
  tmp = x ;
  /* transfer data with write code */
  for ( i = 0 ; i < 8 ; i++ ) {
    /* send bit datum */
    PORTC &= ~(1 << MSDA_BIT) ;
    if ( tmp & MASK80 ) { PORTC |= (1 << MSDA_BIT) ; }
    /* 1 -> SCL */
    m_iic_scl(ON);
    /* shift */
    tmp <<= 1 ;
    /* 0 -> SCL */
    m_iic_scl(OFF);
  }
  PORTC &= ~(1 << MSDA_BIT) ;
  /* change inupt */
  DDRC  &= ~(1 << MSDA_BIT) ;
  /* 1 -> SCL */
  m_iic_scl(ON);
  /* get acknowledge */
  tmp = (PINC & (1 << MSDA_BIT)) >> 2 ;
  /* 0 -> SCL */
  m_iic_scl(OFF);
  /* change output */
  DDRC |= (1 << MSDA_BIT) ;

  return tmp ;
}

byte m_iic_read(byte x)
{
  byte i;
  byte result ;
  /* change inupt */
  PORTC &= ~(1 << MSDA_BIT) ;
  DDRC  &= ~(1 << MSDA_BIT) ;
  /* default */
  result = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    /* shift */
    result <<= 1 ;
    /* 1 -> SCL */
    m_iic_scl(ON);
    /* get bit datum */
    if ( PINC & (1 << MSDA_BIT) ) { result |= ON ; } 
    /* 0 -> SCL */
    m_iic_scl(OFF);
  }
  /* change output */
  DDRC |= (1 << MSDA_BIT) ;
  if ( x ) { PORTC |=  (1 << MSDA_BIT); }
  else     { PORTC &= ~(1 << MSDA_BIT); }
  /* 1 -> SCL */
  m_iic_scl(ON);
  /* 0 -> SCL */
  m_iic_scl(OFF);

  return result ;
}

void get_color2()
{
  byte i ;
  byte j ;
  word tmp ;
  byte xx[8] ;
  /*
    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; }
  /* */
  j = DEVICE_ID ;
  j <<= 1 ;
  j &= 0xFE ;
  /* initialize */
  m_iic_start();
  m_iic_write(j);
  m_iic_write(CONTROL_REG);
  m_iic_write(0x83);
  m_iic_start();
  m_iic_write(j);
  m_iic_write(CONTROL_REG);
  /* set High or Low and exposure length */
  m_iic_write(0x03);
  m_iic_stop();
  /* wait */
  delay( tmp ) ;
  /* read */
  m_iic_start();
  m_iic_write(j);
  m_iic_write(0x03);
  m_iic_start();
  m_iic_write(j | ON);
  /* get */
  j = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    if ( i == 7 ) { j = 1 ; }
    *(xx+i) = m_iic_read(j);
  }
  /* stop */
  m_iic_stop();
  /* store */
  for ( i = 0 ; i < 4 ; i++ ) {
    j = (i << 1);
    tmp = *(xx+j) ;
    tmp <<= 8 ; 
    tmp |= *(xx+j+1) ;
    *(xrgbi+i+4) = 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("AG :") ; show_value( *(xrgbi+1) );
    rs_puts("BG :") ; show_value( *(xrgbi+5) );
  } 
  else
  /* all color informations */
  {
    rs_puts("AR :") ; show_value( *(xrgbi+0) );
    rs_puts("AG :") ; show_value( *(xrgbi+1) );
    rs_puts("AB :") ; show_value( *(xrgbi+2) );
    rs_puts("AIR:") ; show_value( *(xrgbi+3) );
    rs_puts("BR :") ; show_value( *(xrgbi+4) );
    rs_puts("BG :") ; show_value( *(xrgbi+5) );
    rs_puts("BB :") ; show_value( *(xrgbi+6) );
    rs_puts("BIR:") ; show_value( *(xrgbi+7) );
  }
  crlf();
}

void setup()
{
  /* initialize serial port */
  Serial.begin(9600);
  sindex = 0 ;
  /* set initial state */
  PORTB = 0x00 ;
  PORTC = 0x0C ;
  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 ;
  state = 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();
      get_color2();
      /* 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 */
    if ( state ) { get_color2(); }
    else         { get_color(); }
    /* update state */
    state++ ;
    state &= ON ;
    /* show */
    if ( eflag ) { 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 ;
    }
  }
}

 カラーセンサーのどちらを利用するのかで関数を分けて
 あります。get_color()がArduinoの内蔵ハードウエアを
 利用します。get_color2()は、GPIOを利用したIICバス
 でセンサー情報を取得します。

 センサーが2個になったので、情報量は2倍となります。
 word指定の配列のサイズを4から8とします。

 get_color2()は、センサー情報を配列に格納するとき
 オフセットの4をつけて対応しました。

 タイマー割込みで、どちらのセンサーから情報を取得
 するのかは、ステートマシンを利用して記述してます。

 変数stateを用意し、0か1のいずれの値しか持たない
 ように、からくりを用意しました。

    /* get color values */
    if ( state ) { get_color2(); }
    else         { get_color(); }
    /* update state */
    state++ ;
    state &= ON ;

 このスケッチで、2つのセンサーの情報を取得すると
 次のようになります。



 緑だけを抜き出すと、次のような端末表示です。



 Arduino、カラーセンサー、電圧変換モジュールの接続は、以下。



 A5、A4は、Arduinoの内蔵IICバス専用モジュールに接続される
 ので、プルアップする電源電圧が3.3Vでも、問題ありません。
 GPIOとして使う、A3、A2は、5Vインタフェースで扱うように
 しておきます。カラーセンサーには、3.3Vを与えます。
 電圧変換モジュール上にプルアップ抵抗があるため、外付けの
 抵抗は不要。

 エンハンスメントタイプのMOSFETを利用したインタフェースを
 半田付けして、テストしてみました。




 回路は、以下。



 この回路では、Wireライブラリを使うと動作しなかったので
 GPIOを使ったスケッチにしました。

 2つのチャネルを(A5,A4)=(SCL,SDA)=(D19,D18)、(A3,A2)=(SCL,SDA)=(D17,D16)
  に割り当てました。

#include <MsTimer2.h>
#include <EEPROM.h>

#define OFF 0
#define ON  OFF+1

#define MASCL_BIT 5
#define MASDA_BIT 4
#define MBSCL_BIT 3
#define MBSDA_BIT 2

#define MASK80  0x80
#define IIC_CNT 32

#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[8] ;

/* sensor command */
byte scmd ;

/* which sensor */
byte state ;

/* 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 m_iic_wait(void)
{
  byte i ;
  /* wait */
  for ( i = 0 ; i < IIC_CNT ; i++ ) ;
}

void m_iic_scl(byte x,boolean wx)
{
  byte xx ;
  /* channel A */
  xx = MASCL_BIT ;
  /* channel B */
  if ( wx ) { xx = MBSCL_BIT ; }
  /* impress */
  if ( x ) { PORTC |=  (1 << xx) ; }
  else     { PORTC &= ~(1 << xx) ; }
  /* delay */
  m_iic_wait();
}

void m_iic_start(boolean wx)
{
  byte xx ;
  byte yy ;
  /* channel A */
  xx = MASDA_BIT ;
  /* channel B */
  if ( wx ) { xx = MBSDA_BIT ; }
  yy = xx+1 ;
  /* both H */
  PORTC |= (3 << xx) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SDA */
  PORTC &= ~(1 << xx) ;
  /* delay */
  m_iic_wait();
  /* 0 -> SCL */
  PORTC &= ~(1 << yy) ;
}

void m_iic_stop(boolean wx)
{
  byte xx ;
  byte yy ;
  /* channel A */
  xx = MASDA_BIT ;
  /* channel B */
  if ( wx ) { xx = MBSDA_BIT ; }
  yy = xx+1 ;
  /* set level */
  PORTC |=  (1 << yy) ;
  PORTC &= ~(1 << xx) ;
  /* delay */
  m_iic_wait();
  /* 1 -> SDA */
  PORTC |= (1 << xx) ;
  /* delay */
  m_iic_wait();
}

byte m_iic_write(byte x,boolean wx)
{
  byte i   ;
  byte tmp ;
  byte xx ;
  /* send bit datum */
  xx = MASDA_BIT ;
  if ( wx ) { xx = MBSDA_BIT ; }
  /* load raw data */
  tmp = x ;
  /* transfer data with write code */
  for ( i = 0 ; i < 8 ; i++ ) {
    /* impress datum */
    PORTC &= ~(1 << xx) ;
    if ( tmp & MASK80 ) { PORTC |= (1 << xx) ; }
    /* 1 -> SCL */
    m_iic_scl(ON,wx);
    /* shift */
    tmp <<= 1 ;
    /* 0 -> SCL */
    m_iic_scl(OFF,wx);
  }
  PORTC &= ~(1 << xx) ;
  /* change inupt */
  DDRC  &= ~(1 << xx) ;
  /* 1 -> SCL */
  m_iic_scl(ON,wx);
  /* get acknowledge */
  tmp = (PINC & (1 << xx)) >> xx ;
  /* 0 -> SCL */
  m_iic_scl(OFF,wx);
  /* change output */
  DDRC |= (1 << xx) ;

  return tmp ;
}

byte m_iic_read(byte x,boolean wx)
{
  byte i;
  byte result ;
  byte xx ;
  /* channel A */
  xx = MASDA_BIT ;
  /* channel B */
  if ( wx ) { xx = MBSDA_BIT ; }
  /* change inupt */
  PORTC &= ~(1 << xx) ;
  DDRC  &= ~(1 << xx) ;
  /* default */
  result = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    /* shift */
    result <<= 1 ;
    /* 1 -> SCL */
    m_iic_scl(ON,wx);
    /* 0 -> SCL */
    m_iic_scl(OFF,wx);
    /* get bit datum */
    if ( PINC & (1 << xx) ) { result |= ON ; } 
  }
  /* change output */
  DDRC |= (1 << xx) ;
  if ( x ) { PORTC |=  (1 << xx); }
  else     { PORTC &= ~(1 << xx); }
  /* 1 -> SCL */
  m_iic_scl(ON,wx);
  /* 0 -> SCL */
  m_iic_scl(OFF,wx);

  return result ;
}

void get_color(boolean wx)
{
  byte i ;
  byte j ;
  word tmp ;
  byte xx[8] ;
  /*
    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; }
  /* */
  j = DEVICE_ID ;
  j <<= 1 ;
  j &= 0xFE ;
  /* initialize */
  m_iic_start(wx);
  m_iic_write(j,wx);
  m_iic_write(CONTROL_REG,wx);
  m_iic_write(0x83,wx);
  m_iic_start(wx);
  m_iic_write(j,wx);
  m_iic_write(CONTROL_REG,wx);
  /* set High or Low and exposure length */
  m_iic_write(0x03,wx);
  m_iic_stop(wx);
  /* wait */
  delay( tmp ) ;
  /* read */
  m_iic_start(wx);
  m_iic_write(j,wx);
  m_iic_write(0x03,wx);
  m_iic_start(wx);
  m_iic_write(j | ON,wx);
  /* get */
  j = 0 ;
  for ( i = 0 ; i < 8 ; i++ ) {
    if ( i == 7 ) { j = 1 ; }
    *(xx+i) = m_iic_read(j,wx);
  }
  /* stop */
  m_iic_stop(wx);
  /* store */
  for ( i = 0 ; i < 4 ; i++ ) {
    j = (i << 1);
    tmp = *(xx+j) ;
    tmp <<= 8 ; 
    tmp |= *(xx+j+1) ;
    *(xrgbi+i+4*wx) = 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("AG :") ; show_value( *(xrgbi+1) );
    rs_puts("BG :") ; show_value( *(xrgbi+5) );
  } 
  else
  /* all color informations */
  {
    rs_puts("AR :") ; show_value( *(xrgbi+0) );
    rs_puts("AG :") ; show_value( *(xrgbi+1) );
    rs_puts("AB :") ; show_value( *(xrgbi+2) );
    rs_puts("AIR:") ; show_value( *(xrgbi+3) );
    rs_puts("BR :") ; show_value( *(xrgbi+4) );
    rs_puts("BG :") ; show_value( *(xrgbi+5) );
    rs_puts("BB :") ; show_value( *(xrgbi+6) );
    rs_puts("BIR:") ; show_value( *(xrgbi+7) );
  }
  crlf();
}

void setup()
{
  /* initialize serial port */
  Serial.begin(9600);
  sindex = 0 ;
  /* set initial state */
  PORTB = 0x00 ;
  PORTC = 0x0C ;
  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 */
  xcnt = 0 ;
  for ( xcnt = 0 ; xcnt < 8 ; xcnt++ ) { *(xrgbi+xcnt) = 0 ; }
  state = 0 ;
  /* trigger period */
  MsTimer2::set(NPER,update_trigger);
  /* enable */ 
  MsTimer2::start(); 
}

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(OFF);
      get_color(ON);
      /* 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(state);
    state++ ;
    state &= ON ;
    /* 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 ;
    }
  }
}

 Arduinoと変換基板の接続は、次のようになります。



 TeraTermを利用した、Arduinoスケッチの動作確認を
 すると、以下の2チャネル分の情報を表示します。



 Processingスケッチは、次頁にて説明。


目次

inserted by FC2 system