Arduino勉強会

2014/12/29からのアクセス回数 6694

GMC-4との出会い

私が最初にマイコンを見たのが、「秋葉原のBIT-INN」に展示されていたTK-80でした。 *1

400px-TK-80.jpg

この基板の上にテンキーと7セグメントLEDが8個付いたのが、コンピューターかと思われるかも 知れませんが、初期のマイコンはテンキーを使って直接マシン語を打ち込んでプログラムを 入力していました。 *2

2009年6月に学研の「大人の科学Vol.24」 にTK-80を思わせる4-bitマイコンGMC-4が付録に付いてきたので、すぐに購入しました。

GMC-4.jpg

そこで、GMC-4用にC言語ライクな簡易言語コンパイラーを作った記事が GMC-4コンパイラー です。

この時は、アセンブラからマシン語に手で変換して、プログラムを組むことが大変だと思って 簡易言語のコンパイラーを1日仕事で作って公開しました。

Arduinoを使ってGMC-4を作る

Arduino勉強会で何を作りたいかと聞かれ、とっさに「GMC-4をArduinoで作ってみたい」と答えた のは、GMC-4を子供たちが作って、キーボードからプログラムを入力したら、マイコンのイメージ が変わるのではないかと思ったからです。

Arduino版GMC-4の部品

Arduino版GMC-4には、1個の7セグメントLEDと7個のLED、そして20個のタクトスイッチに 2個のトランジスタと10個の抵抗をユニバーサル基板に載せただけのとても簡単なものです。 後はArduinoのプログラムですべて処理します。

GMC4-Arduino.png

回路図

7セグメントの接続が画像と異なりますが、KiCADの練習で回路を書きました。

ついでに、プリント基板のパターンを作りました。

現バージョンのボードの配線は、以下の通りです。

GMC4-Brd.png

キーボードは配線だけ

Arduinoのライブラリにkeypadがあり、これはタクトスイッチを以下の様に配線するだけで マトリックスキーボードを作ることができる素晴らしいクラスです。*3

Keypad_pattern.jpg

スケッチの作成

ハードは下手くそでもソフトなら大丈夫ということで、以下のクラスを用意しました。*4

KeyBoard.h

KeyBoard.hでは、Keypadに渡す、キーマップと、入力文字から値を取り出すgetCode、キーが押されているかどうか 調べるisPressedメソッドを用意しました。

LED7Seg.h

7セグメントLEDとLEDアレイは、交互に表示するため、on、offのメソッドと値をセットするdrawメソッド 用意しました。

LEDArray.h

LEDアレイは、アドレスを表示するために使用するので、setAddressとgetAddressメソッドで値の読み書きをしています。

GMC4.h

GMC4をシミュレーションしているのが、GMC4.hに定義されているGMC4クラスです。 この中の、stepメソッドが1命令毎に処理するメソッドです。

GMC4.hの処理を理解するには、FX-マイコン・全マニュアル を参照してください。 *5

メインのスケッチ

メインのスケッチだけ、ソースをそのまま示します。 処理としては、キーボードからの入力に対する処理の切替をしているだけですが、 一つだけオリジナルのGMC4と異なる点があります。

それは、Arduinoのシリアルモニターを使ってGMC4用の機械語をパソコンから入力できることです。 これによってプログラムの確認がとても簡単になりました!

#include <Keypad.h>
#include <SoftwareSerial.h>
#include "GMC4.h"

SoftwareSerial mySerial(0, 11); // RX, TX

LEDArray  ledArray;
LED7Seg   led7Seg;
KeyBoard  keyBoard;
GMC4      gmc4(&keyBoard, &ledArray, &led7Seg);


byte lastCode;
byte addr;
byte mode;
byte key;

void setup() {
  mySerial.begin(9600);
  lastCode = gmc4.resetAll();
  ledArray.setAddress(0);
  led7Seg.setValue(0xF);
  mode = PROGRAM;
}

void readProgram() {
  while(mySerial.available()) {
    key = mySerial.read();
    if (key >= '0' && key <= '9')
      lastCode = key - '0';
    else if (key >= 'A' && key <= 'F')
      lastCode = key - 'A' + 10;
    else if (key == 'T') {
      gmc4.longTone();
      lastCode = gmc4.reset();
      ledArray.setAddress(gmc4.getAddr());
      led7Seg.setValue(lastCode);
      mode = PROGRAM; 
    }
    lastCode = gmc4.incr(lastCode);
    ledArray.setAddress(gmc4.getAddr());
    led7Seg.setValue(lastCode);           
  }
}

