INDEX(各項目ごとの目次)

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

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

8/20/2008

Arduino モータドライバ+モータ

以前「Arduino 小型DCモータ/TA7291P」で、モータドライバICのTA7291Pを用いてDCモータの制御を行いました。TA7291Pは、許容電流は1.0A(最大2.0A)なので小型のDCモータ向きでした。より大きなモータを制御するには、以下のようなモータドライバあるいはモータコントローラなどがあります。Arduino基盤に対して、電圧、電流ともに許容値を超えるため、モータ駆動用外部電源が必要になります。


東芝 TA7291P


東芝 TA8440HQ:PWM端子付きブリッジドライバIC


NEC UPD16805:モータドライブ用IC


東芝 TA8429HQ


STマイクロエレクトロニクス L6203


「モータドライバIC」
TA7291P :連続1.0A(最大2.0A):モータ用電源 0~20V
TA7279P :連続1.0A(最大3.0A):モータ用電源 0~16V(PWM端子なし)
TA8440HQ:連続1.5A(最大3.0A):モータ用電源 0~50V
UPD16805:連続1.0A(最大4.2A):モータ用電源 0.5~8.0V
TA8429HQ:連続3.0A(最大4.5A):モータ用電源 7~27V
L6203 :連続4.0A(最大5.0A):モータ用電源 12~48V
TB62300F:連続2.5A(最大8.0A):モータ用電源 18~40V

「モータドライバボード」
Poloru VNH3SP30:連続9A(最大30A) :モータ用電源最大30V
Poloru VNH2SP30:連続14A(最大30A):モータ用電源最大19V

「モータコントローラ」
SyRen10 :連続10A(最大15A) :モータ用電源 6~24V
SyRen25 :連続25A(最大45A) :モータ用電源 6~24V
Pololu SMC04 :最大30A  :モータ用電源 6~18V
KONDO UMD-540S:50A以下:モータ用電源 4.8~12V

「デュアルモータコントローラ(モータ2個制御)」
Sabertooth2x5 :連続5A(最大10A) :モータ用電源 6~18V
Sabertooth2x10 :連続10A(最大15A):モータ用電源 6~24V
Sabertooth2x25 :連続25A(最大50A):モータ用電源 6~24V

「ラジコンカー用スピードコントローラ/アンプ」
FUTABA MC230CR 連続45A(最大90A) :モータ用電源7.2V〜8.4V
FUTABA MC330CR 連続100A(最大200A):モータ用電源7.2V〜8.4V
KONDO VFS-FR 連続240A(最大960A):モータ用電源7.2V〜8.4V


連続アンペア数は、PWM制御など使わず直接連続運転したときの許容値になります。ArduinoのanalogWrite()やパルスを生成してPWM制御するならば、最大アンペア数近くまで出力可能になります。ただし、ドライバによって性質が異なるので、ゆとりを見ておいたほうがいいでしょう。あまりにも発熱しすぎる場合は、放熱器をドライバ本体に取付ける必要があります。

大抵のモータドライバやモータコントローラなどには、
・回路用電源端子(5V/Arduino基盤5V端子へ)
・モータ用端子(2端子/モータへ接続)
・外部電源端子(モータ駆動用電源/GNDは他と共有)
・GND共有端子(Arduino基盤GND端子と共有)
・正転/逆転/停止など切替用信号端子(2端子/Arduino基盤へ)
・PWM用端子(Arduino基盤PWM端子へ)
がついているはずなので、接続方法はほぼ共通しています。


ラジコン用アンプについて
ラジコンカー用スピードコントローラ(アンプ)の場合、レース用のものは「バックなし(前進のみ)」が多いため、「バック付き(前進/後進)」かどうかを確認する必要があります。


フタバ MC231CR アンプ【送料無料】


フタバ MC331CR アンプ【送料無料】


【ラジコン RCパーツ】KO PROPO【ESC(アンプ)】VFS-FRバック付きVFS

アンプ本体には、
・モータ用端子(2端子/モータへ接続)
・外部電源端子(モータ駆動用電源/ラジコン用7.2Vバッテリーなどへ接続)
・3本線
  回路用電源:赤(Arduino基盤5V端子へ)
  GND:黒(Arduino基盤GNDと共有)
  信号線:白(Arduino基盤PWM端子へ)
がついています。ArduinoのanalogWrite()で、PWMピンと信号線(白)を接続して(サーボをPWM制御するような方法)、スピード調整/正転/反転/停止できます。analogWrite()の括弧内の値(0〜255)を中点(127前後)にすると停止状態になるはずです。
あるいは、Arduinoのサーボライブラリのservo.write()を使って0~180の範囲(90が中点)で制御することができるはずです。

上記以外に、MOS-FETを用いてモータドライバを自作する方法もあります。


