ArduinoI/Oライブラリの製作

Daisukeh 2009/07/25 17:24 作成
Daisukeh 2009/07/27 08:30 追記
Daisukeh 2009/08/09 10:52 移設

記事一覧

ArduinoのGAINER化

ArduinoとGAINER  この記事では、processingを使ってarduinogainerと同じ手順で操作するためのライブラリを紹介する。これまでにもarduinogainerの設計思想が異なっている、ということはサイトやブログで何度か説明してきた。arduinoハードウェア独立型、つまりあらかじめパソコンで作成したプログラムを転送(アップロード)しておいて、以降は必要がない限り電源だけで動作するエレクトリック・ガジェットを製作するのに便利な仕組みになっている。一方のgainerパソコン依存型、つまりパソコンの外部入出力デバイスとしての位置付けであって、ハードウェアにプログラムを転送することなく、パソコンのアプリケーションと連携して動作するようになっている。ふたつのデバイスに共通することは、パソコンを使ってインタラクション・デザインをする場合には、デバイスの独立性は重要ではないという点だ。gainerはそのあたりを割り切ってしまうことで、入出力機能をモード別にカスタマイズできる仕様になっている。(PSoCマイコンにインプリメントすることで、アンプなどを外付けすることなくコンフィギュレーションで対応できるのだ。)arduinoは基本的にはAVRマイコンができることはほとんどできるが、その仕組みは自分で作らなければならない。(センサーやアクチュエータの接続には電子回路を拡張する必要もある。そのための「シールド」と呼ばれるアドオン・ボードもある。)

MAX/MSPによるFirmataサンプル  そこで「arduinogainer化することはできないか?」というアイデアが湧いてくるのだ。ハードウェア独立型のガジェット製作はあまり頻繁にしないのであれば、arduinoを単純な入出力デバイスとして定義してしまうことによって、毎回プログラムを転送しなくても済むことになる。つまりgainer的設計思想のタイニー版を作り込もうということである。いろいろ調べてみると、これと同じようなアイデアを持つ人は案外と多いようで、Arduino IDE(0016で確認)では標準でFirmataStandardFirmata)というサンプルコードが存在することがわかった。このライブラリはprocessing用のライブラリと一緒に提供されており、Arduino公式サイトFirmata公式サイトに多くの情報が掲載されているのだ。仕組みの概要は前記したものと同じだが高い柔軟性を持っているため、gainerと同じようにarduinoをコントロールできる「らしい」。この「らしい」というのは自分の環境では安定動作が確認できなかったためだ。自作ArduinoATmega8)とArduino Duemilanoveで動作確認したのだが、processingのコードでarduinoオブジェクトを生成すると、通信回線がオープンすると同時に自動リセット(DTRアクティブ)がかかる。この後ブートローダがFirmataを起動するまでに10秒程度待ち時間がある。(これって俺の環境だけなのかな?)この待ち時間はデッドタイムになっているらしく、processingから入出力指令を送信してしまうと、もちろん正常に受信されない(ロストデータとなる)ため動作が不安定になる。当初この現象をFirmataのversion2(現行の最新版)で試して確認した。その後でversion1でも確認したが現象は同じだった。自動リセットは無効にすることもできる(自作Arduinoはジャンパー、Arduino Duemilanoveはパターンカット)のだが、そもそもそういう操作を自動化しようとしているので本末転倒なのだ。

Firmataの動作が不安定

Arduino IDE付属のFirmataサンプル  なんとかFirmataのソースコードを追いかけてみたのだが、そのロジックに複雑な通信制御などは一切介在していないことがわかった。基本的な動作はversion1のスケッチ(プログラム)を見るとよくわかった。コマンドの送受信に対応したピンの入出力方向やデータのやりとりが、メインループ中にシンプルに組み込まれていた。version2ではライブラリのコア部分はC言語のコードで提供されていて、ビルド時にリンクされるようだ。processingのライブラリはSerialオブジェクトと組み合わせて使うようになっており、ソースの他にJARファイルで提供されている。以下に掲載するコードはarduinoのスケッチで、入出力混在モード、全入力モード、、全出力モードの3モード構成とした。アナログ入力はどのモードでも可能だが、通信プロトコルのビット幅を節約したので、8ビット(0~255)の分解能にしてある。アナログ入力の値は読み出しリクエストをしてから、返送される2バイトのデータを処理することとした。デジタル入力はピンのデータ値が変化した場合に、自動的にarduinoから上位あるいは下位のバイトデータとして送信することにした。デジタル出力も同様に上位か下位のバイトデータをarduinoに送信することで即時反映される仕組みにした。また、arduinoが動作していることを確認できるように、1秒感覚でタイミングデータを送信し、標準搭載のLEDをフリッカさせるようにした。(モード設定により無効にすることができる。)

