INDEX(各項目ごとの目次)

[HOME]  [Processing関係]  [Arduino関係]  [マテリアル関係]  [秋葉原工作マップ]

2008年用ですが、部分的に内容を更新しています(2010/06/14)。
また、[建築農業工作ゼミ2009-2010]とも連動していますので、そちらにも幾つかサンプルがあります。
:

6/08/2008

Arduino サーボ制御



サーボモータは、信号を送ると指定した角度まで回転するので、ロボットの間接部分にもよく用いられています。通常のアナログサーボであれば、回転角の範囲は0〜180度程度です。種類によっては、回転範囲が180度以下のものや、360度回転(連続回転サーボ、あるいは0〜360度の範囲で回転するサーボ180度のサーボを改造する例、もうひとつの改造例)するものもありますが、今回は180度の回転が可能な一般的なサーボを制御します。サーボもDCモータ同様、Arduino基盤に対しては過電流となる恐れがあるので、別電源を用意したほうが無難ですが、一つくらいであれば直接つないでもそれほど問題でないでしょう。
サーボには大抵5V線(赤)、GND線(黒)、信号線(白)の3つの線があります。そのままArduino基盤につなぐ場合、5V線、GND線をそれぞれ基盤の5V端子、GND端子へ接続し、信号線をPWM端子へつないでanalogWrite()で制御することができます。



analogWrite()で動かす方法:(動くけど多少不安定)
今回はPWM端子である3番ピンにサーボの信号線を接続し、可変抵抗器で操作します。可変抵抗器からのanalogRead()による読み取り値0〜1023を4で割って、0〜255の範囲にスケールダウンします。analogWrite()は0〜255の値を出力しますが、サーボの動作角度においてはおよそ0〜180度に対応します。例えば、出力値を127としてanalogWrite(3,127)であれば、約90度のところで停止します。パルス信号の性質上、1ループを約20ミリ秒にすると動きが安定します。そのために、delay(20)を最後に加えておきます。

Arduinoのプログラム:

void setup(){
//特になし
}

void loop(){
//可変抵抗器の値を読み込み4で割る
int val=analogRead(0)/4;
//アナログ出力
analogWrite(3,val); //0~255
//0.05秒ループにする
delay(20);
}


analogWrite()が0〜255なので、180度の回転範囲を256段階の分解能で出力できるということになります。ただし、この方法だとガタガタと不安定な動きになるかもしれませんので、以下の方法をおすすめします。


ライブラリを利用する方法(Arduino0018):
Arduino0016まではPWMの9番ピンと10番ピンだけにサーボを接続可能でしたが、Arduino0017以降では、ソフトに含まれているライブラリを使うことで最大12個まで接続可能です(Megaの場合最大48個)。
ただし、このライブラリを使用すると9~10番ピンのPWM機能は使えなくなります(Megaの場合は12~23ピンをサーボに使用すると11~12ピンのPWMが機能しなくなります)。つまり、サーボとanalogWrite()を同時に使うプログラムの場合は、analogWrite()に使用するピンとして9~10のピンを避ける必要があります。
「メニューバー>Sketch>Import Library...>Servo」を選択すると「#include <Servo.h>」が自動的に挿入されライブラリを使用可能にします。以下はArduino0018に内包されているServoライブラリの使用例です。attach()でサーボを接続するピンを指定し、write()で0~180の角度の値(整数値)をいれます。プログラム内でmap()を使っていますが、センサから読み込まれる値val(変数)の範囲0~1023をサーボの角度出力値0~180度に変換する方法です。


#include <Servo.h>

Servo servo;//サーボのインスタンス

void setup(){
//サーボの信号線を3番ピンに接続
//(PWMピン以外のピンにも接続可)
servo.attach(3);
}

void loop(){
//センサの読み取り値
int val=analogRead(0);
//map()を使って0~1023のセンサ読取り値を0~180の角度に変換
int deg=map(val,0,1023,0,180);
//サーボ出力
servo.write(deg);//0~180まで
}



精度をあげて制御する方法:writeMicroseconds()を使う
write()を使う方法は0~180度を180段階の分解能でしか角度設定できませんが、新たに加わった機能writeMicroseconds()によって、より細かく角度を設定することが可能です。この場合サーボにパルス(パルス幅)の値を送って角度を決定します。
例えば:

writeMicroseconds(500)で0度
writeMicroseconds(1500)で90度(中間位置)
writeMicroseconds(2500)で180度

という感じになります。つまり0~180度の範囲を500~2500の範囲に変換すればいいことになります。
しかし、サーボによって受け入れるパルス幅が異なるので仕様書などで確認してください。
各サーボの最小値や最大値を超えたパルスを送ってもそれ以上回転しないか、負荷を与えることにもなるので注意して下さい。
ちなみに、
servo.attach(ピン番号,最小パルス幅,最大パルス幅);
というように()内に3つの値をいれることができます。最小パルス幅はデフォルトでは544、最大パルス幅は2400に設定されているようです。これらの値で動く範囲を調節できます。


#include <Servo.h>

Servo servo;//サーボのインスタンス

void setup(){
//サーボの信号線を3番ピンに接続
//(PWMピン以外のピンにも接続可)
servo.attach(3);
}

void loop(){
//センサからの読取り値
int val=analogRead(0);//0~1023
//map()を使って0~1023を544~2400に変換
int pulseWidth=map(val,0,1023,544,2400);
//サーボ出力
servo.writeMicroseconds(pulseWidth);//変換したパルス幅値を代入:544~2400
}


上記プログラムでは、writeMicroseconds()を使うことで、0~180度の範囲を544~2400の範囲の分解能で動かすことができます(180度の範囲を2400-544=1856分解能、約0.1度単位で角度を調節可能)。上の場合はanalogRead()を使っているので、その精度に左右されます(つまり1024分解能)。


以下は2008までの内容です。参考までに。

その他のライブラリの使用例:
ArduinoのPlaygroundというサイトには、サーボのライブラリがあります。このライブラリをダウンロードして、Arduinoのフォルダ内にあるlibraries(Arduino-0011>hardware>libraries)に入れれば、Arduinoの画面のメニューバー>sketch>Import Library>Servoを選んで利用することができます(#include <Servo.h>という一文が自動的に書き込まれます)。このライブラリを利用すれば、PWM端子以外のピンにもサーボを接続することができます。servo.write()の()内に0〜180の整数値を入れることで角度を制御するので、分解能は180(1度ずつ)となります。analogRead()の0〜1023の値に0.176を掛けて出力値を0〜180にスケールダウンします。小数点の計算なのでfloat型の変数valにしてから、servo.write()の()内にint()を用いて整数化しています。最後のServo::refresh()を、周期が20ミリ秒以下にならないように、少なくとも50ミリ秒に一回は呼び出す必要があります。

#include <Servo.h>

Servo servo;

void setup(){
//サーボの信号線を3番ピンに接続
//(PWMピン以外のピンにも接続可)
servo.attach(3);
}

void loop(){
//読み取り値をスケールダウン
float val=analogRead(0)*0.176;
//サーボ出力
servo.write(int(val));
//周期を更新
Servo::refresh();
}




パルスをつくって制御する方法:
analogRead()の読み取り値である0〜1023の1024段階で制御する方法があります。この場合は、プログラム上でdigitalWrite()のHIGHとLOWを交互に出力するパルスを生成して制御します。HIGHの継続時間とLOWの継続時間の合計が、パルスの周期である約20ミリ秒(20000マイクロ秒)になります。delayMicroseconds()で、HIGHとLOWの継続時間を変化させるプログラムで、サーボの動作角度を制御します。一般的なサーボにおいては、HIGHの継続時間は500〜2500マイクロ秒程度になります。500マイクロ秒で0度、2500マイクロ秒で180度という計算になります。約2000マイクロ秒の振り幅があるので、analogRead()で読み取った値を2倍するとほぼ0〜180度を1024段階の分解能で表現できます。digitalWrite()を使うのでPWM以外のピンにもサーボを接続することができます。

void setup(){
//パルス出力ピンの設定
//(デジタル出力なのでどのピンでも可)
pinMode(3,OUTPUT);
}
void loop(){
//可変抵抗器の読み込み値を2倍にする(振幅値:約2000)
int val=analogRead(0)*2;
//パルス:HIGHを出力
digitalWrite(3,HIGH);
//パルス最小値を500としvalを代入
delayMicroseconds(val+500);
//パルス:LOWを出力
digitalWrite(3,LOW);
//HIGHの継続時間を差引いて周期を20000usに調整
delayMicroseconds(10000-(val+500));
delayMicroseconds(10000);
}

パルスの周期は20000マイクロ秒なので、LOWの継続時間は20000マイクロ秒からHIGHの継続時間を差し引いた時間となります。尚、delayMicroseconds()の()内に入れられる最大値は16383なので(精度を保つことができる最大値)、20000-(val+500)とは書かずに、10000-(val+500)と10000に分けて書いてあります。


サーボによっては、パルスの最小値や最大値あるいは振幅値が多少異なるので、正確に制御したい場合はデータシートを参照するか、サーボごとにテストしてみる必要があります。


絵とき「サーボ制御」基礎のきそ (Mechatronics Series)
塩田 泰仁
日刊工業新聞社
売り上げランキング: 248872

Arduino 小型DCモータ/TA7291P

小型のDCモータ「FA-130」を制御する方法についてです。このモータは、車のプラモデルなどに使われるDCモータです。最大で500mAの電流が流れます。大抵DCモータを扱う場合、Arduino基盤にとっては過電流となるので別電源(乾電池など)が必要となります。
DCモータには二本の線がついており、一方をプラスに、もう一方をマイナスにつなげば回転し、プラスとマイナスを入れ替えれば逆回転します。スピードは、電圧が低いと遅く、高いと速く回転しますが、今回の場合はPWM(パルス)で調節します。パルスは、一定の電圧でONとOFFを高速に繰り返して出力する方法で、ONの継続時間が長いほど速く回転し、OFFの時間が長いほど遅く回転します。このONとOFFの時間の比率を「デューティ比」と言います(実際には、回転速度というよりトルクに反映されます)。



上図と下図を比較すると、「ONの継続時間」については、下図より上図のほうが長いので、上図の方がモータは速く回転します(トルクが高くなります)。



PWMでは、このONとOFFの時間の比率を変えることでスピード調節を行っています。以前行ったLEDの照度調整も同様の仕組みです。LEDの場合、実際は点滅しているのに過ぎないのですが、繰り返されるON/OFFがあまりにも速いので、明るさが変わったように見えています。

また下図のように、モータを正転/逆転させる場合は、電源へつないでいる二本の線の途中にスイッチを設けて入れ替え可能にします。切り離せば静止状態になります。このような切替を可能にする回路を「Hブリッジ回路」といいます。



そこで、いままで説明したことを容易にしてくれるのが、今回用いるモータドライバIC「TA7291P」です。「TA7291P」には、10本の端子があります。
東芝 TA7291P

東芝 TA7291P

価格:189円(税込、送料別)





 1:GND(Arduino/GND端子)と共有
 2:モータの端子へ接続
 3:非接続
 4:PWM端子(Arduino/アナログ出力端子)へ接続
 5:信号用端子(Arduino/デジタル出力端子)へ接続
 6:信号用端子(Arduino/デジタル出力端子)へ接続
 7:5V電源(Arduino/5V端子)と共有
 8:外部電源のプラス端子へ接続(乾電池など)
 9:非接続
10:モータの端子へ接続

今回は、可変抵抗器で正転/逆転/静止/スピード調節しようと思います。以下のようにそれぞれを接続することとします。複雑な配線に見えるかもしれませんが、間違わずにそれぞれを接続して下さい。


TA7291Pの5番ピンと6番ピンは、静止/正転/逆転を決めるための信号用の端子であり(それぞれArduinoのデジタル出力の1番ピン、2番ピンに接続)、
5番ピンが「LOW」、6番ピンが「LOW」の場合は静止
5番ピンが「HIGH」、6番ピンが「LOW」の場合は正転
5番ピンが「LOW」、6番ピンが「HIGH」の場合は逆転
となります。ArduinoのdigitalWrite()から出力されるLOW/HIGHの組合わせによって決められます。つまり、Arduinoのデジタル出力1番ピンと2番ピンのHIGH/LOWの出力の組合わせをプログラムによって操作することになります。
スピード調節については、TA7291Pの4番ピンがArduinoのアナログ出力の3番ピン(PWMピン)と接続され、ArduinoからPWM出力によって制御されます。

今回は、可変抵抗器を右に回すと正転、左に回すと逆転、中間だと静止するプログラムにします。可変抵抗器からanalogRead()によって読み取られる値は0〜1023なので、それを2で割って0〜511にスケールダウンし、
  0〜254:逆転(0で高速、254で低速)
255〜256:静止
257〜511:正転(257で低速、511で高速)
となるようにします。逆転時では数値が0に近いほど速く、254に近いほど遅くなり、正転時では数値が大きいほど速くなるので、調整した値をanalogWrite()の出力値に入れます。よって、以下のようなプログラムになります。

Arduinoのプログラム:

void setup(){
pinMode(1,OUTPUT); //信号用ピン
pinMode(2,OUTPUT); //信号用ピン
}

void loop(){
//アナログ入力:0番ピンの値を2で割る
int val=analogRead(0)/2; //0~511の値にする

//静止/正転/逆転の状態に分けてプログラムする
if(val>=255 && val<=256){ //静止:255~256
//LOW,LOWでデジタル出力
digitalWrite(1,LOW);
digitalWrite(2,LOW);
}else if(val>256){ //正転:257~511
//HIGH,LOWでデジタル出力
digitalWrite(1,HIGH);
digitalWrite(2,LOW);
//valが大きいほど出力値も大きくなる
analogWrite(3,val-256); //出力値:1~255
}else{ //逆転:0~254
//LOW,HIGHでデジタル出力
digitalWrite(1,LOW);
digitalWrite(2,HIGH);
//valが小さいほど出力値は大きくなる
analogWrite(3,255-val); //出力値:1~255
}
}

外部電源には、1.5Vの乾電池が4本入る電池ボックスなどを使うといいでしょう。
TA7291Pのデータシートには、外部電源のプラス端子をつなぐための8番ピンの電圧は、PWMに使うための4番ピンの電圧以上なければいけないと書いてあります。これに従えば、今回の場合の外部電源は、5V以上必要となります。

関連:「Arduino モータドライバ+モータ」(その他のモータドライバ等について)


MonotaRO (モノタロウ)

6/06/2008

Processing ドラッグしながら図形を描く


上はこのプログラムをキャプチャした画像です。
下の白いキャンバス内にドラッグして矩形を描くことができます。eキーで白紙に戻ります。







Processingでは、予めプログラム上で図形の座標やサイズを決めてから描画させますが、
一般の描画ソフト(イラストレータなど)のように、ドラッグしながら図形の大きさを決めて描くサンプルを以下に書きます。今回は、描く図形をrect()にし、マウスボタンを押した地点から描画を開始し、ドラッグ中はrect()のサイズが変化し、マウスボタンを放した時に描画完了とします(いわゆる描画ソフトでの一般的な描き方)。重ね描きできるようにするためには、毎回background()で画面を塗りつぶさず、今回はloadPixels()updatePixels()を使うことにします。重ね描きが分かりやすいように、noFill()で図形の塗り無しで、外形線だけの描画とします。「e」のキーを押せば、白紙に戻るようにします。

Processingのプログラム:

//図形描画開始点座標の変数
int x,y;

void setup(){
size(400,300);
//最初に背景色を白にしておく
background(255);
//始点と終点座標による描画に設定
rectMode(CORNERS);
//塗り無し
noFill();
}

void draw(){
//ここには何も書かない
}

//マウスボタンが押されたら
void mousePressed(){
//マウス座標を変数に入れておく
x=mouseX;
y=mouseY;
//画面内容を記憶しておく
loadPixels();
}

//ドラッグしたら
void mouseDragged(){
//画面内容を更新する
updatePixels();
//x,yを開始点、マウス座標を終点として描画
rect(x,y,mouseX,mouseY);
}

//キーが押されたら
void keyPressed(){
//「e」キーなら
if(key=='e'){
//白で塗りつぶす
background(255);
}
}

初期設定のsetup()では、rectMode(CORNERS)にして、開始点と終点の二点間の座標による定義にしておきます。マウスボタンを押した時に、マウス座標値mouseXmouseYrect()の描画の開始点としてxとyの変数に記憶させ、その時の画面内容をloadPixels()を使って記憶しておきます(ドラッグ中の処理のための下準備)。そしてドラッグ中には、loadPixels()の時の画面内容をupdatePixels()によって表示させつつ、xとyを開始点としてrect()を描き始め、終点はドラッグ中のmouseXとmouseYの座標を使って常に変化するようにします。loadPixels()によって、画面内容を記憶させておかなかったり、updatePixels()によってその画面内容を表示させなければ、ドラッグ中のrect()の線は重なり合うように描画されます(試しに、updatePixels()を消してランさせればどうなるか分かります/下画像)。


updatePixels()を使わない場合の画面。
このようにドラッグ中の変化する線も消されずに描画されます。敢えてこの方法を使うということも考えられます。

6/05/2008

Processing 手描きの線の表現




Processingにおいて、rect()ellipse()のような幾何学図形ではなく、マウスを使って「手描き」の表現をする場合のサンプルです。マウスボタン(クリック)を押しながらドラッグすると、手描きのような線を引くことができ、「e」のキーを押せば画面は真っ白に戻るという内容です。

以下の画面中央(白い矩形内)に描くことができます。









Processingのプログラム:

void setup(){
//画面サイズ幅400、高さ300
size(400,300);
//滑らかな描画(アンチエイリアス)
smooth();
//背景色を255(白)に設定
background(255);
}

void draw(){
//ここには何も書かなくてよい
}

//マウスドラッグ中のプログラム
void mouseDragged(){
//線を描画
line(pmouseX,pmouseY,mouseX,mouseY);
}

//キーが押された時のプログラム
void keyPressed(){
//もしキーが「e」なら
if(key=='e'){
//背景色を白で塗り直す
background(255);
}
}


上のプログラムでは、mouseDragged()keyPressed()の時にしか描画しないので、draw(){...}内には特に書く項目はありません。線を引くには、line(x1,y1,x2,y2)というように四つの値が入り、開始点(x1,y1)から終点(x2,y2)まで線を引きます。line()内のpmouseXは、一つ前(1ループ前)のマウスのX座標値であり、mouseX()は現在のX座標値です。つまり、一つ前のマウス座標値から現在のマウス座標値まで線を引くということになります。ドラッグ中は、その内容が繰り返され連続した線になります。すべてを白紙に戻すには、キーを押したときに、background()を用いて画面全体を塗り直します。draw(){..}内にbackground()を書いておくと、描画されている線も同時に上塗りされて消えてしまうので、setup(){...}の中で、最初に一度設定しておき、線だけが重ね描きされるようにします。

Arduinoにつないだセンサから読み取った値を、シリアル通信を通してline()内に入れれば、センサによって自由な線を描くことができます。応用的な使い方を考えてみて下さい。

6/02/2008

出力方法について

出力方法には、LEDのように発光表示する視覚的なもの、ものを動かす実際の力やエネルギーをつくりだすアクチュエータ、その他、熱や音を生成するものなどあります。特にアクチュエータの代表となるモータは、ギヤや機構の組合わせによって、様々な動き方を可能にしますが、電気以外に機械に対する知識や技術も必要になってきます。また、Arduino基盤と接続するには、モータドライバICFETトランジスタ、別電源が必要となります。
視覚的な表示方法であれば、Processingのプログラムを液晶プロジェクタで直接投影することも考えられます。
音に関しては、直接鳴らすブザーやスピーカがありますが、Processingの音のライブラリ(minimEssSonia)を用いることもできます。その場合は、既に用意してある音源データを再生したり、プログラム上で波形をつくって音を出力することもできます。
以下に、様々な出力方法のリストを挙げておきます。幾つかは、その他の部品を取付けないと作動しないものや、それに応じたプログラムが必要になるものも含まれていますが、今後授業で取り扱っていきたいと思います。

表示(発光)関係
 一般電球/蛍光灯
 LED(単色、3色)
 7セグLED
 ドットマトリックスLED
 液晶ディスプレイ
 小型有機ELディスプレイ
 冷陰極管
 レーザーモジュール
 EL発光シート

アクチュエータ関係
 DCモータ
 ギヤードモータ
 (平行ギヤ、ベベルギヤ、ウォームギヤ、ラック、遊星ギヤ)
 ステッピングモータ
 サーボモータ
 振動モータ

 電磁石
 ソレノイド

 気体ポンプ
 液体ポンプ
 電磁弁
 エアシリンダー

 バイオメタル人工筋肉
 通電性高分子人工筋肉

熱関係
 フィルムヒーター
 ニクロム線(発熱)
 ペルチェ素子(冷却)

音関係
 圧電スピーカ/ブザー
 コーンスピーカ
 Processingライブラリの利用(minimEssSoniaなど)
 関連:「スピーカ/音出力について


[目次:Processing関係]  [HOMEへ戻る]  [目次:Arduino関係]