目次

卓上調整

 メカが完成したので、マシンを卓の上に載せて
 動作を確認し、調整します。

 マシンはスタートスイッチを押した後、センサー情報を
 判断して走行するので、センサー情報を与えて、どの様
 にサーボモータで前輪を動かすのかを調べます。




 パーソナルコンピュータ上のGUIで、センサー情報を
 指定し、マイクロコンピュータに与え、8ビットの
 データとしてマシン制御担当のFPGAに与えます。

 GUI画面は、以下とします。



 通信ポートと転送速度をコンボボックスで選択後
 Connectボタンのクリックでマイクロコンピュータ
 と接続します。

 センサー情報出力は、コンボボックスの中から該当する
 パターンを指定後、sendボタンをクリックします。

 切断するときは、Disconnectボタンをクリックします。

 Javaコードの構成は、以下としました。



 トップレベルのコード(rstst.java)は、以下です。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

import gnu.io.*;
import java.io.*;

// internal Device Test Board class
class DtbC
{
  SerialPort         port;
  CommPortIdentifier comID;

  String comName;
  int    baudRate;

  InputStream  in;
  OutputStream out;
  // open method
  boolean rs_open(String Com_Name,int Baud_Rate)
  {
    comName = Com_Name;
    baudRate = Baud_Rate;
    // get port ID
    try {
      comID = CommPortIdentifier.getPortIdentifier(comName);
    } catch(Exception e) {
      JOptionPane.showMessageDialog(null,"Do not nortify !","DtbC.open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    // already opened
    if ( comID.isCurrentlyOwned() == false ) {
      try { 
        // generate instance
        port = (SerialPort)comID.open("DTB",2000);
        // baud rate , data length , stop bit , parity 
        port.setSerialPortParams(baudRate,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );
        // no flow control
        port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
        // input and output stream
        in = port.getInputStream();
        out = port.getOutputStream();
      } catch(Exception e) {
        JOptionPane.showMessageDialog(null,"Do not open !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already opened !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    return true;
  }
  // close method 
  boolean rs_close()
  {
    if ( comID.isCurrentlyOwned() ) {
      try {
        port.close();
        in.close();
        out.close();
      } catch(IOException e) {
        JOptionPane.showMessageDialog(null,"Do not close !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already closed !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
      return false; 
    }
    return true;
  }
  // send string
  void Serial_puts(String str)
  {
    byte[] data = str.getBytes();
    try {
      out.write(data);
      out.flush();
    } catch(Exception e) {
    }
  }
}

// internal Serial Class (super class => DtbC)
class Serial_Class extends DtbC
{
  JComboBox   cbxCom;
  JComboBox   cbxBaud;
  JTextArea   edtText;
  JScrollPane scrPane;
  // constructor
  Serial_Class()
  {
    // generate text area
    edtText = new JTextArea();
    // generate scroll pane
    scrPane = new JScrollPane(edtText);
    scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // COM port ComboBox
    cbxCom = new JComboBox();
    cbxCom.addItem("COM1"); cbxCom.addItem("COM2");
    cbxCom.addItem("COM3"); cbxCom.addItem("COM4");
    cbxCom.addItem("COM5"); cbxCom.addItem("COM6");
    cbxCom.addItem("COM7"); cbxCom.addItem("COM8");
    cbxCom.addItem("COM9");
    // default port
    cbxCom.setSelectedItem("COM6");
    // Buad rate ComboBox
    cbxBaud = new JComboBox();
    cbxBaud.addItem("4800") ;
    cbxBaud.addItem("9600");
    cbxBaud.addItem("19200");
    // default baud rate
    cbxBaud.setSelectedItem("9600");
  }
  // open method
  void open()
  {
    boolean flag;
    // convert COM name to string
    String COM_Name = (cbxCom.getSelectedItem()).toString();
    // get baud rate from ComboBox
    int Baud_Rate = Integer.parseInt((cbxBaud.getSelectedItem()).toString());
    // open 
    flag = rs_open(COM_Name,Baud_Rate);
    // success
    if ( flag ) {
      try {
        // register receive event handler
        port.addEventListener(new SerialPortListener());
        // add event monitor
        port.notifyOnDataAvailable(true);
      } catch(Exception e) {
      }
      edtText.append("Connected");
    }
  }
  // close method
  void close()
  {
    boolean flag;
    // close 
    flag = rs_close();
    // success
    if ( flag ) { edtText.append("Disconnected"); }
  }
  // event listener
  class SerialPortListener implements SerialPortEventListener
  {
    // event handler
    public void serialEvent(SerialPortEvent Serial_event)
    {
      StringBuffer buffer = new StringBuffer();
      int received_data = 0 ;
      // receive completed 
      if ( Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE ) {
        // loop until get 'break'
        while (true) {
          try {
            // get data from input stream
            received_data = in.read();
            // no charactor
            if ( received_data == -1 ) break;
            // store
            if ( (char)received_data != '\r' ) {
              buffer.append((char)received_data);
            } else {
            // get delimiter
              // convert 
              edtText.append(buffer.toString());
              // clear buffer
              //buffer.delete(0,buffer.length()-1); 
              buffer.delete(0,buffer.length()); 
              // post handling
              edtText.setCaretPosition(edtText.getText().length());
              //break;
            }
          } catch(IOException ex){
          }
        }
      }
    }
  }
}

// internal Frame (window) class
class MFrame extends JFrame
{
  Serial_Class serial;
  JComboBox cbxSensor ;
  // constructor
  MFrame()
  {
    // call super class method
    super("MCR-VC sensor test");

    serial = new Serial_Class();
    // generate pane
    JPanel cp = new JPanel();
    // set layout moe
    cp.setLayout(null);
    // add pane to frame
    setContentPane(cp);
    // generate scroll pane
    JScrollPane sp = new JScrollPane(serial.edtText);
    // enable vertical scroll bar
    sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // set scroll pane dimension
    sp.setBounds(50,50,400,300);
    // add scroll pane
    cp.add(sp);
    // show COM port
    JLabel com_label = new JLabel("COM port:");
    cp.add(com_label);
    com_label.setBounds(50,20,100,20);
    cp.add(serial.cbxCom);
    serial.cbxCom.setBounds(120,20,80,20);
    // show selected baud rate
    JLabel baud_label = new JLabel("Baud rate : ");
    cp.add(baud_label);
    baud_label.setBounds(250,20,100,20);
    cp.add(serial.cbxBaud);
    serial.cbxBaud.setBounds(350,20,80,20);
    // show selected sensor data
    JLabel sensor_label = new JLabel("sensor data : ");
    cp.add(sensor_label);
    sensor_label.setBounds(50,400,80,20);
    cbxSensor = new JComboBox();
    cp.add(cbxSensor);
    cbxSensor.setBounds(150,400,120,20);
    cbxSensor.addItem("ALL_BLACK") ;
    cbxSensor.addItem("TINY_RIGHT");
    cbxSensor.addItem("RIGHT");
    cbxSensor.addItem("BIG_RIGHT");
    cbxSensor.addItem("CENTER") ;
    cbxSensor.addItem("TINY_LEFT");
    cbxSensor.addItem("LEFT");
    cbxSensor.addItem("BIG_LEFT");
    cbxSensor.addItem("LEFT_WHITE");
    cbxSensor.addItem("RIGHT_WHITE");
    cbxSensor.addItem("ALL_WHITE") ;
    // generate Font
    Font font = new Font("SansSerif",Font.PLAIN,16);
    // add Font information to textarea
    serial.edtText.setFont(font);
    serial.edtText.setLineWrap(true);
    serial.edtText.addKeyListener(new KeyInput());
    serial.scrPane.setBounds(50,50,400,300);
    cp.add(serial.scrPane);
    // define button
    JButton btnConnect = new JButton(new open_action());
    btnConnect.setBounds(50,350,100,36);
    cp.add(btnConnect);
    JButton btnDisconnect = new JButton(new close_action());
    btnDisconnect.setBounds(300,350,100,36);
    cp.add(btnDisconnect);
    JButton btnSend = new JButton(new send_action());
    btnSend.setBounds(300,400,80,20);
    cp.add(btnSend);
    // register KeyInput class to KeyListener
    serial.edtText.addKeyListener(new KeyInput());
  }
  // internal class (bntConnect)
  class open_action extends AbstractAction
  {
    // constructor
    open_action()
    {
      putValue(Action.NAME,"Connect");
    }
    // event method
    public void actionPerformed(ActionEvent btnConnect_act)
    {
      serial.open();
    }
  }
  // internal class (bntDisconnect)
  class close_action extends AbstractAction
  {
    // constructor
    close_action()
    {
      putValue(Action.NAME,"Disconnect");
    }
    // event method
    public void actionPerformed(ActionEvent btnDisconnect_act)
    {
      serial.close();
    }
  }
  // internal class (bntSend)
  class send_action extends AbstractAction
  {
    // constructor
    send_action()
    {
      putValue(Action.NAME,"Send");
    }
    // event method
    public void actionPerformed(ActionEvent bntSend_act)
    {
      //  0 ALL_BLACK
      //  1 TINY_RIGHT
      //  2 RIGHT
      //  3 BIG_RIGHT
      //  4 CENTER
      //  5 TINY_LEFT
      //  6 LEFT
      //  7 BIG_LEFT
      //  8 LEFT_WHITE
      //  9 RIGHT_WHITE
      // 10 ALL_WHITE
      int index ;
      String stmp ;
      // get index 
      index = cbxSensor.getSelectedIndex() ;
      // generate code
      stmp = "B" + index + "\r" ;
      // show
      serial.edtText.append(stmp+"\n");
      // send
      serial.Serial_puts(stmp);
    }
  }
  // key event
  class KeyInput extends KeyAdapter
  {
    String   stmp;
    String[] stmp_array;
    int lineNum;

    public void keyPressed(KeyEvent e)
    {
      // get key then echo to textArea
      if ( e.getKeyCode() == KeyEvent.VK_ENTER )
      {
        //serial.edtText.append("\n");
        stmp = serial.edtText.getText();
        stmp_array = stmp.split("\n",0);
        lineNum = stmp_array.length - 1;
        // send serial port
        serial.Serial_puts(stmp_array[lineNum]+"\r");
      }
    }
  }
}

public class rstst
{
  private final static int my_frm_width  = 500 ;
  private final static int my_frm_height = 500 ;

  public static void main(String args[])
  {
    MFrame frame = new MFrame();
    // 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // set dimension
    frame.setSize(my_frm_width,my_frm_height);
    // show
    frame.setVisible(true);
  }
}

 GUIの形態を決めるコード(MFrame.java)は、以下。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

import gnu.io.*;
import java.io.*;

class MFrame extends JFrame
{
  JTextArea edtText;

  MFrame()
  {
    // call super class constructor
    super("MCR machine test");
    // generate pane
    JPanel cp = new JPanel();
    // set layout moe
    cp.setLayout(null);
    // add pane to frame
    add(cp);
    // generate text area
    edtText = new JTextArea();
    // enable word wrap
    edtText.setLineWrap(true);

    // generate scroll pane
    JScrollPane sp = new JScrollPane(edtText);
    // enable vertical scroll bar
    sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // set scroll pane dimension
    sp.setBounds(50,50,400,300);
    // add scroll pane
    cp.add(sp);

    // generate Font
    Font font = new Font("SansSerif",Font.PLAIN,16);
    // add Font information to textarea。
    edtText.setFont(font);

    // generate ComboBox
    JComboBox cbxCom = new JComboBox();
    // add items
    cbxCom.addItem("COM1"); cbxCom.addItem("COM2");
    cbxCom.addItem("COM3"); cbxCom.addItem("COM4");
    cbxCom.addItem("COM5"); cbxCom.addItem("COM6");
    cbxCom.addItem("COM7"); cbxCom.addItem("COM8");
    // set location and dimension
    cbxCom.setBounds(120,20,80,20);
    // add ComboBox
    cp.add(cbxCom);
    // set default COM port
    cbxCom.setSelectedItem("COM6");
    // add label
    JLabel com_label = new JLabel("COM port:");
    com_label.setBounds(50,20,100,20);
    cp.add(com_label);
    // communication condition
    JComboBox cbxBaud = new JComboBox();
    // add items
    cbxBaud.addItem("4800") ; cbxBaud.addItem("9600");
    cbxBaud.addItem("19200"); cbxBaud.addItem("38400");
    cbxBaud.addItem("57600");
    cbxBaud.setBounds(350,20,80,20);
    cp.add(cbxBaud);
    // select 38400 bps
    cbxBaud.setSelectedItem("38400");
    // show selected baud rate
    JLabel baud_label = new JLabel("Baud rate : ");
    baud_label.setBounds(250,20,100,20);
    cp.add(baud_label);

    // define button
    JButton btnConnect = new JButton(new open_action());
    btnConnect.setBounds(50,400,150,40);
    cp.add(btnConnect);
    JButton btnDisconnect = new JButton(new close_action());
    btnDisconnect.setBounds(300,400,150,40);
    cp.add(btnDisconnect);

    // register KeyInput class to KeyListener
    edtText.addKeyListener(new KeyInput());

  }

  // internal class (bntConnect)
  class open_action extends AbstractAction
  {
    // constructor
    open_action()
    {
      putValue(Action.NAME,"Connect");
    }
    // event method
    public void actionPerformed(ActionEvent btnConnect_act)
    {
      edtText.append("Connected\n");
      JOptionPane.showMessageDialog(null,"Conneced","actionPerformed()",JOptionPane.INFORMATION_MESSAGE);
    }
  }

  // internal class (bntDisconnect)
  class close_action extends AbstractAction
  {
    // constructor
    close_action()
    {
      putValue(Action.NAME,"Disconnect");
    }
    // event method
    public void actionPerformed(ActionEvent btnDisconnect_act)
    {
      edtText.append("Disonnected\n");
      JOptionPane.showMessageDialog(null,"Disconneced","actionPerformed()",JOptionPane.INFORMATION_MESSAGE);
    }
  }
  // key event
  class KeyInput extends KeyAdapter
  {
    //何かキーボードが押されたときに呼ばれるメソッド。
    public void keyPressed(KeyEvent e)
    {
      //ENTERキーならば、テキストエリアに表示。
      if ( e.getKeyCode() == KeyEvent.VK_ENTER )
      {
       edtText.append("Enterキーが押されました。");
      }
    }
  }
}

 通信オブジェクトのラッパであるコード(DtbC.java)は、以下。
 (DtbCは、Data transfer block Classの略)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import gnu.io.*;

class DtbC
{
  SerialPort port;
  CommPortIdentifier comID;

  String comName;
  int baudRate;

  InputStream in;
  OutputStream out;

  // open method
  boolean rs_open(String Com_Name,int Baud_Rate)
  {
    comName = Com_Name;
    baudRate = Baud_Rate;
    // get port ID
    try {
      comID = CommPortIdentifier.getPortIdentifier(comName);
    } catch(Exception e1) {
      JOptionPane.showMessageDialog(null,"Do not nortify !","Serial_Base.open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    // already opened
    if ( comID.isCurrentlyOwned() == false ) {
      try { 
        // generate instance
        port = (SerialPort)comID.open("DTB",2000);
        // baud rate , data length , stop bit , parity 
        port.setSerialPortParams(baudRate,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );
        // no flow control
        port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
        // input and output stream
        in = port.getInputStream();
        out = port.getOutputStream();
      } catch(Exception e2) {
        JOptionPane.showMessageDialog(null,"Do not open !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already opened !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    return true;
  }

  // close method 
  boolean rs_close()
  {
    if ( comID.isCurrentlyOwned() ) {
      try {
        port.close();
        in.close();
        out.close();
      } catch(IOException e3) {
        JOptionPane.showMessageDialog(null,"Do not close !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already closed !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
      return false; 
    }
    return true;
  }

  // send string
  void Serial_puts(String str)
  {
    try {
      byte[] data = str.getBytes();

      out.write(data);
      out.flush();
    } catch(Exception e4) {
    }
  }
}

 通信オブジェクトの本体(Serial_Class.java)は、以下。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

import gnu.io.*;
import java.io.*;

class Serial_Class extends DtbC
{
  JComboBox cbxCom;
  JComboBox cbxBaud;
  JTextArea edtText;
  JScrollPane scrollPane;

  // constructor
  Serial_Class()
  {
    // generate text area
    edtText = new JTextArea();
    // generate scroll pane
    scrollPane = new JScrollPane(edtText);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // COM port ComboBox
    cbxCom = new JComboBox();
    cbxCom.addItem("COM1"); cbxCom.addItem("COM2");
    cbxCom.addItem("COM3"); cbxCom.addItem("COM4");
    cbxCom.addItem("COM5"); cbxCom.addItem("COM6");
    cbxCom.addItem("COM7"); cbxCom.addItem("COM8");
    // default port
    cbxCom.setSelectedItem("COM6");
    // Buad rate ComboBox
    cbxBaud = new JComboBox();
    cbxBaud.addItem("4800") ; cbxBaud.addItem("9600");
    cbxBaud.addItem("19200"); cbxBaud.addItem("38400");
    cbxBaud.addItem("57600");
    // default baud rate
    cbxBaud.setSelectedItem("38400");
  }

  // open method
  void open()
  {
    boolean flag;
    // convert COM name to string
    String COM_Name = (cbxCom.getSelectedItem()).toString();
    // get baud rate from ComboBox
    int Baud_Rate = Integer.parseInt((cbxBaud.getSelectedItem()).toString());
    // open 
    flag = rs_open(COM_Name,Baud_Rate);
    // success
    if ( flag ) {
      try {
        // register receive event handler
        port.addEventListener(new SerialPortListener());
        // add event monitor
        port.notifyOnDataAvailable(true);
      } catch(Exception e) {
      }
      edtText.append("Connected\n\n");
    }
  }

  // close method
  void close()
  {
    boolean flag;
    // close 
    flag = rs_close();
    // success
    if ( flag ) {
      edtText.append("Disconnected\n\n");
    }
  }

  // event listener
  class SerialPortListener implements SerialPortEventListener
  {
    // event handler
    public void serialEvent(SerialPortEvent Serial_event)
    {
      StringBuffer buffer = new StringBuffer();
      int received_data;

      received_data = 0;
      // receive completed 
      if ( Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE ) {
        // loop until get 'break'
        while (true) {
          try {
            // get data from input stream
            received_data = in.read();
            // no charactor
            if ( received_data == -1 ) break;
            // store
            if ( (char)received_data != '\r' ) buffer.append((char)received_data);
            // get delimiter
            else {
              // new line
              buffer.append('\n');
              // convert 
              edtText.append(buffer.toString());
              // clear buffer
              buffer.delete(0,buffer.length()-1); 
              // post handling
              edtText.setCaretPosition(edtText.getText().length());
              break;
            }
          } catch(IOException ex){
          }
        }
      }
    }
  }
}

 マイクロコンピュータとして、AtmelのATtiny2313を利用します。
 回路図は、以下です。



 20MHzで動作させ、シリアルインタフェースは小信号NPN
 トランジスタを利用した簡易タイプにしました。

 パーソナルコンピュータから与えられたコード番号を
 基に、配列からビットパターンを引出して、ポートB
 に出力します。

 受信割込みで、パーソナルコンピュータが与えたコードを
 取得します。コマンド到着を、フラグで通知します。

#include <avr/io.h>
#include <avr/interrupt.h>

#define OFF 0
#define ON  OFF+1

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

#define FOSC   20000000
#define BAUD   9600
#define MYUBRR (FOSC/16/BAUD)-1

#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0

#define BUFSIZE 8

#define SENSOR_ALL_BLACK   0
#define SENSOR_TINY_RIGHT  1
#define SENSOR_RIGHT       2
#define SENSOR_BIG_RIGHT   3
#define SENSOR_CENTER      4
#define SENSOR_TINY_LEFT   5
#define SENSOR_LEFT        6
#define SENSOR_BIG_LEFT    7
#define SENSOR_LEFT_WHITE  8
#define SENSOR_RIGHT_WHITE 9
#define SENSOR_ALL_WHITE   10
	
volatile UBYTE sbuf[BUFSIZE] ;
volatile UBYTE sindex;
volatile UBYTE uflag ;
volatile UBYTE cmd ;
volatile UBYTE select ;

volatile UBYTE spat[16] = {0x00,0x0C,0x06,0x03,
                           0x18,0x30,0x60,0xC0,
                           0xF0,0x0F,0xFF,0xFF,
                           0xFF,0xFF,0xFF,0xFF};

#define NO  0
#define YES NO+1

/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void  user_initialize(void);
void  show_help(void);
UBYTE rs_get_digit(UBYTE x);
void  rs_putchar(UBYTE x);
void  rs_puts(UBYTE *x);

/*------*/
/* main */
/*------*/
int main(void)
{
  /* initialize */
  user_initialize();
  /* enable interrupt */
  sei();
  /* loop */
  while ( ON ) {
    /* handling */
    if ( uflag == ON ) {
      /* clear flag */
      uflag = OFF ;
      /* get command */
      cmd = *(sbuf+0) ;
      /* branch */
      if ( cmd == '?' ) {
        show_help();
      }
      if ( cmd == 'B' ) {
        select = rs_get_digit(*(sbuf+1));
        select = select * 10 + rs_get_digit(*(sbuf+2));
        PORTB = *(spat+select);
      }
    }
  }
  /* dummy */
  return 0 ;
}

/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
  /* PORT D */
  PORTD = 0b00000001 ; /* 00000001 */
  DDRD  = 0b11111110 ; /* oooooooi */
  /* PORT B */
  PORTB = 0b00000000 ; /* 00000000 */
  DDRB  = 0b11111111 ; /* oooooooo */
  /* clear flags */
  uflag = OFF ;
  /* others */
  cmd    = 0 ;
  select = 0 ;
  /* initialize serial */
  {
    /* clear index */
    sindex = 0 ;
    /* clear buffer */
    *(sbuf+0) = 0 ;
    /* set Baud Rate Registers */
    UBRRL = MYUBRR ;
    /* Enable receive interrupt , receive module and transmit module */
    UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN) ;
  }
}

/* UART receive interrupt */
ISR(USART_RX_vect)
{
  UBYTE ch ;
  /* get 1 charactoer */
  ch = UDR ;
  /* store */
  *(sbuf+sindex) = ch ;
  sindex++ ;
  /* judge */
  if ( ch == '\r' ) {
    uflag  = ON ;
    sindex = 0 ;
  }
}

void  show_help(void)
{
  rs_puts( (UBYTE *)"B -> pattern" ) ;
  rs_puts( (UBYTE *)"? -> Help" ) ;
}

UBYTE rs_get_digit(UBYTE x)
{
  volatile UBYTE result ;
  /* default */
  result = 0 ;
  if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
  if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10; };
  if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10; };
  return result ;
}

void  rs_putchar(UBYTE x)
{
  while ( !(UCSRA & (1 << UDRE)) ) {}
  UDR = x ;
}

void  rs_puts(UBYTE *x)
{
  while ( *x != '\0' ) {
    rs_putchar( *x ) ;
    x++ ;
  }
  rs_putchar('\r');
  rs_putchar('\n');
}

 路面情報をテキストファイルに入れ、それを与えることで
 卓上調整をより簡単にしたいと考えました。

 テキストファイルの1行に入れる情報は、次の書式としました。

  センサーデータ(文字列) 継続時間(msの倍数)

 テキストファイルの内容は、以下のようにします。

  CENTER 1000
  ALL_BLACK 1500
  TINY_RIGHT 1000
  RIGHT 3000
  BIG_RIGHT 1000
  TINY_LEFT 1000
  LEFT 2000
  BIG_LEFT 1000
  ALL_WHITE 1500
  RIGHT_WHITE 1500
  LEFT_WHITE 1500
  ALL_WHITE 1500
  CENTER 1000

 Javaコードを拡張して、テキストファイルから情報を入力し
 センサー情報をマイコンに自動転送するボタンを用意します。



 コードは、以下です。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

import gnu.io.*;
import java.io.*;

// internal Device Test Board class
class DtbC
{
  SerialPort         port;
  CommPortIdentifier comID;

  String comName;
  int    baudRate;

  InputStream  in;
  OutputStream out;
  // open method
  boolean rs_open(String Com_Name,int Baud_Rate)
  {
    comName = Com_Name;
    baudRate = Baud_Rate;
    // get port ID
    try {
      comID = CommPortIdentifier.getPortIdentifier(comName);
    } catch(Exception e) {
      JOptionPane.showMessageDialog(null,"Do not nortify !","DtbC.open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    // already opened
    if ( comID.isCurrentlyOwned() == false ) {
      try { 
        // generate instance
        port = (SerialPort)comID.open("DTB",2000);
        // baud rate , data length , stop bit , parity 
        port.setSerialPortParams(baudRate,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );
        // no flow control
        port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
        // input and output stream
        in = port.getInputStream();
        out = port.getOutputStream();
      } catch(Exception e) {
        JOptionPane.showMessageDialog(null,"Do not open !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already opened !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
      return false;
    }
    return true;
  }
  // close method 
  boolean rs_close()
  {
    if ( comID.isCurrentlyOwned() ) {
      try {
        port.close();
        in.close();
        out.close();
      } catch(IOException e) {
        JOptionPane.showMessageDialog(null,"Do not close !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
        return false;
      }
    } else {
      JOptionPane.showMessageDialog(null,"Already closed !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
      return false; 
    }
    return true;
  }
  // send string
  void Serial_puts(String str)
  {
    byte[] data = str.getBytes();
    try {
      out.write(data);
      out.flush();
    } catch(Exception e) {
    }
  }
}

// internal Serial Class (super class => DtbC)
class Serial_Class extends DtbC
{
  JComboBox   cbxCom;
  JComboBox   cbxBaud;
  JTextArea   edtText;
  JScrollPane scrPane;
  // constructor
  Serial_Class()
  {
    // generate text area
    edtText = new JTextArea();
    // generate scroll pane
    scrPane = new JScrollPane(edtText);
    scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // COM port ComboBox
    cbxCom = new JComboBox();
    cbxCom.addItem("COM1"); cbxCom.addItem("COM2");
    cbxCom.addItem("COM3"); cbxCom.addItem("COM4");
    cbxCom.addItem("COM5"); cbxCom.addItem("COM6");
    cbxCom.addItem("COM7"); cbxCom.addItem("COM8");
    cbxCom.addItem("COM9");
    // default port
    cbxCom.setSelectedItem("COM6");
    // Buad rate ComboBox
    cbxBaud = new JComboBox();
    cbxBaud.addItem("4800") ;
    cbxBaud.addItem("9600");
    cbxBaud.addItem("19200");
    // default baud rate
    cbxBaud.setSelectedItem("9600");
  }
  // open method
  void open()
  {
    boolean flag;
    // convert COM name to string
    String COM_Name = (cbxCom.getSelectedItem()).toString();
    // get baud rate from ComboBox
    int Baud_Rate = Integer.parseInt((cbxBaud.getSelectedItem()).toString());
    // open 
    flag = rs_open(COM_Name,Baud_Rate);
    // success
    if ( flag ) {
      try {
        // register receive event handler
        port.addEventListener(new SerialPortListener());
        // add event monitor
        port.notifyOnDataAvailable(true);
      } catch(Exception e) {
      }
      edtText.append("Connected");
    }
  }
  // close method
  void close()
  {
    boolean flag;
    // close 
    flag = rs_close();
    // success
    if ( flag ) { edtText.append("Disconnected"); }
  }
  // event listener
  class SerialPortListener implements SerialPortEventListener
  {
    // event handler
    public void serialEvent(SerialPortEvent Serial_event)
    {
      StringBuffer buffer = new StringBuffer();
      int received_data = 0 ;
      // receive completed 
      if ( Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE ) {
        // loop until get 'break'
        while (true) {
          try {
            // get data from input stream
            received_data = in.read();
            // no charactor
            if ( received_data == -1 ) break;
            // store
            if ( (char)received_data != '\r' ) {
              buffer.append((char)received_data);
            } else {
            // get delimiter
              // convert 
              edtText.append(buffer.toString());
              // clear buffer
              //buffer.delete(0,buffer.length()-1); 
              buffer.delete(0,buffer.length()); 
              // post handling
              edtText.setCaretPosition(edtText.getText().length());
              //break;
            }
          } catch(IOException ex){
          }
        }
      }
    }
  }
}

// internal Frame (window) class
class MFrame extends JFrame
{
  Serial_Class serial;
  JComboBox cbxSensor ;
  String[] stmpx ;
  String[] cmdval = new String[11] ;
  String[] cmd    = new String[11] ;
  // constructor
  MFrame()
  {
    // call super class method
    super("MCR-VC sensor test");

    serial = new Serial_Class();
    // generate pane
    JPanel cp = new JPanel();
    // set layout moe
    cp.setLayout(null);
    // add pane to frame
    setContentPane(cp);
    // generate scroll pane
    JScrollPane sp = new JScrollPane(serial.edtText);
    // enable vertical scroll bar
    sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    // set scroll pane dimension
    sp.setBounds(50,50,400,300);
    // add scroll pane
    cp.add(sp);
    // show COM port
    JLabel com_label = new JLabel("COM port:");
    cp.add(com_label);
    com_label.setBounds(50,20,100,20);
    cp.add(serial.cbxCom);
    serial.cbxCom.setBounds(120,20,80,20);
    // show selected baud rate
    JLabel baud_label = new JLabel("Baud rate : ");
    cp.add(baud_label);
    baud_label.setBounds(250,20,100,20);
    cp.add(serial.cbxBaud);
    serial.cbxBaud.setBounds(350,20,80,20);
    // make table
    //String[] cmd = new String[11] ;
    {
      cmd[ 0] = "ALL_BLACK"   ; cmd[ 1] = "TINY_RIGHT"  ;
      cmd[ 2] = "RIGHT"       ; cmd[ 3] = "BIG_RIGHT"   ;
      cmd[ 4] = "CENTER"      ; cmd[ 5] = "TINY_LEFT"   ;
      cmd[ 6] = "LEFT"        ; cmd[ 7] = "BIG_LEFT"    ;
      cmd[ 8] = "LEFT_WHITE"  ; cmd[ 9] = "RIGHT_WHITE" ;
      cmd[10] = "ALL_WHITE"   ;
    }
    //String[] cmdval = new String[11] ;
    {
      cmdval[ 0] = "B00" ; cmdval[ 1] = "B01" ;
      cmdval[ 2] = "B02" ; cmdval[ 3] = "B03" ;
      cmdval[ 4] = "B04" ; cmdval[ 5] = "B05" ;
      cmdval[ 6] = "B06" ; cmdval[ 7] = "B07" ;
      cmdval[ 8] = "B08" ; cmdval[ 9] = "B09" ;
      cmdval[10] = "B10" ;
    }
    // show selected sensor data
    JLabel sensor_label = new JLabel("sensor data : ");
    cp.add(sensor_label);
    sensor_label.setBounds(50,400,80,20);
    cbxSensor = new JComboBox();
    cp.add(cbxSensor);
    cbxSensor.setBounds(150,400,120,20);
    for (int i = 0 ; i < 11 ; i++ ) {
      cbxSensor.addItem(cmd[i]) ;
    }
    // generate Font
    Font font = new Font("SansSerif",Font.PLAIN,16);
    // add Font information to textarea
    serial.edtText.setFont(font);
    serial.edtText.setLineWrap(true);
    serial.edtText.addKeyListener(new KeyInput());
    serial.scrPane.setBounds(50,50,400,300);
    cp.add(serial.scrPane);
    // define button
    JButton btnConnect = new JButton(new open_action());
    btnConnect.setBounds(50,350,100,36);
    cp.add(btnConnect);
    JButton btnDisconnect = new JButton(new close_action());
    btnDisconnect.setBounds(300,350,100,36);
    cp.add(btnDisconnect);
    JButton btnSend = new JButton(new send_action());
    btnSend.setBounds(300,400,80,20);
    cp.add(btnSend);
    JButton btnAuto = new JButton(new auto_action());
    btnAuto.setBounds(300,440,80,20);
    cp.add(btnAuto);
    JButton btnClear = new JButton(new clear_action());
    btnClear.setBounds(300,440,80,20);
    cp.add(btnClear);
    // register KeyInput class to KeyListener
    serial.edtText.addKeyListener(new KeyInput());
  }
  // internal class (bntConnect)
  class open_action extends AbstractAction
  {
    // constructor
    open_action()
    {
      putValue(Action.NAME,"Connect");
    }
    // event method
    public void actionPerformed(ActionEvent btnConnect_act)
    {
      serial.open();
    }
  }
  // internal class (bntDisconnect)
  class close_action extends AbstractAction
  {
    // constructor
    close_action()
    {
      putValue(Action.NAME,"Disconnect");
    }
    // event method
    public void actionPerformed(ActionEvent btnDisconnect_act)
    {
      serial.close();
    }
  }
  // internal class (bntSend)
  class send_action extends AbstractAction
  {
    // constructor
    send_action()
    {
      putValue(Action.NAME,"Send");
    }
    // event method
    public void actionPerformed(ActionEvent bntSend_act)
    {
      int index ;
      String stmp ;
      // get index 
      index = cbxSensor.getSelectedIndex() ;
      // generate code
      stmp = cmdval[index] + "\r" ;
      // show
      serial.edtText.append(stmp+"\n");
      // send
      serial.Serial_puts(stmp);
    }
  }
  // internal class (bntAuto)
  class auto_action extends AbstractAction
  {
    // constructor
    auto_action()
    {
      putValue(Action.NAME,"Auto");
    }
    // event method
    public void actionPerformed(ActionEvent btnAuto_act)
    {
      String xstmp ;
      int i ;
      int j ;
      int xdelay ;
      boolean flag ;

      String stmp ;
      // clear 
      stmp = "" ;
      try {
        FileReader in = new FileReader("txt.txt");
        BufferedReader br = new BufferedReader(in);
        String line;
        while ((line = br.readLine()) != null) {
          stmp += line ;
          stmp += " " ;
        }
        br.close();
        in.close();
        // store
        stmpx = stmp.split(" ");
      } catch (IOException e) {
        //
      }

      for (i = 0 ; i < stmpx.length ; i++ ) {
        xstmp = stmpx[i] ;
        // search
        flag = false ;
        for (j = 0 ; j < 11 ; j++ ) {
          if ( xstmp.equals(cmd[j]) ) { flag = true ; }
          if ( flag == true ) break ;
        }
        // send
        if ( flag == true ) {
          serial.edtText.append(cmdval[j]+"\n");
          // send serial port
          serial.Serial_puts(cmdval[j]+"\r");
        } else {
          // delay
          xdelay = Integer.valueOf(xstmp).intValue();
          try {
             Thread.sleep(xdelay);
          } catch (InterruptedException e){
          }
          serial.edtText.append(xstmp + "\n");
        }
      }
    }
  }
  // internal class (bntClear)
  class clear_action extends AbstractAction
  {
    // constructor
    clear_action()
    {
      putValue(Action.NAME,"Clear");
    }
    // event method
    public void actionPerformed(ActionEvent btnClear_act)
    {
      serial.edtText.setText("");
    }
  }
  // key event
  class KeyInput extends KeyAdapter
  {
    String   stmp;
    String[] stmp_array;
    int lineNum;

    public void keyPressed(KeyEvent e)
    {
      // get key then echo to textArea
      if ( e.getKeyCode() == KeyEvent.VK_ENTER )
      {
        //serial.edtText.append("\n");
        stmp = serial.edtText.getText();
        stmp_array = stmp.split("\n",0);
        lineNum = stmp_array.length - 1;
        // send serial port
        serial.Serial_puts(stmp_array[lineNum]+"\r");
      }
    }
  }
}

public class rstst
{
  private final static int my_frm_width  = 500 ;
  private final static int my_frm_height = 500 ;

  public static void main(String args[])
  {
    MFrame frame = new MFrame();
    // 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // set dimension
    frame.setSize(my_frm_width,my_frm_height);
    // show
    frame.setVisible(true);
  }
}

 センサー情報の文字列とコマンドを配列に入れ
 指定されたセンサー情報から、コマンド文字列
 を生成し、継続時間をsleepで作ります。

 新たに構築した調整環境を使うと、早速バグが出ました。
 センサー情報でサーボを動かしますが、動かした後、中央
 にステアリングを戻していません。

 自動車の運転と同じで、進路を変えたなら、ステアリングを
 中央に戻さないと、その状態を維持します。これではライン
 トレースになりません。

 サーボモータで、ステアリングを中央から動かしたなら
 然るべき時間後に、中央に戻します。

 NORMAL、CRANK、LANE_CHANGEの3モードの中で、ステアリング
 を中央に戻す操作は、LANE_CHANGEで必要になります。

 NORMAL、CRANKでは、センサー情報に応じたサーボモータと
 DCモータの制御をかけるだけでよいこともわかりました。

目次

inserted by FC2 system