プログラミング

ArduinoIO.pde(Arduino用)

// ArduinoIO (tributed/inspired by GAINER)   version1.03 09/07/25 Daisukeh
// general I/O modularize
 
#define CMND_MODE       0x00    // mode command
#define CMND_AIO_L      0x20    // analog  I/O (low)  command
#define CMND_AIO_H      0x40    // analog  I/O (high) command
#define CMND_DIO_L      0x80    // digital I/O (low)  command
#define CMND_DIO_H      0xc0    // digital I/O (high) command
 
#define MODE_DEFAULT    0x01    // default mode (AI6,AO2,DI6,DO6)
#define MODE_OUTPUT     0x02    // output mode  (AI6,AO2,DO12)
#define MODE_INPUT      0x03    // input mode   (AI6,DI12)
#define MODE_RESET      0x04    // reset
#define MODE_NOFLICK    0x08    // no flicker (pin13:LED)
#define MODE_TICK       0x10    // second tick/synchronize
 
////////// INTERFACE //////////
 
unsigned long tickms = 0;        // second tick counter (milli-seconds)
boolean flick = false;          // flicker enabled
byte mode = 0;                  // I/O mode
int digital_lo, digital_hi;     // digital bit data
int analog_dt;                  // analog temporary data
 
////////// IMPLEMENTATION //////////
 
void setup()
{
  Serial.begin(57600);          // serial baudrate
  setupMode(MODE_RESET);        // setup mode
}
 
void setupMode(byte data)
{
  // process flags
  if(data & MODE_RESET) data = MODE_DEFAULT;
  flick = !(data & MODE_NOFLICK);
  if(data & MODE_TICK) tickms = millis() + 1000;
 
  // setup system mode
  data &= 0x03;
  if(!data) return;
  mode = data;
  for(int i = 2; i <= 13; i ++) digitalWrite(i, LOW);  // all pins low
  switch(mode)
  {
    case MODE_DEFAULT :    // AI6,AO2,DI6,DO6
      for(int i = 2; i <=  7; pinMode(i ++, INPUT));
      for(int i = 8; i <= 13; pinMode(i ++, OUTPUT));
      break;
    case MODE_OUTPUT :     // AI6,AO2,DO12
      for(int i = 2; i <= 13; pinMode(i ++, OUTPUT));
      break;
    case MODE_INPUT :      // AI6,DI12
      for(int i = 2; i <= 13; pinMode(i ++, INPUT));
      break;
  }
}
 
void loop()
{
  tick();              // second tick signal/flicker
  receiveCommand();    // processing received command
  changeState();       // check input pin state/send commands
}
 
void tick()
{
  // check time lapse
  unsigned long ms = millis();
  if(ms < tickms) return;
  Serial.print((CMND_MODE | MODE_TICK | mode), BYTE);    // send tick signal
  Serial.flush();
  tickms = ms + 1000;
 
  // flicker (pin13:LED)
  if(flick) digitalWrite(13, ((digitalRead(13) == HIGH) ? LOW : HIGH));
}
 
void receiveCommand()
{
  // receive command
  int i, n, b;
  if(Serial.available() == 0) return;
  char data = Serial.read();
 
  // process command
  switch(data & 0xc0)
  {
    default :
      if(!(data & 0xe0))
      {
        // CMND_MODE
        setupMode(data);
      }
      else 
      {
        // CMND_AIO_L
        analog_dt = data & 0x1f;
        i = data & 0x7;
        if(i < 6)
        {
          // check AI(0-5) value
          analog_dt = 0;
          n = analogRead(i) >> 2;
          Serial.print((CMND_AIO_L | ((n << 3) & 0x18) | i), BYTE);
          Serial.print((CMND_AIO_H | ( n >> 2)),             BYTE);
        }
      }
      break;
 
    case CMND_AIO_H :
      // update AO(9,10:PWM) value
      if(!analog_dt) break;
      i    = ((analog_dt & 0x7) - 6) + 9;
      data = ((data << 2) & 0xfc) | ((analog_dt >> 3) & 0x03);
      analogWrite(i, data);
      break;
 
    case CMND_DIO_L :
      // update DO(low:2-7) state
      b = data & 0x3f;
      for(i = 2; i <=  7; i ++, b >>= 1)
        digitalWrite(i, ((b & 1) ? HIGH : LOW));
      break;
 
    case CMND_DIO_H :
      // update DO(high:8-13) state
      b = data & 0x3f;
      n = flick ? 12 : 13;
      for(i = 8; i <= n; i ++, b >>= 1)
        digitalWrite(i, ((b & 1) ? HIGH : LOW));
      break;
  }
}
 
void changeState()
{
  int i, b;    // index,bits
 
  // check DI(low:2-7) state
  for(b = 0, i = 7; i >=  2; i --) 
    b = (b << 1) | ((digitalRead(i) == HIGH) ? 1 : 0);
  if(b != digital_lo) 
    Serial.print((CMND_DIO_L | (digital_lo = b)), BYTE);
 
  // check DI(high:8-13) state
  for(b = 0, i = (flick ? 12 : 13); i >= 8; i --)
    b = (b << 1) | ((digitalRead(i) == HIGH) ? 1 : 0);
  if(b != digital_hi)
    Serial.print((CMND_DIO_H | (digital_hi = b)), BYTE);
}

 processingのシリアル通信オブジェクトは、開始時と終了時に必ずDTRをアクティブにする。これはRS232Cの通信手順でハードウェアフロー制御をすることを考えれば自然なのかもしれない。それが原因でarduinoの自動リセットが働くのだが、どんな機械でも自動でリセットされて初期状態に戻すことは、正常にデバイスを動作させるのに有効な手段であるということも否めない。Firmataでは確認しなかったが、ターゲットデバイス(この場合はarduino)との通信を確立するためには回線だけでなくプロトコルでの接続も確認するのがアプリケーションにとって安全だとも言える。いろいろ考えた末にprocessingが起因するリセットが頻発することなどから、敢えて通信接続チェックを能動的に行うのではなく、1秒間隔で送信されるタイミングデータを利用して受動的に存在確認することが安全で簡便だという結論に至った。このファームウェア・スケッチを利用して入出力が可能であることももちろん実証済みである。processingのサンプルコードも添付しておくこととして、クラス化したArduinoIOライブラリも後日紹介しようと思う。

ArduinoIO_sample.pde(Processing用)

import processing.serial.*;
 
Serial arduino;
int combfr;
int state = 0;
boolean flick = false;
color bgcolor = color(120);
int radius = 10;
 
void setup()
{
  size(300, 300);
  arduino = new Serial(this, Serial.list()[0], 57600);
}
 
void draw()
{
  while(arduino.available() > 0)
  {
    int data = arduino.read();
    if(data == 0x11)
    {
      state = 2;
      flick = !flick;
      arduino.write(0xc0 + (flick ? 0x08 : 0x10));
      arduino.write(0x20 + 0);
    }
    if((data & 0xc0) == 0x80)
    {
      int r = 0, g = 0;
      if((data & 0x01) != 0) r = 120;
      if((data & 0x02) != 0) g = 120;
      if((r == 0) && (g == 0)) bgcolor = color(120);
      else                     bgcolor = color(r, g, 0);
    }
    if((data & 0xe7) == 0x20) combfr = (data >> 3) & 0x03;
    if((data & 0xc0) == 0x40)
    {
      radius = ((data << 2) & 0xfc) + combfr;
      arduino.write(0x20 + 0);
    }
  }
  switch(state)
  {
    case 1 :
      background(bgcolor);
      break;
    case 2 :
      background(255);
      state = 1;
      break;
    default :
      background(0);
      break;
  }
  ellipse((width / 2), (height / 2), radius, radius);
}

参考資料など

failed to fetch data: unkown error

failed to fetch data: unkown error

failed to fetch data: unkown error

failed to fetch data: unkown error

failed to fetch data: unkown error

failed to fetch data: unkown error

やっぱりFirmataは動いた!

Daisukeh 2009/07/27 08:30 追記

 週末の暑い日中にゴミ箱の上で再追試をして動作を確認してみたら、自作ArduinoDuemilanove 328もちゃんと動いた!上記の自動リセットの問題はやはり残ってしまうが、それ以外では問題はないようだった。USB接続では自動リセットも問題にはならない様子で、これに関してはソースコードかサイトに注釈が書かれていたようにも思う。とにかく動作したので、この詳細はブログ「Firmataが動いたよ!」を参照して欲しい。あーよかったーLOL

掲示板

, 2012/05/21 23:15
It's good to get a fresh way of lokoing at it.
, 2018/07/29 22:41
contact@protonmail.ch
スーパーコピーブランド専門ショップ時計 バッグ 財布N級品販売通販
全品送料無料!!
弊社は価値をつけてルイヴィトンを販売して、シャネル
、グッチなど。
◆2018年は最も新型に人気があって、新しい素材の商品到着! 人気ブランド品大注目
◆信用の第1、風格は多くて、品質は良いです!
◆運賃の無料(日本全国)が予約購入することを期待しています!
◆弊社の商品は絶対的な自信があります。
ぜひ、見てくださいね!!
海外スーパーコピーのスーパーコピー バッグ、アクセサリー
スーパーコピー時計、貴金属の(リサイクル品)のスーパーコピー販売買取
日本超人気スーパーコピーブランド時計激安通販専門店
2018年最高品質時計コピー、国際ブランド腕時計コピー、
業界唯一無二.世界一流の高品質ブランドコピー時計。
人気新作ブランドコピー財布、腕時計、雑貨、小物商店
日本的な人気と信頼を得ています。
激安、安心、安全にお届けします.品数豊富な商品情報HPはこちら!!どしどしご来店ください!!!
商品数も大幅に増え、品質も大自信です(*^v^*)
日本では手に入らない商品も、全て卸売りします。
価格、品質、自信のある商品を取り揃えておりますので、
当店の主要な経営のブランド:Louis Vuitton(ヴィトン ) C.Dior(ディオール)
シャネル(シャネル) グッチ(グッチ) Coach(コーチ) Rolex(ロレックス)など.
当店は主に経営する商品:かばん.バッグ .財布 .キーケース. 手帳.腕時計など.
当店の商品は特恵を与える。
興味あれば、是非ご覧下さい
日本な人気と信頼スーパーブランドコピー専門店
---------------- ----------------- ---------------- ---------------
■経営する商品:バッグ、財布、腕時計 その他小物。
---------------- ----------------- ---------------- ---------------
■経営するブランド:ルイヴィトン、シャネル(シャネル)、グッチ(グッチ)、
コーチ(COACH)、ロレックス(ROLEX)、プラダ(PRADA)、 ディオール(DIOR)、
ブルガリ(BVLGARI)、オメガ(オメガ)、カルティエ(CARTIER)。
---------------- ----------------- ---------------- ---------------
■実物写真、付属品を完備しております。
■迅速、確実にお客様の手元にお届け致します。
■低価格を提供すると共に、品質を絶対保証しております。
■商品の交換と返品ができます。
---------------- ----------------- ----------------r\n-------------
◆富な品揃えで最新作も随時入荷致しておりますので、ごゆっくりご覧ください。
, 2018/11/09 10:28
ルイヴィトン コピー品
世界ブランドコピー業内最高レベルのルイヴィトン コピー品(N級品)をお客様に提供します。
ルイヴィトン財布コピー、ルイヴィトン財布、財布ヴィトン、スーパーコピーなど豊富な物件を揃いています。
当店はすべての商品はサイトに掲載していません。
お探しの商品が見つからない場合、お気軽にお問い合わせください。
Enter your comment
 
 
programming/embed/arduinoi_oライブラリの製作.txt · 最終更新: 2009/08/09 10:56 by daisukeh
 

Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS
Driven by DokuWiki Powered by Google do yourself a favour and use a real browser - get firefox ! GIMP is the GNU Image Manipulation Program. Adobe Flex smarty : Template Engine