一般的な模型用モータ
モータについては、一般的なラジコンや模型用(マブチモータ)のものであれば、以下のようなものが挙げられます。

FA-130RA:1.5V時/最大効率時電流0.66A/瞬間最大電流2.20A
RE-140RA:1.5V時/最大効率時電流0.66A/瞬間最大電流2.10A
RE-260RA:3.0V時/最大効率時電流0.64A/瞬間最大電流2.70A
RE-280RA:3.0V時/最大効率時電流0.87A/瞬間最大電流4.70A
RS-380PH:7.2V時/最大効率時電流3.23A/瞬間最大電流14.9A
RS-540SH:7.2V時/最大効率時電流4.57A/瞬間最大電流22.2A

最大効率時電流は、通常時の電流とみなしてもいいでしょう。瞬間最大電流は、急停止や逆転時など様々な負荷がかかった時(負荷をかけて停止した時)の電流値です。一定の速度で回転しているようなものであればいいのですが、回転方向や速度を変化させるような場合は、瞬間最大電流を考慮にいれる必要があります。その場合は瞬間最大電流を許容できるモータドライバが必要になります。

上記のモータにギヤヘッドが取付けてある「タミヤ・ギヤードモータ」シリーズは、比較的高トルクが得られます。380モータであれば、7.2V電源で瞬間最大電流が14.9Aなので、上記モータドライバICでは許容アンペア数が低すぎるため、最低でも15Aまで耐えられる「SyRen10」などが必要になるでしょう。540モータであれば、7.2V電源使用時なら22.2A以上、12V電源使用時なら37A以上耐えられるモータコントローラ「SyRen25」などが必要になるでしょう。
小型のモータであれば、「タミヤ・テクニクラフト」シリーズのギヤボックスなどがあります。

尚、モータのデータシートには「性能線図」と呼ばれる表が掲載されている場合があります。この表を用いて、モータの特性を調べることができます。マブチモータのサイトには性能線図の分かりやすい説明があります。


大型のモータ(その他モータの種類についてはこちら
人を動かすことができる大型のモータであれば、以下のようなものがあり、専用のモータドライバユニットにArduinoを接続しPWM制御可能です。
オリエンタルモータ BLHシリーズ/100W/DC24V(このモータを使った説明
また、以下のようなロボット用/精密機械用のモータであれば、小型なものから大型のものまであります。
マクソンモータ(スイス製)
光進電気工業(ファールハーバー/ドイツ製)
ツカサ電工


松下電器産業 ギアーヘッド

8/18/2008

Arduino デジタルコンパス/HMC6352

デジタルコンパス(方位センサ)によって、物体の方位を磁気的に調べることができます。Arduinoで制御可能あるいは入手しやすいデジタルコンパスとして幾つか以下に挙げておきます。

デジタルコンパスの種類:
・「RDCM-802」(秋月電子:¥3400
・「HMC1052L」(Sparkfun:$24.95ストロベリーリナックス:¥3480
・「HMC6352」(Sparkfun:$59.95ストロベリーリナックス:¥7350スイッチサイエンス:¥6980
・「HM55B(日立製)」(Parallax:$29.99日本マイクロボット教育社:¥4450
・「CMPS03」(RoboticsConnection:$55)

それぞれの性能など:
「RDCM-802」は、3ビットの信号で8方位の解像度しかないので、大体の向きを調べるくらいしかできません。
「HMC1052L」は、ArduinoのanalogRead()で入力すれば10ビット(1024段階)の解像度が得られます。
「HMC6352」は、I2C通信で0.0〜359.9度(0.1度ずつ)の分解能があります。
「HM55B」は、シリアル通信で11ビット(2048段階)の解像度が得られます。
「CMPS03」は、I2C通信で3600の分解能。

サンプルソースについて:
「HMC6352」については、WiringのExamplesのサイトにサンプルソース(Standbyモード)があり、I2C通信のライブラリを用いればArduinoでも使用可能になります。ArduinoのPlaygroundにもサンプルがあります。
「HM55B」については、ArduinoのPlaygroundのサイトにサンプルソースがあります。
「CMPS03」については、Arduino用のライブラリがあります。

HMC6352の使い方:
今回は、「HMC6352」デジタルコンパスモジュールの実験をしてみます。
「HMC6352」は、I2C通信で方位データを得るので、I2C通信のライブラリを用います。ライブラリを取り入れるには、メニューバーのSketch>Import Library>Wireを選択することで「#include <Wire.h>」の一文が自動的にプログラムを書く欄に挿入されます。ArduinoでのI2C通信は、SDA端子(データ用端子)はアナログ入力の4番ピン、SCK端子(クロック用端子)はアナログ入力の5番ピンに限定されます。「HMC6352」は、5V電源でも許容範囲ですが今回は3.3Vを使用することにします。接続方法は以下の様になります。



アドレスについて:
I2C通信では、マスターデバイスとスレーブデバイスという関係性があります。マスターデバイスには複数のスレーブデバイスが接続できるメリットがあり、複数のスレーブデバイスはマスターデバイスから制御されることになります。今回の場合は、Arduino基盤がマスターデバイス、HMC6325がスレーブデバイスになります。複数のスレーブデバイスが接続可能であるため、スレーブデバイス側にはどのデバイスであるかを識別するためのアドレスが必要となります。データシートによれば、HMC6325のデフォルトのアドレスは16進数の「0x42」であり、今回はこのアドレスを使うことにします。ただし、識別されるアドレスは8ビット中の上位7ビットであり、「0x42」を1ビット右にシフト「>>」した値になります(16進数の「0x42」は、二進数の「01000010」であり、1ビット右にシフトするということは、二進数の「01000010」の桁を右に一桁ずらすことになるので、「00100001」(=0x21)になるということです/ビットシフトに関しては「Arduino-Processing シリアル通信3」を参照)。

モード切替について:
HMC6325には、マスターデバイスから「A」を送信することで方位を計測開始しデータを読み取る「Standbyモード」と、一旦「A」を送信後データを読み取るごとに自動的に計測/出力する「Queryモード」、そして設定した周期(1Hz、5Hz、10Hz、20Hz、)で連続的に計測/出力した結果を読み取る「Continuousモード」があります。
今回は「Continuousモード(20Hz)」を使うことにします。この設定をするためには、RAM書き込み用コマンド「G」、書き込み先(レジスタ)の「0x74」、そして設定内容の8ビット「0111010」あるいは16進数の「0x72」を送信します。ちなみに、設定内容については、

0x50:Standbyモード(デフォルト)
0x51:Queryモード
0x52:Continuousモード(10Hz,Periodic Set/Reset=ON)
0x72:Continuousモード(20Hz,Periodic Set/Reset=ON)

となります(詳細はデータシートを参照して下さい)。
シリアルモニターを使って読み取り値を出力することにします。


//I2C通信ライブラリを取り込む
#include <Wire.h>

//デジタルコンパスモジュールのアドレス設定
int compassAddress = 0x42 >> 1; //=0x21
//読み込み値(角度)の変数を用意
int reading = 0;

void setup() {
//I2C通信開始
Wire.begin();
//角度表示のためのシリアル通信開始
//Serial.begin(9600);

//Continuous Modeに設定する
Wire.beginTransmission(compassAddress);
//RAM書き込み用コマンド
Wire.send('G');
//書き込み先指定
Wire.send(0x74);
//モード設定
Wire.send(0x72);
//通信終了
Wire.endTransmission();
//処理時間
delayMicroseconds(70);
}

void loop() {
//デバイスに2バイト分のデータを要求する
Wire.requestFrom(compassAddress, 2);
//要求したデータが2バイト分来たら
if(Wire.available()>1){
//1バイト分のデータの読み込み
reading = Wire.receive();
//読み込んだデータを8ビット左シフトしておく
reading = reading << 8;
//次の1バイト分のデータを読み込み
//一つ目のデータと合成(2バイト)
reading += Wire.receive();
//2バイト分のデータを10で割る
reading /= 10;
Serial.println(reading);
}
//処理のために少し待つ(20Hz)
delay(50);
}


まずは、Wire.begin()でI2C通信を開始します。「HMC6325」の初期設定では、「Standbyモード」になっているため、setup(){...}内で「Continuousモード」に切り替えます。設定内容を「HMC6325」のRAMに書き込むために「G」というコマンド、書き込み先となる専用レジスタの「0x74」、設定内容となる8ビットの「0x72」をWire.send()を使って送信します。
方位角度の読み込みは、Wire.requestFrom()でアドレスと何バイト分のデータかを指定して要求します。計測結果は0〜3599までの値(360度を10倍した値)を2バイト(16ビット)で返してきます。Wire.available()によって2バイト分読み込み可能なデータをカウントしたら、Wire.receive()によって、2バイトの値を2回に分けて読み込みます。一度に読み込むことができる値は1バイト(8ビット、0〜255)までなので、最初の1バイトを読み込んだら、その値を8ビット左にビットシフト(8桁左にビットシフトするということは、256倍することと等しくなります)、その値に次の1バイト分のデータを加算します。値は10倍されているので、最終的に10で割って0〜359度の角度として取り込みます(float型を使えば0.0〜359.9で出力します)。20Hzごとに計測する「Continuousモード」に設定したので、delay(50)を挿入してループの周波数も20Hzにしておきました。

測定結果をProcessingへシリアル通信するのであれば、2回に分けて読み取った値(2バイト分)をそのまま1バイトずつ2回送信(合計2バイト)し、Processing側で受け取ってから二つの値を合成すればいいでしょう。値を合成するには、一個目の値を左に8ビットシフト(または256倍)してから二個目の値を足せば0〜3599の値として得ることができるはずです。BYTEフォーマットなら、そのまま2回で送信します。文字列でデリミタ(区切り記号)を挿入して送信する場合は、2回目の送信時にSerial.println()で改行記号を用いて送信します(Processing側での受信については、「Arduino-Processing シリアル通信3(複数の値を送信する場合)」あるいは「Arduino-Processing シリアル通信5(文字列で送信する場合)」を参照して下さい。

BYTEフォーマットで送信する場合:

void loop() {
Wire.requestFrom(compassAddress, 2);
if(Wire.available()>1){
//2回に分けて読み取った値を
//BYTEフォーマットで2個送信する
Serial.print(Wire.receive(),BYTE);//1個目
Serial.print(Wire.receive(),BYTE);//2個目
}
delay(50);
}

あるいは、文字列として送信する場合:

void loop() {
Wire.requestFrom(compassAddress, 2);
if(Wire.available()>1){
//2回に分けて読み取った値を
//DECフォーマットで2個送信する
Serial.print(Wire.receive(),DEC);
Serial.print(",");//デリミタを挿入送信
Serial.println(Wire.receive(),DEC);//改行記号つき
}
delay(50);
}


また、「C」を送信することでキャリブレーションモードに入り、周囲の磁気の影響によるモジュール内素子のゆがみをなくし正常な状態に調整することが出来ます。モジュールを平らな場所に置いてから6秒から3分以内に、ニ周程度回転させ、「E」を送信することで終了します。20秒以上かけて2回転させれば、正確なキャリブレーションになります。

//キャリブレーション開始コマンド送信
Wire.beginTransmission(compassAddress);
Wire.send('C');
Wire.endTransmission();

//30秒ほど待つ(6秒〜3分まで)
//この間に数回モジュールを回転させる
delay(30000);

//キャリブレーション終了コマンド送信
Wire.beginTransmission(compassAddress);
Wire.send('E');
Wire.endTransmission();


デジタルコンパスをモータなどの磁気を発するものの近くに設置すると磁気的影響を受けるので、少し離れた場所に設置したほうがいいでしょう。

8/11/2008

Arduino+Processing マトリクスLED+Webカメラ

今回は、Webカメラから取り込んだ映像をArduinoに接続した8×8マトリクスLEDに映す実験を行います。まず、ProcessingでWebカメラからの映像を8×8ピクセルで取り込み、合計64個のピクセルの明るさの値(0〜255)を調べてから、その個々の値をシリアル通信でArduinoに送ります。Arduino側では、受け取った64個分の値をマトリクスLEDの個々の明るさに反映させます。Arduino基盤とマトリクスLEDとは、ICを使わず直結することにします(接続方法は「Arduino マトリクスLED1」を参照)。
Processingの画面では、マトリクスLEDの表示シミュレーション(モニタリング)を同時に行うことにします(前回行ったモザイク処理のような方法で赤い円を64個映し出すことにします)。


「Processingの画面(モニタリング)」

Processingのプログラム:

//ビデオライブラリを取り込む
import processing.video.*;
//キャプチャ用オブジェクトを用意
Capture video;

//シリアル通信ライブラリを取り込む
import processing.serial.*;
//シリアル通信オブジェクトを用意
Serial port;

//64個分のピクセル色の配列を用意
int[] pixelValue=new int[64];

//シリアル通信開始用フラグ
boolean start=false;

void setup(){
//画面を160角に設定
size(160,160);
//描画を滑らかにする
smooth();

//映像キャプチャの設定(幅8,高さ8ピクセル,フレームレート30)
video = new Capture(this, 8, 8, 30);

//ポートの設定
port=new Serial(this,"/dev/tty.usbserial-A40014iU",9600);

//外形線なし
noStroke();
}

void draw(){
//背景を黒で塗る
background(0);

//64個分のピクセルの処理
for(int i=0;i<64;i++){
//映像の各ピクセルの色の値を
//明るさの値に変換する
pixelValue[i]=int(brightness(video.pixels[i]));

//円の塗色(赤の値)に代入
fill(pixelValue[i],0,0);
//円を描画
ellipse((i%8)*20+10,(i/8)*20+10,15,15);

//値を送信
if(start){
port.write(pixelValue[i]);
}
}
}

//キャプチャ映像読み込み
void captureEvent(Capture video) {
video.read();
}

クリックでシリアル通信開始
void mousePressed(){
start=true;
}


Processingの方では、VideoライブラリSerialライブラリの二つを取り込む必要があります。マトリクスLEDが8×8の解像度なので、Webカメラから取り込む映像の解像度も8×8にしておきます(カメラ映像の横縦比は4:3なので、少し縦長の映像になってしまいます)。
*Windowsの場合、そのままの設定ではこのVideoライブラリを使用することができません。WinVDIG 1.0.1をインストールする必要があります。
「pixelValue[i]=int(brightness(video.pixels[i]))」では、まず映像の各ピクセルの色をpixels[]で読み込みます。pixels[]は、RGBの三色の値(三つの値)を含んでおり、brightness()で括ると明るさの値(一つの値)に変換されます(0〜255)。変換された値はfloat(小数)なのでint()で括って整数に変換しておきます。この値を、fill()の赤の値に代入し(緑と青は0)、LEDのような赤い円をellipse()を使って64個描画します。8×8を160×160の画面で表示しているので、20×20ピクセルのグリッド状に配置されます。ellipse()の直径はとりあえず15にしておきました。ellipse()のXとY座標は、「%」と「/」を使って計算します(X座標となる「(i%8)*20+10」は、iを8(横幅)で割った余りに20ピクセル掛けて、さらに10ピクセル足すことでellipse()が20×20のグリッドの中心に来るように位置調整しています)。最後に「port.write(pixelValue[i])」で、Arduinoへ各ピクセルの明るさの値を送信します。今回は画面をクリックしたらシリアル通信が開始されるようにしています。

次にArduinoの方に移ります。冒頭で書いたように、今回はマトリクスLEDを、ICを使わず直結します。個々のLEDはダイナミック点灯しているので、点灯時間の長さによって明るさを調整することになります。点灯時間が短ければ暗くなり、長くなれば明るくなります。つまり、Processingから送られて来た明るさの値(0〜255)を、個々のLEDの点灯時間に反映させるプログラムになるということです。マトリクスLEDとの接続方法や詳細については「Arduino マトリクスLED1」を参照してください。

Arduinoのプログラム:

//8x8の二次元配列を用意
byte matrix[8][8];

void setup(){
//出力ピンの設定、すべてオフにする
for(int i=2;i<=17;i++){
pinMode(i,OUTPUT);
digitalWrite(i,LOW);
}
//シリアル通信開始
Serial.begin(9600);
}

void loop(){
//シリアル通信(64個分のデータ)
if(Serial.available()>63){
for(int k=0;k<8;k++){
for(int l=0;l<8;l++){
//読み込んだ値を配列に代入
matrix[k][l]=Serial.read();
}
}
}

//各LEDの点灯制御
for(int i=2;i<=9;i++){
//列の点灯
digitalWrite(i,HIGH);

for(int j=10;j<=17;j++){
//行の点灯
digitalWrite(j,LOW);
//行の点灯継続時間
delayMicroseconds(1+matrix[i-2][j-10]);
//行の消灯
digitalWrite(j,HIGH);
//行の消灯継続時間
delayMicroseconds(256-matrix[i-2][j-10]);
}
//列の消灯
digitalWrite(i,LOW);
}
}


以前の「Arduino マトリクスLED1」とほぼプログラム内容は同じです。異なる部分は、シリアル通信と各LEDを点灯/消灯させる継続時間の部分です。用意する二次元配列は、boolean型ではなくbyte型(0~255の値なので)にしています。
シリアル通信上で干渉しないようにするため、Arduino基盤の0番ピンと1番ピンには何も接続しないことにしています(2〜17番ピンを使用)。シリアル通信では、Processingから送られてくる64個のデータをSerial.available()でカウントして、それぞれの値を予め用意しておいた二次元配列matrixに保存しておきます。送られてくるデータは0〜255(明るさの値)となります。そしてダイナミック点灯していく際に、明るさの値をdelayMicroseconds()に代入して、点灯継続時間と消灯継続時間に割り当てます。delayMicroseconds(0)としてしまうと、0マイクロ秒としては扱ってくれないので、delayMicroseconds()の括弧内に入れられる最小値は1にしてあります。最小1マイクロ秒の点灯時間かつ最大256マイクロ秒の消灯時間のときが最も暗くなるときです。その逆で、最大256マイクロ秒の点灯時間かつ最小1マイクロ秒の消灯時間のときが最も明るくなります。個々のLEDは257マイクロ秒ごとにダイナミック点灯していることになります。個々のLEDの点滅を300マイクロ秒程度にすると点滅しているようには見えないので、今回の257マイクロ秒周期で点滅させれば、ほぼ問題ないでしょう。

関連:
・「シリアル通信1〜5
・「Arduino マトリクスLED1
・「Processing Video(Webカメラ)

ロジクールストア(ウェブカメラカテゴリ)

8/09/2008

Processing Video (Webカメラ)

ProcessingのVideoライブラリを使用することで、パソコンに接続した(あるいは内蔵された)Webカメラからの映像を取り込むことができます。このライブラリを使用するには、パソコンにQuickTimeがインストールされている必要があるので、もしインストールされていない場合は、アップルのQuickTimeのサイトからダウンロード/インストールして下さい。
USB接続する外付けのWebカメラの場合は必要なドライバをメーカーのサイトなどからダウンロード/インストールして使用可能な状態にしておいて下さい。Webカメラがパソコンに内蔵されている場合は、そのまま使うことができるはずです。まずは、簡単な映像の取り込みかたから始めます。

*Windowsの場合、そのままの設定ではこのVideoライブラリを使用することができないことがあります。その場合、WinVDIG 1.0.1をインストールする必要があります。


//ライブラリの取り込み
import processing.video.*;
//キャプチャする映像のオブジェクトを用意
Capture myCapture;

void setup() {
size(200, 200);
//キャプチャする映像の設定
myCapture = new Capture(this, width, height, 30);
}

void draw() {
//映像を画面に配置
image(myCapture, 0, 0);
}

//映像の読み込み
void captureEvent(Capture myCapture) {
myCapture.read();
}

//クリックでカメラセッティング画面になる
void mousePressed(){
myCapture.settings();
}


上記プログラムでは、画面サイズが200×200の正方形であるため、Webカメラでキャプチャされた映像は縦長になってしまうかもしれません。通常画面の比率は4:3(横:縦)であるため、もし比率を合わせるのであれば、320×240(4:3)などに合わせてください。
Capture()によって、親オブジェクト(thisのままでよい)と映像の幅と高さ、フレームレートを設定できます。映像が滑らかに動かない場合は、フレームレートを下げるか、画像サイズを縮小して調整して下さい。
キャプチャされた映像は、毎フレームごとにimage()によって画面内に配置されます。image()の括弧内の数値は、配置するX座標、Y座標となります。上記プログラムでは0,0に設定されているので、左上角の座標を基準に映像が画面内に配置されます。
captureEvent()は、Webカメラから信号が送られてくる度に作動します。read()によって、毎回送られてくる映像信号を読み込んでいます。
今回は最後にクリックするとsettings()によって、カメラのセッティング画面(Webカメラ用の設定アプリケーション画面)が現れるようにしてあります。ここで、カメラの解像度やコントラストなどの設定を行うことができるはずです。

次に映像にフィルタをかけてみるプログラムをしてみます。
画像用のfilter()というコマンドがあり、
THRESHOLD 白黒ニ値化:0.0~1.0(黒〜白)/初期設定0.5
GRAY    グレースケール:パラメータなし
INVERT   反転色:パラメータなし
POSTERIZE ポスタライズ:2~255(各チャンネルの色数の限定)
BLUR    ぼかし:指定半径範囲でぼかす
それぞれをfilter()の括弧内に入れれば、映像にフィルタをかけることができます。フィルタの種類の後にパラメータを入れることで、フィルタのかかり具合を調整することができます。
複数のフィルタを重ねて使うこともできます。ただ、フィルタの種類(特にBLUR)によっては処理速度に影響がでる場合があるので、適宜フレームレートや画素数などを調整する必要がでてくるときがあります。
以下は、キャプチャした映像にぼかしをいれノイズを取払い、その後白黒でニ値化し、白黒の単純な映像に変換するサンプルです。尚、映像の比率は4:3にすることにします。


「フィルタ(ぼかし+白黒ニ値化)をかけた映像(上画像)」


//ライブラリの取り込み
import processing.video.*;
//キャプチャする映像のオブジェクトを用意
Capture myCapture;

void setup() {
size(320, 240);//比率4:3
//キャプチャする映像の設定
myCapture = new Capture(this, width, height, 30);
}

void draw() {
//映像を画面に配置
image(myCapture, 0, 0);
filter(BLUR,1.8);//ぼかし
filter(THRESHOLD,0.7);//白黒ニ値化
}

//映像の読み込み
void captureEvent(Capture myCapture) {
myCapture.read();
}


次に、映像のモザイク化のプログラムをしてみます。画面サイズを320×240とし、横を32分割、縦を24分割し、10×10のモザイク処理をすることにします。まずloadPixels()によって映像の全ピクセルを読み込み、pixels[]によって選択したピクセルの色を取得します。取得した色をもとにrect()でモザイクの矩形を描くことにします。モザイク化されるには、必要なキャプチャ映像は結果的に32×24の解像度があれば済むので、予め32×24のサイズでキャプチャすることにします。


「モザイク映像(上画像)」


//ライブラリの取り込み
import processing.video.*;
//キャプチャする映像のオブジェクトを用意
Capture myCapture;

void setup() {
size(320, 240);//比率4:3
//キャプチャする映像を32×24に設定
myCapture = new Capture(this, 32, 24, 30);
//noStroke(); //モザイクの黒枠をなしにする場合
}

void draw() {
//キャプチャ画像の各ピクセルの色を
//塗色に割当て、矩形を描く
for(int i=0;i<32*24;i++){
fill(myCapture.pixels[i]);
rect((i%32)*10,(i/32)*10,10,10);
}
}

//映像の読み込み
void captureEvent(Capture myCapture) {
myCapture.read();
}


最終的に32×24のモザイクになるので、キャプチャする画像も同様の解像度にしておけば、処理速度が遅くならなくて済みます。pixels[]によってキャプチャされた映像の各ピクセルの色を取得します。32×24なので合計768ピクセル分となります。rect()による矩形も768個必要になるので、まずfill()で塗色を指定してから描きます。pixel[i]のiは画面左上から数えていき最後は右下のピクセルの番号になります。pixel[i]のiは0~767(合計768個)までの連続した数値なので、「%」と「/」を使ってXとYの座標値に変換します。変換したXとYの座標値をrect()に代入することで、320×240の画面に10ピクセル単位で横方向と縦方向に32×24のモザイク矩形として配置されます。今回はnoStroke()を使っていないので、黒い枠のついたモザイク矩形にしています。


ドライバなしですぐにコンピュータに接続可能(UVC対応)なWebカメラとして以下のようなものがあります。
Macintosh/Windows兼用です。
      

関連:
Arduino+Processing マトリクスLED+Webカメラ」--Webカメラ映像をマトリクスLEDに映す。
Processing Webカメラを光センサとして使う」--点光源で画面内に線を描く。
Processing Webカメラ/定点記録画像」--Webカメラ映像を0.5秒おきに画像保存(JPEG)する。
Processing Webカメラ/カラートラッキング」--Webカメラを使い、色を手がかりに物体を追いかける。
Processing Webカメラ/モーショントラッキング」--Webカメラを使って動体検知する。

Arduino マトリクスLED2/MAX7219

以前の「Arduino マトリクスLED1」では、8×8のマトリクスLEDをArduino基盤に直接接続して点灯させましたが、今回はMAX7219というLEDディスプレイドライバICを使って点灯してみます。Arduino基盤にマトリクスLEDを直結すると16個の端子が必要でしたが、MAX7219を使えば5V電源とGND以外に3本の端子で制御することが可能になります。原理的には、シリアルデータを送り、マトリクスLEDを表示させることになりますが、ArduinoにはマトリクスLED用のライブラリ(Wiringのライブラリ)があるので今回はそれを使ってプログラムしてみます。今回使用する8×8のマトリクスLEDは、以前同様、秋月電子で購入したものです。
以下のように、マトリクスLEDの各端子とMAX7219の端子が対応します(マトリクスLEDモジュールの側面に小さな凹凸部があり、MAX7219には端部に半円状の凹部や小さな丸印があるので、それらを手掛かりに向きを合わせてください)。



その他のMAX7219の端子については、
DIN:Arduinoからのシリアルデータ入力端子
DOUT:複数のMAX7219を接続する端子
VCC:5V電源
I_SET:接続する抵抗によって輝度を変えます
GND:AduinoのGNDと共有
LOAD:Arduinoからのデータ入力のロード用端子
CLK:Arduinoからのクロック信号入力端子

Arduino基盤との接続は以下のようになります。I_SETとLOAD端子には、10KΩの抵抗を接続して下さい(I_SETの抵抗値を上げれば暗くなり、下げれば明るくなります)。画像をクリックすれば大きくなります。



既存のサンプルを使って点灯実験してみます。Arduinoの画面からFile>Sketchbook>Examples>Library-Matrix>hello-matrixを選ぶと、プログラムが現れますが、ピン設定に少し変更を加えます。
既存サンプルでは、

pin 0: data (din)
pin 1: load (load)
pin 2: clock (clk)

となっていますが、0番ピンと1番ピンは使わず、

pin 2: data (din)
pin 3: load (load)
pin 4: clock (clk)

に変更することにします。こうすることで、プログラムのデータをアップロードする時やシリアル通信の際に信号が干渉されずにすみます。


//ライブラリを取り込む
#include <Sprite.h>
#include <Matrix.h>

//各ピンの設定
//pin 2: DIN
//pin 3: LOAD
//pin 4: CLK
Matrix myMatrix = Matrix(2, 4, 3);

void setup(){
}

void loop(){
myMatrix.clear(); //表示内容をクリアする

delay(1000);

//ピクセルを指定し表示する
myMatrix.write(1, 5, HIGH);
myMatrix.write(2, 2, HIGH);
myMatrix.write(2, 6, HIGH);
myMatrix.write(3, 6, HIGH);
myMatrix.write(4, 6, HIGH);
myMatrix.write(5, 2, HIGH);
myMatrix.write(5, 6, HIGH);
myMatrix.write(6, 5, HIGH);

delay(1000);
}


以下のように表示(1秒おきに点滅)されれば、配線などに問題ないことになります。write()で、X座標(0〜7)とY座標、ならびにHIGHかLOW(あるいは1か0)を代入し個々のLEDの点灯/消灯を指定します。



最初のArduino側のピンの設定(既存サンプルのコードに変更を加える)と、配線を間違わなければ、座標指定で点灯/消灯を制御できるので、それほど難しくはないと思います。今回のマトリクスLED用のライブラリを使うには、メニューバーのSketch>Import Library>MatrixとSpriteを選択すればインクルードされます。

次は、Spriteという基準となる絵柄を設定し、それが動く(横に流れる)表示方法を行います。Arduinoの画面からFile>Sketchbook>Examples>Library-Matrix>sprite-animationを選択し、このサンプルを使うことにします。前回同様、ピン設定は、

pin 0: data (din)
pin 1: load (load)
pin 2: clock (clk)

となっていますが、0番ピンと1番ピンは使わず、

pin 2: data (din)
pin 3: load (load)
pin 4: clock (clk)

に変更します。


//ライブラリを取り込む
#include <Sprite.h>
#include <Matrix.h>

//各ピン設定
//DIN:2
//LOAD:3
//CLK:4
Matrix myMatrix = Matrix(2, 4, 3);//DIN,CLK,LOAD

//スプライトの指定
//幅、高さ、絵柄を二進数で指定
Sprite wave = Sprite(
8, 4,
B00011000,
B00100100,
B01000010,
B10000001
);

void setup()
{
}

//X座標の変数を用意
int x = 0;

void loop(){
//スプライトの配置
myMatrix.write(x, 2, wave);
//もうひとつのスプライトの配置
myMatrix.write(x - 8, 2, wave);
//点灯時間設定
delay(75);
//画面をクリア
myMatrix.clear();

//アニメーション(カスケーディング)
if(x == 8){//8になったら0に戻す
x = 0;
}
x++;//X座標の変数を増加させる
}


Sprite()で、絵柄の幅、高さを指定し、二進数で点灯させる絵柄(0は消灯箇所、1は点灯箇所)をつくり設定します。write()で、絵柄の配置座標(左上の座標)と絵柄のオブジェクトを指定し表示させます。write()の括弧内のX座標やY座標は変数を用いて変化させることができるので、カスケーディング(絵柄が流れて表示される)の制御も簡単にできます。このサンプルでは、8コマ前にもうひとつの同じ絵柄を用意しておき、二つの絵柄を使用して途切れなく連続して絵柄が流れていくように表示しています。

また以下のようにSpriteを複数用意しておけば、入れ替わりで異なる絵柄を表示できます。


//ライブラリを取り込む
#include <Sprite.h>
#include <Matrix.h>

//各ピンの設定
//pin 2: DIN
//pin 3: LOAD
//pin 4: CLK
Matrix myMatrix = Matrix(2, 4, 3);

//スプライトの指定
//幅、高さ、絵柄を二進数で指定
Sprite pattern1 = Sprite(
8, 8,
B11111111,
B00000000,
B11111111,
B00000000,
B11111111,
B00000000,
B11111111,
B00000000
);

Sprite pattern2 = Sprite(
8, 8,
B10101010,
B10101010,
B10101010,
B10101010,
B10101010,
B10101010,
B10101010,
B10101010
);

Sprite pattern3 = Sprite(
8, 8,
B11110000,
B11110000,
B11110000,
B11110000,
B00001111,
B00001111,
B00001111,
B00001111
);

Sprite pattern3 = Sprite(
8, 8,
B00001111,
B00001111,
B00001111,
B00001111,
B11110000,
B11110000,
B11110000,
B11110000
);


void setup()
{
}

//X座標の変数を用意
int x = 0;

void loop(){
//スプライトの配置
myMatrix.write(0, 0, pattern1);
//点灯時間設定
delay(200);
//画面をクリア
myMatrix.clear();

myMatrix.write(0, 0, pattern2);
delay(200);
myMatrix.clear();

myMatrix.write(0, 0, pattern3);
delay(200);
myMatrix.clear();

myMatrix.write(0, 0, pattern4);
delay(200);
myMatrix.clear();
}


関連:
・「Arduino マトリクスLED1」(ICを使わずマトリクスLEDを制御する方法)
MAX7219データシート(MAXIM JAPAN)



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