ラベル 工作 の投稿を表示しています。 すべての投稿を表示
ラベル 工作 の投稿を表示しています。 すべての投稿を表示

2015年6月19日金曜日

netduino 3 wifi で雨量確認ガジェットを作る




最近,研究に使う関係で色々なマイコンを調べていますが,その中でも比較的最近発売された netduino 3 wifi というのがおもしろそうだったので,個人的に購入して遊んでみました.

2013年8月17日土曜日

Android タブレットで倒立振子

突然ですが,諸般の事情で Android タブレット(Nexus 7)を制御器としたセグウェイっぽい自走式倒立振子を作りました.忘れないうちに製作の要点をメモしておきます.後日気が向いたときに詳細な記事を書くかもしれません.
Android タブレットは内蔵するジャイロセンサで角速度を計測し,モータに印加する制御入力の計算を行います.腕のように見えるのはレゴブロックで作られたバンパーで転倒時と机からの落下時に液晶画面を守ります.

IOIO-OTG と HUB-ee Wheel による製作容易なハードウェア

ハードウェア的に特に重要な部品は IOIO-OTG と HUB-ee Wheel です.


上の写真が IOIO-OTG で,これを介して Android からモータを駆動することができます. いわゆる ADK と似たような機能を持ちますが小型であることをはじめとして,様々な面で扱いやすいと思います.


上の写真は HUB-ee Wheel で,一見タイヤに見えますが中にモータ・モータドライバ・エンコーダを内蔵している便利部品です.エンコーダがかなり粗く(4逓倍で128カウント/回転)カウンタを内蔵していない点が少し残念ですが,レゴブロックと簡単に結合でき,ハードウェアの製作を飛躍的に簡単にしてくれます.

また,今回は適当な Nexus 7 専用ケースに両面テープで電池などの部品とレゴブロック2本を接着し,あとはレゴブロックを嵌め合わせることで HUB-ee Wheels を固定し,バンパーなどを構築しています.


制御器の連続時間実装

ソフトウェア,つまり制御理論の面でやや特殊なのは制御器の連続時間実装を行っている点です.というのも,Android は非リアルタイムOSで一定周期でのジャイロセンサによる計測や制御入力の更新が困難だからです.実際 IOIOLib Application Framework で何も考えずに制御ループを回したときの実行間隔は以下のようになります.


概ね 5 ms 程度の間隔でループが回っているものの 20 ms 以上の間隔になることもしばしばあり,離散時間システムとしての実装には多少無理があることがわかります.

倒立振子のモデリングと制御器の設計は特に特殊なところはありません.

今後の課題

現状では IOIO-OTG がエンコーダのカウントをサポートしておらず,Androidのソフトウェアによる計数を行っているので,高速に移動したり制御周期が長くなったりするとエンコーダの取りこぼしが発生してしまいます.

本来なら Android 端末を使った自走式倒立振子のメリットとして,カメラやネットワークを簡単に利用できることが挙げられるべきですが,この問題のために制御周期への影響が大きいと考えられるこれらの機能が使いにくいのが残念なところです.

本格的に遊ぶためにはエンコーダ用のカウンタ回路を IOIO-OTG の外部に設けるべきであると考えられます.


2012年4月30日月曜日

Arduino とレゴで倒立振子(2)モータドライバの設計

前後の記事は
です.

少しずつ書いている実験用倒立振子製作メモですが,今回はモータドライバの設計について説明します.前回述べたようにモータの電流制御を行う必要があることと電源がUSBであることを踏まえると,モータドライバには
  • モータ電圧5V,ロジック電圧5Vで動作
  • 電流容量1A以上
  • 31kHz程度で電圧をON/OFFすることが可能
といった性能が求められます.電圧・電流に関する条件はUSBバスパワーの仕様から直接生じるものですが,最後の条件は電流制御に必要とされるPWMキャリア周波数によるものです.

2012年4月22日日曜日

Arduino とレゴで倒立振子(1) 設計意図