void loop() {
  if (mode == PROGRAM || mode == STEP_LedOffBeepOff || mode == STEP_LedOnBeepOn) {
    if (mySerial.available())
      readProgram();
    else
      key = gmc4.getKey();
   
    if (key != NO_KEY) {
      if ((key >= '0' && key <= '9') || (key >= 'A' && key <= 'F')) {
        addr = (lastCode > 0) ? lastCode << 4 : 0;
        lastCode = gmc4.getCode();
        addr += lastCode;
        led7Seg.setValue(lastCode);
      }
      else {
        switch (key) {
          case 'S':  // A SET
            lastCode = gmc4.addrSet(addr);
            ledArray.setAddress(gmc4.getAddr());
            led7Seg.setValue(lastCode);
            break;
          case 'I':  // INCR
            if(mode == PROGRAM) {
              lastCode = gmc4.incr(lastCode);
              ledArray.setAddress(gmc4.getAddr());
              led7Seg.setValue(lastCode);       
            }
            else if (mode == STEP_LedOffBeepOff || mode == STEP_LedOnBeepOn) {
              mode = gmc4.step();
              if (mode == STEP_LedOnBeepOn)
                ledArray.setAddress(gmc4.getAddr());
            }
            break;
          case 'R':  // RUN
            switch (lastCode) {
              case 1:
                mode = RUN_LedOffBeepOff;
                break;
              case 2:
                mode = RUN_LedOnBeepOff;
                break;
              case 5:
                mode = STEP_LedOffBeepOff;
                break;
              case 6:
                mode = STEP_LedOnBeepOn;
                break;
              default:
                mode = RUN_LedOnBeepOn;
            }
            gmc4.reset();
            ledArray.setAddress(gmc4.getAddr());
            gmc4.setMode(mode);
            break;
          case 'T':  // RESET
            gmc4.longTone();
            lastCode = gmc4.reset();
            ledArray.setAddress(gmc4.getAddr());
            led7Seg.setValue(lastCode);
            mode = PROGRAM; 
            break;       
        }
        addr = 0;
      }
    }
  }
  else {
    mode = gmc4.step();
  }
  gmc4.draw();
}

GMC4のスケッチは、以下のファイルをダウンロードしてください。

デバッグの方法

GMC4のようなシミュレータをArduinoで作る場合、デバッグがとても大変になります。

GMC4.hのデバッグは、MacOSのEclipseでダミーのKeyBoard, LED7Seg, LEDArrayを用意して 行いました。

参考として以下にソースを置いておきます。

動作確認

プログラムの動作を確認するため、FX-マイコン・全マニュアルの以下のサンプルで動作を確かめました。

以下に大人の科学のProgram1 15秒カウンタを動かしたときの画像とFacebookの動画のURLを 示します。

GMC4のプログラムは、以下の通りです。

アドレス命令記号命令コード
01TIYA
0111
02TIA8
0399
04CALE
05TIMRC
06CY3
07AO1
08CY3
09CALE
0ASHTS9
0BAIYB
0C11
0DJUMPF
0E11
0F33
10JUMPF
1100
1222
13CALE
14ENDS7
15JUMPF
1611
1755

最後に、Resetボタンを押します。

Arduinoのシリアルモニターから入力する場合には、上記の命令コードを並べて入力し、最後にTを付けます。

A189EC313E9B1F13F02E7F15T

実行するには、Runボタンを押します。

15秒タイマー.png

URL

lbeDuinoを使った2号機

lbeDuinoを使った2号機の記事を以下にまとめました。

コメント

選択肢 投票
おもしろかった 3  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。勉強会で分からなかったこと等、お気軽に問い合わせて下さい。

スパム防止に画像の文字列も入力してください。


(Input image string)

*1 Wikiペディアの画像を引用
*2 友人の浜野君が、これからはマイコンの時代が来ると言ったので、大学に入るなりすぐにプログラミングの勉強をしたのを覚えています。
*3 配線図は、ikkei blogの4×4のキーパッドを試してみたから引用しました。
*4 本来ならC++のクラスヘッダとクラス本体を分けるのですが、Arduinoのタブで使うことを考えてヘッダファイルだけで、クラスを作りました。
*5 命令の簡単な説明は、GMC-4コンパイラーにもあります。

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc