目次

スタブ作成

 Processingで通信する場合、受信割込みを利用します。

 通信相手が必要なので、Arduinoを利用してスタブを
 作成して対応しました。

 カラーセンサーからデータを定期的に取得して
 それをバーで表示するので、Arduinoを利用して
 Processingのスケッチをテストするための環境を
 用意したと言えばよいでしょう。

 スタブを利用する場合、スタブを動かすための
 プログラムが必要です。このプログラムコード
 を、テストドライバと呼びます。

 テストドライバをProcessingスケッチで書くのは
 面倒なので、TeraTermをテストドライバもどきで
 利用します。

 TeraTermの内容は、以下。



 定期的に2チャネル分のデータを生成して送信する
 スケッチを作成すればよいでしょう。

 データは乱数で生成して、それなりのデータになる
 ようにします。Arduinoの乱数の仕様は以下。

 random(min, max)

 min: 生成する乱数の下限。省略可能 
 max: 生成する乱数の上限 

 2チャネル分のデータは、8個になるのでひとつの乱数を
 生成し、剰余系で8データにしました。

  long rx = random(50,1200) ;

  *(cha+0) = rx %  800 ;
  *(cha+1) = rx %  900 ;
  *(cha+2) = rx % 1000 ;
  *(cha+3) = rx % 1100 ;

  *(chb+0) = rx % 400 ;
  *(chb+1) = rx % 500 ;
  *(chb+2) = rx % 600 ;
  *(chb+3) = rx % 700 ;

 タイマー割込みで乱数を生成し、擬似のセンサー
 データを生成します。

 どこに入れるかというとは関数get_sensorの中です。

 スケッチは、以下。

#include <MsTimer2.h>

#define OFF 0
#define ON  OFF+1

#define MASK80  0x80

#define LED_BIT 5

#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 get_color(boolean wx)
{
  long rx ;
  /* generate random number */
  rx = random(50,1200) ;
  /* which */
  if ( wx ) {
    /* channel B */
    *(xrgbi+4) = rx % 400 ;
    *(xrgbi+5) = rx % 500 ;
    *(xrgbi+6) = rx % 600 ;
    *(xrgbi+7) = rx % 700 ;
  } else {
    /* channel A */
    *(xrgbi+0) = rx %  800 ;
    *(xrgbi+1) = rx %  900 ;
    *(xrgbi+2) = rx % 1000 ;
    *(xrgbi+3) = rx % 1100 ;
  }
}

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) );
  }
  /* Mask */
  {
    *(msg+0) = 'N' ;
    if ( mflag == ON ) { *(msg+0) = 'Y' ; }
    rs_puts( msg );
  }
  /* Green */
  {
    *(msg+0) = 'N' ;
    if ( gflag == 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 ; }
}

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

 カラーセンサーから情報を取得する部分だけを
 スタブにしてあるので、Processingスケッチの
 テスト、デバッグが終わった段階で、スタブを
 実処理に置換します。

 スケッチでは、関数get_colorだけがスタブですが
 数値の文字列変換、1文字送信、文字列送信等の
 付随する処理を同時にテストしています。

 1文字送信を作成したなら、そのラッパー関数である
 文字列送信の関数を定義。

 建築物の礎石を並べていくように、最も下位レベルのI/Oを
 作成します。そのプリミティブ関数をラッパー関数で包む
 作業を続けていきます。

 ラッパー関数は、スタブを動かすためのテストドライバと
 呼んでもよいでしょう。


目次

inserted by FC2 system