続きの記事は
  • Arduino とレゴで倒立振子(2)モータドライバの設計
  • Arduino とレゴで倒立振子(3)電源の性能
  • です

    4コマ(6時間)で制御工学を履修していない学生さんに倒立振子を制御してもらうという大変責任重大な学生実験の担当を拝命しました.

    引き継いだ実験装置もあったのですが,20年前のPC-9801で動いており,たまにエラーが出る状況だったので,学生実験に最適化したシステムに入れ替えようと思い立ち,マイコンは Arduino,機械部分はレゴというちょっと変わった構成で倒立振子を製作しました.

    実験装置の外観


    予備機製作の際のマニュアルも必要ですし,製作に必要な情報を徐々にブログにまとめていこうかと思います.第一回はこの実験装置の設計で特徴的なところをまとめ,大雑把な設計意図について説明します.

    2010年10月10日日曜日

    こんなポータブルDVDドライブが欲しい

    僕が参加する学会の資料はCD配布の場合が多いのですが,CDドライブがあるノートPCやポータブルCDドライブを用意するのは結構かさばります.CDドライブはCDのサイズより小さくならないのがよろしくないですね.

    そこで,こんなポータブルDVDドライブがあったらいいなーというのを考えてみました.何かのはずみで材料が手に入ったら作りたいので,ここに記録しておきます.

    こんな感じで回転中のメディアが露出してるドライブは,近未来な設定の漫画とかでは出てきますが,レーザーや回転部の危険があるせいか実際の製品では見ませんね.ミスでレーザーを見ないようにするカバーと,そこそこ安定した足は実用上必要なんじゃないかなぁ…

    あと,絵では画力の関係で省略していますが,背面と側面の足は収納時にはゴミがヘッドに入るのを塞ぐような構造にすると良いと思います.

    でもそのうち学会の配付資料もネット配布がメインになって,こんな悩みはなくなるんでしょうね.

    2010年2月12日金曜日

    小型で安価な回転角を検出する装置

    ホビーでロボット系の工作をする際に,モーターの回転角や回転速度の検出が良く問題になると思います.RCサーボがこの手の工作で頻繁に使われている理由として,角度の検出部を自分で工作することが困難なことがあげられると思うのですがどうでしょう?

    アナログ型光学式ロータリーエンコーダ


    そこでここでは,アナログ型の光学式ロータリーエンコーダによって角度を検出する方法を提案してみます.通常光学式のロータリーエンコーダにおいては下の図のようなスリットを持った回転円板を用います.
    このような円板は手作りすることが困難であり,高精度の物は高価になります.また,絶対値型のエンコーダはスリットやセンサーの数が多く,自作は非常に困難で大型になってしまいます.そこで,ここでは以下のようなグレースケールを持つ円板
    を用いて,以下の図のように配置されたセンサーを用いることを考えます.


    グレースケールを持つ円板はプリンタで簡単に作成できますし,センサの組み付け精度などもそれほど必要とされないのでこのような装置は比較的簡単に作成することが出来ます.

    試作機

    次に実際に試作品を作ってみた結果を示します.
    円板はプリンタで印刷したもので,後ろの田宮の小型ギアボックスは回転軸の固定&テスト用です.


    センサー部は適当に買ってきた反射型のフォトインタラプタを2個,回転軸について90度対称な位置に配置しただけです.


    組み合わせると下の写真のような感じになります.


    動作テストの様子です.


    動画で使っている円板は黒い部分の半径を変化させてグラデーション円板の代用とした物です.透過型のフォトインタラプタを用いる場合やグレーが使えない場合に有用なのではないかと思います.
    いい加減な工作ですが,それらしい波形が出ていることが確認できます.もう少し真面目に作れば,実用的な角度センサになるのではないでしょうか.

    2009年5月26日火曜日

    Arduinoで簡易オシロスコープ

    2013/4/22 ライセンスを修正BSDライセンスとしました
    Arduinoで簡単に使える簡易オシロスコープもどきを作ってみました.ちょっとした実験にはなかなか便利なので公開しておきます.

    スクリーンショット

    全体図scr1
    マウスで周波数などの読み取りも可能
    scr2

    操作法

    • [↑][↓] 時間軸の変更
    • [space] データ取得の停止/再開
    • [s] データをcsv形式で保存
    • [マウス操作] 値の読み取り・ドラッグで周波数読み取り

    インストール

    • 下記のソースの末尾・Arduino用のプログラムの部分をArduinoに書き込んでおく.
    • 下記のソースをProcessingにコピーし,シリアルポートの設定とフォントの生成/設定を行う.
    • 実行してみる

    ソース


    // ArduinoScope v1.0.0
    // 
    // Note:
    //  1. please confirm serial port setting
    //  2. prepare font
    //  3. Arduino code is attached at the end of this code
    
    // Copyright (c) 2009-2013 I. Maruta <ichiro.maruta@gmail.com>
    // All rights reserved.
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    // 1. Redistributions of source code must retain the above copyright
    //    notice, this list of conditions and the following disclaimer.
    // 2. Neither the name of the author nor the names of its contributors
    //    may be used to endorse or promote products derived from this software
    //    without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    // SUCH DAMAGE.
    
     
    
    import processing.serial.*;
    
    Serial ArduinoPort;  // Create object from Serial class
    
    int NumOfScopes,NumOfInput=2;
    int data_span=10000;
    Strage dfs = new Strage();
    Scope[] sp;
    
    int fontsize=16;
    PFont myFont;
    
    void setup() 
    {
      // Serial Port 
      println(Serial.list());
      String portName = Serial.list()[0]; // TODO: automatic detection?
      ArduinoPort = new Serial(this, portName, 38400);
      ArduinoPort.bufferUntil(10);
    
      // Screen
      size(800, 600);
      NumOfScopes=2;
      sp = new Scope[NumOfScopes];
      sp[0]= new Scope(0,50,10,width-100,height/2-35,512,-512,1000);
      sp[1]= new Scope(1,50,height/2+15,width-100,height/2-35,1024,0,1000);
    
      myFont = loadFont("Dotum-16.vlw");
      textFont(myFont,fontsize);
    }
    
    class Scope{
      int input_id;    // corresponding input
      int posx,posy;   // screen position of the scope
      int sizex,sizey; // pixel size of the scope
      float yu,yl;     // range of y is [yl,yu]
      int tspan;       //
      int ngx,ngy; // number of grids
      float maxposx,maxposy,minposx,minposy,maxx,minx,maxy,miny;
    
      Scope(int did,int px,int py,int sx,int sy,float syu,float syl,int ts){
        input_id=did;
        posx=px; 
        posy=py;
        sizex=sx; 
        sizey=sy;
        yu=syu; 
        yl=syl;
        tspan=ts;
        ngx=10; 
        ngy=4;
      }
    
      void grid(){
        pushStyle();
        fill(255,196);
        stroke(0,0,150);
        for(float gx=sizex; gx>=0; gx-= (float)sizex/ngx){
          line(posx+gx,posy,posx+gx,posy+sizey);
          textAlign(CENTER,TOP);
          text((int)map(gx,sizex,0,0,-tspan),posx+gx,posy+sizey+2);    
        }
        for(float gy=sizey; gy>=0; gy-= (float)sizey/ngy){
          line(posx,posy+gy,posx+sizex,posy+gy);
          textAlign(RIGHT,CENTER);
          text((int)map(gy,0,sizey,yu,yl),posx,posy+gy);    
        }
        popStyle(); 
      }
    
      int curx,cury;
    
      // draw cursor
      void cur()
      {
        // return if mouse cursor is not in this scope
        if(constrain(mouseX,posx,posx+sizex)!=mouseX 
          || constrain(mouseY,posy,posy+sizey)!=mouseY) return;
    
        pushStyle();
    
        // draw cross cursor
        stroke(255,0,0,196);
        fill(255,0,0,196);
        line(mouseX,posy,mouseX,posy+sizey);
        line(posx,mouseY,posx+sizex,mouseY);
    
        // draw measure if mouse is dragged
        if(mousePressed){
          line(curx,posy,curx,posy+sizey);
          line(posx,cury,posx+sizex,cury);
          textAlign(RIGHT,BOTTOM);
          text((int)map(curx,posx,posx+sizex,-tspan,0)+"ms, "+(int)map(cury,posy,posy+sizey,yu,yl),curx,cury);
          textAlign(LEFT,TOP); 
          text("("+nfp((int)map(mouseX-curx,0,sizex,0,tspan),1)+"ms, "+nfp((int)map(mouseY-cury,0,sizey,0,-(yu-yl)),1)+")\n"+nf(1000/map(mouseX-curx,0,sizex,0,tspan),1,2)+"Hz\n"+nf(TWO_PI*1000/map(mouseX-curx,0,sizex,0,tspan),1,2)+"rad/sec",mouseX,mouseY+2);
        }
        else{
          curx=mouseX;
          cury=mouseY;
          textAlign(RIGHT,BOTTOM);
          text((int)map(curx,posx,posx+sizex,-tspan,0)+"ms, "+(int)map(cury,posy,posy+sizey,yu,yl),curx,cury);
        }
        popStyle();
      }
    
      // draw min&max tick
      void minmax(){
        pushStyle();
        fill(255,128);
        stroke(0,0,100);
        textAlign(RIGHT,CENTER);
        line(posx,maxposy,posx+sizex,maxposy);
        text((int)maxy,posx,maxposy); 
        line(posx,minposy,posx+sizex,minposy);
        text((int)miny,posx,minposy); 
        textAlign(LEFT,CENTER);
        textAlign(CENTER,TOP);
        text("max",maxposx,maxposy); 
        textAlign(CENTER,BOTTOM);
        text("min",minposx,minposy+20); 
        popStyle();
      }
    
      // draw scope
      void Plot(){
        float sx,sy,ex,ey;
        int nof=0;
        DataFrame df_last = dfs.get(0);
    
        maxy=-1e10; // -inf
        miny=1e10;  // +inf
    
        // draw background (for transparency)
        pushStyle();
        noStroke();
        fill(0,0,64,64);
        rect(posx,posy,sizex,sizey);
        popStyle();
    
        // draw data plot
        pushStyle();
        stroke(0,255,0);
        smooth();
        strokeWeight(1);
        for(int idx=0;(dfs.get(idx).t>max(df_last.t-tspan,0)) && -idx<data_span;idx--){
          DataFrame df_new=dfs.get(idx);
          DataFrame df_old=dfs.get(idx-1);
          sx=(float) map(df_new.t, df_last.t, df_last.t - tspan, posx+sizex,posx);
          ex=(float) map(df_old.t, df_last.t, df_last.t - tspan, posx+sizex,posx);
          sy=(float) map((float)df_new.v[input_id],(float) yu,(float) yl,(float) posy,(float) posy+sizey );
          ey=(float) map((float)df_old.v[input_id],(float) yu,(float) yl,(float) posy,(float) posy+sizey );
          if(ex<posx){
            ey+=(sy-ey)*(posx-ex)/(sx-ex);
            ex=posx;
          }
          line(sx,sy,ex,ey);
          maxy=max(maxy,df_new.v[input_id]);
          if(maxy==df_new.v[input_id]){
            maxposx=sx;
            maxposy=sy;
          }
          miny=min(miny,df_new.v[input_id]);
          if(miny==df_new.v[input_id]){
            minposx=sx;
            minposy=sy;
          }
          nof++;
        }
        popStyle();
    
        //    minmax();    
    
        // draw current value of input
        pushStyle();
        textAlign(LEFT,CENTER);
        stroke(0,0,64);
        fill(0,255,0,196);
        text(df_last.v[input_id],posx+sizex,map(df_last.v[input_id], yu, yl, posy, posy+sizey ));
        popStyle();   
    
        grid();
        cur();    
      }
    }
    
    void draw() 
    { 
      background(0);
    
      for(int i=0;i<NumOfScopes;i++){
        sp[i].Plot();
      }
    }
    
    // input data buffer class
    // (now using ring buffer)
    class Strage{
      int cur;
      DataFrame[] DataFrames;
    
      Strage(){
        cur=0;
        DataFrames=new DataFrame[data_span];
        for(int idx=0;idx<data_span;idx++){
          int ret_v[] = new int[NumOfInput];
          DataFrames[idx] = new DataFrame(0,ret_v);
        }
      }
    
      void push(DataFrame d){
        cur = ((cur+1) %data_span);
        DataFrames[cur]=d;
      }
    
      DataFrame get(int idx)
      {
        int num=(cur+idx);
        for(; num<0; num+= data_span);
        return((DataFrame) DataFrames[num]);
      }
    
      void save()
      {
        String savePath = selectOutput();  // Opens file chooser
        if (savePath == null) {
          // If a file was not selected
          println("No output file was selected...");
        }else{
          PrintWriter output;
          output = createWriter(savePath); 
          DataFrame df_last = this.get(0);
          for(int idx=0;-idx<data_span;idx--){
            if(this.get(idx).t==0) break;
            output.print(this.get(idx).t-df_last.t);
            for(int k=0;k<NumOfInput;k++){
              output.print(","+this.get(idx).v[k]);
            } 
            output.println("");
          }
          output.flush();
          output.close();
        }
      }
    }
    
    class DataFrame{
      int t;
      int[] v;
      DataFrame(int st, int[] sv){
        t=st;
        v=sv.clone();
      }
    }
    
    boolean isactive=true;
    
    // buffering data from serial port
    void serialEvent(Serial myPort)
    {
      int[] vals=new int[NumOfInput];
      int timestamp;
      int[] splitdata;
      if( myPort.available() > 0) { 
        String datline=myPort.readString();
        splitdata=parseInt(datline.split(","));
        if((splitdata.length==NumOfInput+2)){
          timestamp=splitdata[0];
          for(int idx=0;idx<NumOfInput;idx++){
            vals[idx]=splitdata[idx+1];
          }
          if(isactive){
            if((timestamp-dfs.get(0).t)<0){
              dfs.cur--;
            }
            if((timestamp-dfs.get(0).t) > ((float)sp[0].tspan / sp[0].sizex/2.0) ){
              dfs.push( new DataFrame(timestamp,vals));
            }
          }
        }
      }
    }
    
    // keyboard user interface
    void keyPressed(){
      switch(key){
        // activate/deactivate scope update
      case ' ':
        isactive=!isactive;
        break;
        // save record
      case 's':
        dfs.save();
        break;
      case CODED:
        switch(keyCode){
          // Increse time span
        case UP:
          for(int i=0;i<NumOfScopes;i++){
            sp[i].tspan*=2;
          }
          break;
          // Decrease time span
        case DOWN:
          for(int i=0;i<NumOfScopes;i++){
            sp[i].tspan/=2;
          }
          break;
        }
        break;
      }
    }
    
    /* Arduino code
    void setup()
    {
      Serial.begin(38400);  
    }
    
    void loop()
    {
      Serial.print(millis());
      Serial.print(",");
      Serial.print(analogRead(0));
      Serial.print(",");
      Serial.print(analogRead(1));
      Serial.println(",");
    }
    */

    2009年4月15日水曜日

    通販できる海外のホビーロボット用部品店

    ネットを使うと海外からも簡単に部品が買えて良いですね.
    最近目を付けてる海外サイトをメモしておきます.

    • Gravitech
      Arduino nanoを売ってます.僕が注文したときは12日で届きました.ちなみに送料は$5.85.スイッチサイエンスさんから買った方が速いし,値段もトータルでは同じくらいのはず.
    • Dimension Engineering
      モータードライバー,センサーなど.僕が購入したときはUSPS First Classで送料$2.5,一週間くらいで着きました.急ぐのならメカロボショップさんでも購入できます.
    • RobotShop
      ロボット材料,モジュールなどなど.ルンバをbluetooth接続するキットとかを売っているのが気になる.日本からも通販できるようだけど,重量物は送料が怖い・・・
    • Pololu Robotics and Electronics
      モータードライバ,センサー等々.試したことはないけど,日本からも購入可能なはずです.配送はUSPS First Classのようなので,一週間そこそこで着くはず.送料は基板程度なら$2.5だと思います.急ぐのならメカロボショップさんでも購入できます.
    • Endurance
      R/Cラジコンの部品.PCTx (パソコンをラジコンの送信機にするデバイス)が売ってるのでメモ.
    • The Robot Marketplace
      なんか凶悪そうなモーターが売ってるのでメモ.パワー系ロボコン用ですね
    • SuperDroid Robots
      ロボット関連いろいろ.オムニホイールを扱っているのでメモ.
    • SparkFun
      Arduino関連が超有名.大抵のものはスイッチサイエンスさんで扱っているので,そちらから購入した方が良いでしょう.最近は日本橋でもSparkFun製品を結構見かけますね.

    2009年4月8日水曜日

    Gainer mini でオシロスコープもどき

    最近お手軽なマイコンが流行しているみたいで,僕も色々手を出しています.

    Gainer はパソコンとUSBで接続できて,Processing等のお手軽な言語で
    パソコン側から制御できるI/Oモジュールです.Gainer mini はその互換機で,より小型のモジュールになってます.
    プログラムが簡単なので,芸術作品とかに良く使われてるみたいですね.

    純粋な芸術作品にはあまり興味はないんですが,
    融通の利く計測装置として便利そうなので,一つ購入してオシロスコープもどきを作ってみました.
    パソコン側のスクリーンショットはこんな感じ


    Sparkfunのジャイロセンサー(MLX90609・1軸)と秋月の加速度センサー(KXM52-1050・3軸)を接続して動かしている動画.



    計測周期は4チャンネルで10msを若干切るくらいが限界のようですね.単チャンネルなら2ms前後までいけるかも知れません.
    OSごとの時刻取得関数に依存してしまいますが,10ms程度の制御周期でよければ制御にも使えそうな感じもします.ただ,MacのProcessingの実装では時刻取得関数millis()の精度が良くないようで,厳しいかもしれません.

    2009年3月22日日曜日

    使えそうな部品探索@日本橋(モータードライバ編)

    昔ほど頻繁に日本橋に行かなくなったので,どこの店にどの部品があるか把握できない・・・
    というわけで,今後のためにまとめておきます.今回はモータードライバ関連です.

    最初に店ごとにとってきたモータードライバ関連部品コーナーの写真,
    続いてカテゴリーごとの部品まとめになっています.

    あとトーカイとシリコンハウス共立は重要かと思いますが,見る時間がなかったので入ってません.

    ではカテゴリーごとのまとめ編

    • モータードライバIC
      一番楽な選択肢で,基本的に一つの部品でモータードライバが構成できます.
      この手のICでよく使われているICにTA7291とかTA8440とかTA8429などがあります.これらのICは,東芝のカセットレコーダー用のICで入手が容易ですが,バイポーラトランジスタでできてるICなので電圧降下が激しく(1~3Vくらい),発熱が大きいことなどから,電池で動くタイプのマシンには使いたくありません.また,スイッチ速度も遅いのでPWMにもむかないです.
      ちなみにTB****という型番のモータードライバはFETベースなので電圧降下が小さく使いやすいです.ただし,こちらは滅多に見かけませんが・・・
      TA****については,どこでも手に入るし,個人的にあんまり使わないので,ここではバッサリ省略してます.
      DCモーター用
      TA****以外のICってやっぱりほとんど日本橋では出回ってないですねー.
      このジャンルに関しては通販で探した方がいいかも.
      1. μPD16805GS
        パーツランドの部品棚ではMPD16805になってます.これはこれで正しい気もしますが,uPDって書いてあることの方が多いかな?
        はんだ付けが少し困難であることを除けば,田宮の工作セット系のモーターFA130とかRA260の制御に申し分ない性能で使いやすいICです.
      ステッピングモーター用
      あんまり使わないけど,ついでにリストアップ.
      1. STK672-050
        ユニポーラ定電流チョッパ方式(他励PWM方式)ステッピングモータドライバ(正弦波駆動)出力電流3.0A
      2. LB1845
        PWM 電流制御式 ステッピングモータドライバ
      3. TB6615PG
        3相/4相ステッピングモータドライバ
      4. (PMM8713)
        製造中止のステッピングモーター用IC.直接ステッピングモーターを駆動するドライブ能力はないそうです.
        今後の入手性に難はありそうですが,デジットにはまだあるようですね.
      ブラシレスモーター用
      いつか使おうと思って全然使ったことがないブラシレスモーター・・・
      この機会に使ってみるか?
      1. ECN3022SP
        ECN3022はIGBTを6個内蔵したワンチップ三相ブリッジICです。
        特に三相DCブラシレスモータ制御用に最適です。
      RCサーボモーター用IC
      使ったことないですが,RCサーボで使われているICも売っています.何度か調べようと思って調べ損ねているのでついでにまとめ.自作の機械をラジコン化するときに便利かな?
      1. NJM2611D
      2. M64611FP
      3. M52461GP
      データシートを見た感じだと,安価なRCサーボのほとんどはデッドバンド付きのP制御のようですね.

    • ゲートドライバ&MOSFET
      適したモータードライバが見つからない場合,大抵はディスクリート部品でMOSFETを使ったモータードライバを組むことになります・・・が,MOSFETのゲートを駆動する回路は電源投入時や電圧低下時の安全性,ゲート電圧の確保などを考えると結構難しく,この部分の間違いでモータードライバが炎上する事故がよく起きます.
      というわけで,僕はゲートドライバは可能な限りIC使って設計を避けることにしてます(笑)
      昔はゲートドライバICとかあんまり売ってなかったのですが,最近は結構売っているようで,いい時代になったものです.
      ゲートドライバ
      マルツパーツ/千石電商の参入で入手できるものがだいぶ増えたようです.
      D級アンプとかが流行ってるのも要因のひとつか?
      1. HCPL-3180
        2 Amp Output Current, High Speed IGBT/ MOSFET Gate Drive Optocoupler
      2. HCNW3120-000E
        2.0 Amp Output Current IGBT Gate Drive Optocoupler
      3. HCPL-316J-000E
        2.0 Amp Gate Drive Optocoupler with Integrated Desaturation Detection and Fault Status Feedback
      4. HCPL-3150-000E
        0.5 Amp Output Current IGBT Gate Drive Optocoupler
      5. HCPL-314J
        HCPL-3140-000E
        HCPL-314-000E
        0.4 Amp Output Current IGBT Gate Drive Optocoupler
      6. IRS2011SPBF
        HIGH AND LOW SIDE DRIVER
      7. IRS2110PBF/IRS2110SPBF/IRS2113PBF/IRS2113SPBF
        HIGH AND LOW SIDE DRIVER
      8. IRS21271SPBF/IRS21281SPBF
        CURRENT SENSING SINGLE CHANNEL DRIVER
      9. IRS2092PBF/IRS2092SPBF
        PROTECTED DIGITAL AUDIO DRIVER
      10. IRS20955SPBF
        PROTECTED DIGITAL AUDIO DRIVER
      11. TLP250 / TLP251
        IGBT/MOSFET駆動用フォトカプラ
        昔結構探してみつからなかった思い出が・・・
      FETアレイ
      たぶん4AM12(廃品種)とかMP4212
      みたいなPch×2,Nch×2の構成のFETアレイがよくつかわれてるんですが,今回なぜか見つからなかった・・・また探しておきます.
      1. MP4208
        Pch×4 RDS:0.2Ω ID 5A(Peak 10A)
      2. MP4209
        Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
      3. MP4210
        Nch×4 RDS:0.12Ω ID 5A(Peak 20A)
      4. MP4211
        Pch×4 RDS:0.16Ω ID 5A(Peak 20A)
      5. MP4410
        Nch×4 RDS:0.12Ω ID 5A(Peak 20A)
      6. MP4411
        Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
      7. MP4412
        Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
      8. MP6404
        Nch×3 Pch×3 RDS:0.12Ω(Nch) 0.16Ω(Pch) ID 5A(Peak 20A)



    2009年1月15日木曜日

    三叉ヘビ型ロボットの製作

    三叉ヘビ型ロボットというおもしろい構造のロボットが
    杉江研の石川先生たちによって研究されています。
    僕は研究に深く関わっているわけではありませんが、とてもいい動きをするロボットなので一度作ってみたいと思っていました。研究室には一応理論を検証するための機械がありますが、データを取ったり精度を確保するためにそれなりに大がかりな装置になっています。

    今回は、より単純に三叉の動きを楽しむために、小型で小回りの良いロボットを製作してみました。
    以下製作記録です。
    デモ用のプログラムを書き込んで動作

    いつもより多めにまわってます。
    学部生の勧誘で本部に出張する時とかに役立てる予定。

    2008年9月29日月曜日

    六足歩行機構

    昔作ったものをあさってたら六足歩行機構が出てきました.
    ブログのタイトルのところにあるアニメーションのような機構で,モーター1つで歩いてるような動きが出来ます.

    完成図
    実際の動作の様子

    2008年7月31日木曜日

    LQGによる倒立振り子の制御実験

    久しぶりにロボット的なものを作りたくなったので
    どうせなら制御理論の検証ができるものを…
    というわけで、Segway的な倒立振り子を作ってみた。

    全体図



    機械部分は入手性がよくて組み立て簡単な田宮模型の部品で固めました。
    本体はユニバーサルプレートで、たまたま手に入った透明プラスチックバージョンを使ってます。
    車輪はナロータイヤセット、ギアはハイパワーギアボックスHEだったと思います。
    もうちょっとギア比が低いハイスピードギアボックスの方がベターかもしれません。

    電池ボックスは熱に強い金属のやつを買ってきました。
    一度熱で端子付近のプラスチックが溶けたことがあるので…

    回路を実装する基板はSunhayatoのICB-88

    電池ボックスも基板もいい感じにユニバーサルプレートにくっつきます。

    回路


    回路も今後の補修のために部品の入手性がいいやつで…

    右の緑色の基板はトランジスタ技術の付録についてたR8C/Tinyの基板です。
    これはSunhayatoからも互換性のあるものが出てますね。

    真ん中の青色はSunhayatoの加速度センサーモジュールMM-2860

    左の青い基板は同じくSunhayatoのモータードライバモジュールMM-531です。
    電流容量0.7Aは心もとないので、2回路をパラレルにして使っています。
    同じチップなら特性もわりとそろっているので問題ないと思いますが
    あんまり誉められたもんじゃないですね。

    左下のディスクリート部品的な部分で2.4Vの電源から3.3Vの電源を作ってます。
    モーターの電源は電池直結です。

    右端のコネクターはE8aエミュレータを接続するためのもので
    上の3線は角速度ジャイロ(KRG-3)
    下の2線はデバッグ用のブザー
    左の4線は電池とモーターです。

    側面




    機械部分にあんまりこりたくないのでユニバーサルプレートと
    ねじとスペーサーでしのいでいます。
    基板を固定するビスがかなり長いのは転倒時に基板が地面に当たるのを防ぐためです。

    モーター



    モーターについてるセラミックコンデンサはブラシで発生するノイズを
    吸収するためのものです。
    マイコンと一緒にDCモーターを使う場合には必須らしいです。
    たしかに昔PICマイコンを使ってたときにはこれで誤作動しなくなりましたが
    最近のマイコンでも必要なのだろうか…

    ちなみにエンコーダはついてないので
    車輪の回転角は制御していません。角速度のみの制御です。

    制御



    最初は適当にPID的な制御でも立つかなーと思っていたのですが
    意外とチューニングに苦戦したので
    おとなしくモデルを構築してLQGを使ってみました。
    制御器が不安定システムになるようなので
    まぁなるべく極が左の方に来るように調節しています。
    制御器は3次のシステムで制御周期は10msです。
    R8Cでこの制御周期だと5次くらいまでなら何とかなるかな〜という感じでしょうか。

    やっぱりモーター周りのモデルが怪しいのですが、
    ロバスト制御の代名詞であるH∞制御とかだとこの手の怪しさは扱いにくいですね。
    そのあたりを扱える理論が必要なのだろうか…