So-net無料ブログ作成
検索選択
前の10件 | -

モータードライバでモーターを動かしてみる。PLLで。 [Arduino]

さて、ATtiny25/45/85 には、外付けのクリスタルがなくても高速なPWMを出力できるモードがありました。
これは動作クロックとは別で、64MHz(低電圧時は32MHzのモードを使用)まで行けます。
PLL (Phase Locked Loop) というらしい。
ここまで高速ではなくてもいいですが、Timer0を空けるために、Timer1をつかうのでこのモードを使ってみました。
これで前回と同様なものに仕上がったはず。

// モータードライバ(BD6211F)のテスト (ATtiny45 1MHz版, PLL)
//    FIN   RIN   VREF  OUT1  OUT2
//     L     L     x     HiZ   HiZ   スタンバイ
//     H     L     VCC   H     L     正転
//     L     H     VCC   L     H     逆転
//     H     H     x     L     L     ブレーキ(停止)
//     PWM   L     VCC   H    #PWM   正転(PWM制御A)
//     PWM   H     VCC   L    #PWM   逆転(PWM制御B)(PWM duty比と出力が逆になる)

#define  BD6211F_FIN      1                  // OC1A
#define  BD6211F_RIN      0

void setup() {
  pinMode( BD6211F_FIN ,     OUTPUT );       // OC1A
  pinMode( BD6211F_RIN ,     OUTPUT );
  // 20-100kHzほどのPWMを作成
  PLLCSR = _BV(LSM) | _BV(PCKE) | _BV(PLLE);      // 非同期低速PLL動作 (32MHz)
  TCCR1  = _BV(PWM1A) | _BV(COM1A1) | _BV(CS11);  // 2分周
  OCR1C  = 255;                                   // 62.5kHz (32MHz/2分周/256clk)  
}

void loop() {
  int motorPWM;             // モーターの出力
  // ■正転(PWM制御A) スピードアップ
  for( motorPWM = 1; motorPWM < 16; motorPWM++) { 
    OCR1A =  motorPWM * 17; 
    digitalWrite( BD6211F_RIN , LOW      );
    delay( 1000 );
  }
  // ■ブレーキ(停止)
  OCR1A = 255;
  digitalWrite( BD6211F_RIN , HIGH );
  delay( 2000 );
  // ■正転(PWM制御A) スピードダウン
  for( motorPWM = 15; motorPWM > 0; motorPWM--) { 
    OCR1A =  motorPWM * 17; 
    digitalWrite( BD6211F_RIN , LOW      );
    delay( 1000 );
  }
  // ■逆転(PWM制御B) スピードアップ
  for( motorPWM = 1; motorPWM < 16; motorPWM++) { 
    OCR1A =  255 - motorPWM * 17; 
    digitalWrite( BD6211F_RIN , HIGH     );
    delay( 1000 );
  }
  // ■スタンバイ
  OCR1A = 0;
  digitalWrite( BD6211F_RIN , LOW  );
  delay( 2000 );
  // ■逆転(PWM制御B) スピードダウン
  for( motorPWM = 15; motorPWM > 0; motorPWM--) { 
    OCR1A =  255 - motorPWM * 17; 
    digitalWrite( BD6211F_RIN , HIGH     );
    delay( 1000 );
  }  
}

これで、Arduinoの時間系の関数を使えるはず、、。

bd6411test_circ.jpg
回路は前回のそのままで。

しかし、また別に新たな問題が発覚しました。また次回。
タグ:モーター PLL

モータードライバでモーターを動かしてみる。 [Arduino]

モーターを動かしてみたいというのは前々から考えてたのですが、LEDとは違ってマイコンに直結するわけにも行かずちょっと調べてみました。
具体的には、ミニ四駆やプラレールなどに使われているおもちゃ用のFA-130タイプのモーターを動かしてみたいと思いました。
fa-130ra-2270.jpg
箱には、使用電圧範囲 1.5~3.0V、適正電圧 1.5V、消費電流 500mA とありました。

ちょっと秋月電子のページを見てみたら、BD6211というモータードライバをみつけました。

フルブリッジドライバ 7V BD6211F-E2: 半導体 秋月電子通商 電子部品 ネット通販
http://akizukidenshi.com/catalog/g/gI-05087/

bd6211.png

出力電流:1.0Aまでということで、モーターの消費電流 500mA以上あるのでいいかと思いきや、、

性能線図の見方と使用例|マブチモーター
http://www.mabuchi-motor.co.jp/ja_JP/technic/t_0201.html

で、みてみると、停動電流(Is)というのがあり、「回転中のモーターの負荷を増加させて、モーターの回転が停止した時の電流を停動電流(A)と表します。」と書いてありました。
データシートで見てみると、FA-130RA-2270 の STALL CURRENTに2.20A とありました。

FA-130RA - マブチモーター
pdf" target="_blank">http://www.mabuchi-motor.co.jp/en_US/cat_files/fa_130ra.pdf

まあ、でもホビーユースだし、、特徴 6)に「出力保護回路(過電流/過電圧/過熱/不足電圧)」って書いてあるし、、まあとりあえずつないでみるかということでやってみました。

ただ、通常のArduinoだと、システムが5Vになっているし、なにかやって壊れちゃうのもいやなので、ATtiny45Vと単3アルカリ乾電池2本で動かしてみることにしました。
SOP8ピンSIP化変換基板をつかってブレッドボードで使えるようにして、裏面にコンデンサーものせました。

SOP8ピンSIP化変換基板 (1枚): パーツ一般 秋月電子通商 電子部品 ネット通販
http://akizukidenshi.com/catalog/g/gP-06554/

で、こんな感じにしました。
bd6411test.jpg

モーターの配線からノイズが出るのか、配線の向きによってはリセットがかかったので、念のためプルアップ。
マイコンのロジックのIO電圧も乾電池の電圧より低めにでるようなので、プルアップしてみました。

bd6411test_circ.jpg

スケッチはこんな感じ。

// モータードライバ(BD6211F)のテスト (ATtiny45 1MHz版)
//    FIN   RIN   VREF  OUT1  OUT2
//     L     L     x     HiZ   HiZ   スタンバイ
//     H     L     VCC   H     L     正転
//     L     H     VCC   L     H     逆転
//     H     H     x     L     L     ブレーキ(停止)
//     PWM   L     VCC   H    #PWM   正転(PWM制御A)
//     PWM   H     VCC   L    #PWM   逆転(PWM制御B)(PWM duty比と出力が逆になる)

#include "wiring_private.h"                  // sbi(), cbi() を使うため
#include <util/delay.h>

#define  BD6211F_FIN      1                  // OC0B
#define  BD6211F_RIN      0

void setup() {
  pinMode( BD6211F_FIN ,     OUTPUT );       // OC0B
  pinMode( BD6211F_RIN ,     OUTPUT );
  // 20-100kHzほどのPWMを作成
  TCCR0A = _BV(WGM01) | _BV(WGM00);          // 高速PWM (TOP値 OC0A),
  TCCR0B = _BV(WGM02) | _BV(CS00);           // 分周なし
  TIMSK  = 0;               // タイマー割り込みの不許可 (Arduinoの時間系をつぶす)
  OCR0A  = 15;              // 62.5kHz @ 1MHz (←1MHz/16clk)  OC0B 0-15でPWMのduty比調整
}

void loop() {
  int motorPWM;             // モーターの出力
  // analogWriteは sbi(TCCR0A, COM0B1); をやってくれて OCR0Bに値を入れてくれる。
  // ただし、値が0だと digitalWrite を呼び出し、cbi(TCCR0A, COM0B1); でPWM OFFにされる。
  // ■正転(PWM制御A) スピードアップ
  cbi( TCCR0A, COM0B0 );    // OC0B非反転動作
  for( motorPWM = 1; motorPWM < 16; motorPWM++) { 
    analogWrite(  BD6211F_FIN , motorPWM ); 
    digitalWrite( BD6211F_RIN , LOW      );
    _delay_ms( 1000 );
  }
  // ■ブレーキ(停止)
  cbi( TCCR0A, COM0B0 );    // 標準ポート動作(OC0B切断)
  digitalWrite( BD6211F_FIN , HIGH );
  digitalWrite( BD6211F_RIN , HIGH );
  _delay_ms( 2000 );
  // ■正転(PWM制御A) スピードダウン
  cbi( TCCR0A, COM0B0 );    // OC0B非反転動作
  for( motorPWM = 15; motorPWM > 0; motorPWM--) { 
    analogWrite(  BD6211F_FIN , motorPWM );
    digitalWrite( BD6211F_RIN , LOW      );
    _delay_ms( 1000 );
  }
  // ■逆転(PWM制御B) スピードアップ
  sbi( TCCR0A, COM0B0 );    // OC0B反転動作
  for( motorPWM = 1; motorPWM < 16; motorPWM++) { 
    analogWrite(  BD6211F_FIN , motorPWM );
    digitalWrite( BD6211F_RIN , HIGH     );
    _delay_ms( 1000 );
  }
  // ■スタンバイ
  cbi( TCCR0A, COM0B0 );    // 標準ポート動作(OC0B切断)
  digitalWrite( BD6211F_FIN , LOW  );
  digitalWrite( BD6211F_RIN , LOW  );
  _delay_ms( 2000 );
  // ■逆転(PWM制御B) スピードダウン
  sbi( TCCR0A, COM0B0 );    // OC0B反転動作
  for( motorPWM = 15; motorPWM > 0; motorPWM--) { 
    analogWrite(  BD6211F_FIN , motorPWM );
    digitalWrite( BD6211F_RIN , HIGH     );
    _delay_ms( 1000 );
  }  
}

動いている様子です。

わかりにくいので、音で感じてください。


マブチモーター FA-130RA

マブチモーター FA-130RA



タグ:モーター

Arduino ISP を3.3Vでも使えるように [Arduino]

例えばBluetoothのモジュールをAVRマイコンに接続してしまった場合など、すでに3.3Vで周辺回路を作ってしまったときに、AVRマイコン書き換え時のISPの信号レベルが5Vだと心配です。
ISPのレベルを3.3Vにシフトすることを考えました。
調べてみると、、

RadioAgeCom:Arduino ISPによるArduinoのAVRライター化(3V対応)
http://radio-age.com/make/Arduino-ISP/index.html

こちらにまるまるそのままありました。
BSS138というFETを4個使うそうです。

bss138.png

Logic Level Converter Bi-Directional - BOB-12009 - SparkFun Electronics
https://www.sparkfun.com/products/12009

levelshift_fet.png

さて、つくろうかどうしようかと思ったところで、うちにはSeeeduinoが眠っていたことを思い出しました。
FTDIのUSBシリアル変換チップが載っていて、電源切り替えスライドスイッチ(USB/外部)やオートリセットの切り替えスライドスイッチのほかに電圧選択スライドスイッチ(5V/3.3V)がついています。

seeeduino2120.jpg

16MHzで3.3Vは保障外ですがこれでいけそうです。(まだ確認していません。)




秋月の「SDカードスロットDIP化モジュール」とArduinoをつなぐ [Arduino]

SDカードスロットとレギュレーターがセットになって2.54mmピッチのピンがついたものです。

k05818.jpg
SDカードスロットDIP化モジュール: 組み立てキット 秋月電子通商 電子部品 ネット通販
http://akizukidenshi.com/catalog/g/gK-05818/

DIP化モジュールとありますが、DIPとはDual Inline Package のことなので、本来はSIP (Single Inline Package) が正しいのではないかと思います。

特徴としては、、
(1) SPI接続するためのピンだけでている
(2) 表面にピンが出ている
(3) 入出力ともに3.3Vでプルアップされる

(1) については、SDモードを使うにはライセンスなど必要らしいのでSPIモードで十分。
(2) については、裏返しにしないと、ブレッドボードに刺さりません。シルク印刷は表面にあるので、ブレッドボードに挿してしまうとピンアサインがわからなくなってしまいます。事前にメモしておくか、ブレッドボードの端っこに挿してシルク印刷が見えるようにするかしないといけません。裏返す利点としては、ヘッダピンの根本の黒いプラスチック部品の高さと、カードスロットの厚みとが近いのでやや安定はします。
(3) については、ちょっと悩みました。いろいろ調べたところ、SDカードからの信号(SDOのみ)はArduino
のHレベル(5V)よりは電圧が低いですがそのままArduinoにつないでOK。逆の信号(SDI, CLK, CS)はそのままだと、5VがSDカードにかかってしまいSDカードが壊れてしまうかもしれません。そこでダイオードのカソードをArduino側にして間に挟んで接続します。Arduino側の信号がHのときは、ダイオードのおかげでSDカード方向には電流は流れないものの3.3VでプルアップされているのでSDカードの信号もHになります。Arduino側の信号がLのときは、SDカード側からダイオードを通ってArduinoの方に電流がながれていくのでSDカード側もLになります。(といっても順方向電圧降下があるので、0.6Vですが、Lと見なします。)

つないでみるとこんな感じ。
k05818_bb1.jpg

Arduino Leonardo と UNO で確認しました。
k05818_bb2.jpg

タグ:SDカード

USBasp使ってみた。 [Arduino]

USBaspという書込装置があります。
USBコネクタ直結タイプのものは10ピンタイプのものがほとんどですが、6ピンタイプのものを見つけたのでゲットしました。
usbasp_6p.jpg
Aliexpress内のお店で $4.40 (送料込み)、2週間ほどで届きました。

あと問題となるのはドライバ
64bit版でwindows8 ということでドライバのインストールが非常に厳しくなっています。
そこで次のソフトを使うと、いとも簡単にインストールできました。

Zadig - USB driver installation made easy
http://zadig.akeo.ie/

ここから、ソフトをダウンロードして実行するだけ。
あらかじめ別にドライバをダウンロードしておく必要もありませんでした。

実行すると、、
zadig_1.png

このブツをUSBコネクタにさしこみ、ドライバを指定。
zadig_2.png

AVRISP mkII と違って電源がきているので ATtiny45 をこんな感じでつないで、、
usbasp_pc.jpg

マイコンボードをATtiny45、書込装置をUSBaspに指定。
LチカのスケッチのLEDのピン(13番ピン)だけ書き換えて書き込みます。

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: warning: cannot set sck period. please check for usbasp firmware update.

こんな注意を受けますが、ちゃんと書き込めていました。

タグ:USBasp

GR-SAKURA、GR-KURUMI 買おうかどうしようか。

GR-SAKURA、GR-KURUMI は日本のRenesasが作っているCPUを使った Arduino と類似のマイコンボートとなっています。
日本のメーカーが作っているのでぜひ使いたいところではありますが、ちょっと特徴をしらべてみました。

がじぇっとるねさす | ルネサス エレクトロニクス
http://japan.renesas.com/gr

gadget_rene.jpg
・高性能32bit CPU 表面実装
・LAN、USBホスト、microSD(MMCカード)に初めから対応
・安価(Arduino本体と各種シールドを合わせたものと比較して)
・クラウドWebコンパイラ
・GR-KURUMIボードは乾電池1本(1.5V)で動く

簡単にはこんな感じ。

以下、あくまで個人的なArduinoとGR-SAKURAとに対する印象です。
Arduinoは、プロトタイピングが目的であり、そのプロトタイピングが早いというのが利点。
最後までArduinoを使うというものではなく最終的には、自作の基板でつくったり、Pro mini のようなボートを組み込むという用途に向いているのではないかなぁと思っています。
イーサネットシールドやUSBホストシールドなど各種シールドもありますが、これは他のマイコンボードであれば初めから搭載していて価格面でも劣っています。このシールドと同様のものを自作するのも大抵困難だと思います。
イーサネットシールドとかUSBホストシールドなどを必要とするような工作は、GR-SAKURA などといった初めから機能を搭載し、しかも安価なもので作ったほうがいいのだと思います。
GR-SAKURAは、ハード的にはだいたい利点がほとんどなのですが、表面実装CPUであり自作はほぼ困難(KURUMIならいける?)、互換機がないなどの欠点があります。
ただホビーユースとして使う上で一番気になるのは、ライセンスの注意しないといけないようです。
Arduinoはハードもソフトも基本的になにをやってもOKという感じで面倒なことを考えなくてもいいのですが、GR-SAKURAではライブラリなどは特殊電子回路株式会社という会社が作ったものでありフリーではありません。そのためGR-SAKURAという枠でのみArduinoライクなシステムの使用が許可され、Webコンパイラが使えるというかローカル環境での使用はできないといった制限があります。
逆にArduinoはGPLなのでプログラムも公開しなければならないようですが、企業の人にとってはこの点が使いにくいものになっているのかもしれません。
つまりGR-SAKURAは、ハード・ソフト・開発環境はホビーユースとして設計されているのに、ライセンスは企業向けとなっているところに違和感を感じてしまいます。
そうはいってもGR-SAKURAという枠組みを超える(外れる)ものを個人レベルで作るのは無理そうなので実質問題ないのだと思います。

RXduinoのライセンス
http://rx.tokudenkairo.co.jp/license.html


国産マイコンボードGR‐SAKURAではじめる電子工作 (I・O BOOKS)

国産マイコンボードGR‐SAKURAではじめる電子工作 (I・O BOOKS)

  • 作者: 倉内 誠
  • 出版社/メーカー: 工学社
  • 発売日: 2013/09
  • メディア: 単行本


手っ取り早くマトリックスLEDを使う その3 [Arduino]

マトリックスLEDで表示ができるようになったので、それで何かしてみようと思いました。
とりあえず、ジャンケンをしてみます。
jkp.jpg
スイッチを取り付けるのも面倒だったので、リセット毎にランダムで表示することとしました。
横スライドしやすいようにイメージデータは列毎1バイトとして作成しました。

また恥ずかしながらソースは下記のとおり。
// Arduino Pro Miniで手っ取り早くマトリックスLEDを使うスケッチ (Arduino Pro Mini専用)
//   (SZ420788K: 8x8, 0.8inch, カソードコモン)
//   を応用してジャンケンをする。
#include <avr/sleep.h>
const uint8_t MATRIX_ROW[] = {  2,  7, 17,  5, 10, 16, 11, 14 };  // 行 → デジタルピン番号
const uint8_t MATRIX_COL[] = {  6, 12, 13,  3, 15,  4,  8,  9 };  // 列 → デジタルピン番号 (左からLSB->MSB)
uint8_t *MATRIX_IMAGE;        // イメージのポインタ

uint8_t jkp_ready[] = {       // 横にスライドしやすいようにイメージは列毎にデータを作成
  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  // じゃん
  B00111111,  B01000000,  B10000000,  B10000000,  B10000010,  B01000100,  B01000001,  B00100010,
  B00000000,  B00010000,  B00010000,  B00011100,  B00110000,  B11001000,  B00001110,  B00101000,
  B00101000,  B00010000,  B00000000,  B11000000,  B00100000,  B00011000,  B00010110,  B00010001,
  B01100000,  B10000000,  B10000000,  B01000000,  B00100000,  B00000000,  B00000000,  B00000000,

  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  // けん
  B01111100,  B10000011,  B00000000,  B00000000,  B00000100,  B00000100,  B10000100,  B01111111,
  B00000100,  B00000100,  B00000000,  B11000000,  B00100000,  B00011000,  B00010110,  B00010001,
  B01100000,  B10000000,  B10000000,  B01000000,  B00100000,  B00000000,  B00000000,  B00000000,
  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  B00000000,  
};
uint8_t jkp_image[3][8] = {
  { B00111000,  B01111100,  B11111110,  B11111110,  B11111110,  B11111110,  B00111110,  B00011100 },  // グー
  { B00110000,  B01111111,  B11111111,  B11110000,  B11111111,  B11111111,  B01111000,  B00110000 },  // チョキ
  { B00110000,  B01111110,  B11110000,  B11111111,  B11110000,  B11111111,  B01110000,  B00011000 }   // パー
};
  
void setup() {
  for( int i = 2; i <= 17; i++ ) pinMode( i, OUTPUT );
  pinMode( A4, INPUT );       // ランダムな値の発生源として未接続のピンをアナログ入力にする
  TCCR2A = B00000000;         // Timer2 (8bit) のオーバーフローで割り込む。ちらつきがない分周比は
  TCCR2B = B00000010;         // dot毎なら010(8分周まで),line毎なら101(128分周まで)くらい。
  TIMSK2 = B00000001;         // TOIE2 (オーバーフロー割り込み許可)
}

void loop() {
  for( int i = 0; i < 72; i++ ) {
    MATRIX_IMAGE = jkp_ready + i;
    delay(30);
  }
  delay(200);
  MATRIX_IMAGE = jkp_image[ analogRead( A4 ) % 3 ];
  delay(2000);
  MATRIX_IMAGE = jkp_ready;   // 消灯
  delay(1);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_mode();               // リセットするまで動作停止
}

ISR( TIMER2_OVF_vect ) {
  static uint8_t row, col;
  digitalWrite( MATRIX_COL[ col ], LOW  );
  if( ++col == 8 ) {
    col = 0;
    digitalWrite( MATRIX_ROW[ row ], HIGH );
    row = ( row + 1 ) % 8;
    digitalWrite( MATRIX_ROW[ row ], LOW  );
  }
  digitalWrite( MATRIX_COL[ col ], ( MATRIX_IMAGE[ col ] >> row ) & 1 );  // データの都合で行と列を変更
}

未使用のA4ピンをアナログ入力でランダムな値の発生源としましたが、入力端子をオープン(未接続)状態にするのはどうやら本当は良くないらしい、、、。

こんな感じです。



初めてのYou Tubeへのアップロードでした。

Arduinoでの時間管理 [Arduino]

Arduinoにおける時間の扱いを Arduino IDE 1.0.5-r2 (Windows版) で調べてみました。
time.png
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino にある wiring.c を覗いてみます。

ArduinoはTimer0という8ビットのタイマ/カウンタを使用して時間の管理をしています。
CPUクロックを64分周して0から255までカウントしていきオーバーフローで割り込んで時間を計算していっているようです。

64分周でさらに256回に1回割り込むと、割り込みがかかるのにかかるクロック数は、64 x 256 clkです。
16MHzだと、割り込みがかかるのにかかる時間は、(64 x 256) / 16000000 sec = 1024 μsec となります。
割り込みのたびに、この 1024 を 1000で割った商(=1)をミリ秒のところに足していきます。
また余り(=24)を別に足していき、1000をになったらミリ秒に1を足す、、と思いきや、、余りを3ビット右シフト(=8で割る)したもの(=3)が、1000を3ビット右シフト(=8で割る)したもの(=125)になったらミリ秒に1を足していく。(3ビット右にシフト(=8で割る)しても整数であることと、8ビットでの処理ができるのでこのようにしたのだと思います。)
こんな感じで、mills()はできています。

micros() は、Timer0がオーバーフローした回数と、Timer0のカウンタを使ってできています。
CPUクロックの64分周ごと、つまり (1/16000000) x 64 sec = 4μsecごとにカウントアップしていくわけで、
micros()関数が呼ばれたときにはトータルで「(オーバーフローした回数 x 256) + 現在のカウンタ」回カウントされているので、これに4μsecをかけると、経過したμ秒が得られる。これが micros() の正体のようです。

さて、delay() はどうなっているのかというと、呼び出された時間と現在の時間をμ秒単位で(micros()を呼び出して)比較し、1000以上になったらカウントダウンしていき0になるまでループするというあんばいです。

問題は、delayMicroseconds() です。
CPUクロックが 20MHz, 16MHz, 8MHzの場合しかまともに動作しません。
これは、1サイクルで4クロック消費するループ(つまり、20MHzなら 1/5 μsec, 16MHzなら 1/4 μsec, 8MHzなら 1/2 μsecを消費するループ)をそれぞれ、必要とするμ秒数の5倍、4倍、2倍回すことでできています。
ですから ATtiny45 の 1MHz など 16MHz未満のものはすべて 8MHz として動作当然するようになっていうるので、うまいくはずがありません。
関数の呼び出しなどに伴うオーバーヘッドなども考慮された作りにはなっています。

同じような時間を止める関数がArduinoのシステムとは別にAVRのライブラリにあります。
C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\util にある delay.h , dalay_basic.h を覗いてみます。

dalay_basic.h には、_delay_loop_1() と _delay_loop_2() という2つの関数が定義されています。

_delay_loop_1() は、パラメータに8ビットの符号なし整数型でループ回数を指定、1ループあたり3クロック消費。
_delay_loop_2() は、パラメータに16ビットの符号なし整数型でループ回数を指定、1ループあたり4クロック消費。
オーバーヘッドは、1MHz動作のCPUだとそれぞれ、768μsec, 262.1msecに達するとコメントにありました。

dalay.h には、_delay_us() と _delay_ms() という2つの関数が定義されています。

_delay_us() は、F_CPU を 3000000 で割ったものに、μ秒をかけたものが、1未満なら _delay_loop_1() を1回ループ。255より大きければ(8ビットに収まらないならば)精度をミリ秒に落として _delay_ms() で処理。それ以外なら、_delay_loop_1() で処理するというもの。
つまり、16MHz の場合、256 x 3 / 16 = 48 μ秒以上だとミリ秒単位に制度がおちて、さらにオーバーヘッドについては無考慮です。
ArduinoのdelayMicroseconds()だと使えるクロックが限定されますが、よっぽど正確です。

_delay_ms() は、F_CPU を 4000 で割ったものに、ミリ秒をかけたものが、1未満なら(パラメータが1以上でF_CPUが4kHz以上ならあり得ませんが、、) _delay_loop_2() を1回ループ。65535より大きければ(16ビットに収まらないならば)F_CPUを40000で割ったものを _delay_loop_2() でループさせ(=1/10msec消費する)、それをさらにμ秒の10倍でループするという処理。それ以外なら、_delay_loop_2() でそのまま処理するというもの。_delay_loop_2() には、16bit(=65535)までしかパラメータに渡せないので、16MHzの場合、65536 x 40000 / 16000000 = 16.384 秒未満しか使えないようです。

あと、時間に関係する関数としては、pulseIn() があります。
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino にある wiring_pulse.c を覗いてみます。
こちらも信号が変化するまでループをします。ループの回数を測定しそのループにかかるクロック数をかけることでパルスの長さを得ることができます。

消費クロック数から時間を測る方法は、割り込みによる影響で誤差がでるので注意が必要なようです。

タグ:時間 Delay

Arduino TVout Library セットアップ [Arduino]

いわゆるビデオ出力(NTSC)について調べてみました。

いろいろ調べるとAVRでのカラービデオ出力は大変ということがわかりました。
AVRを14.318MHzのクリスタルで動かして、1クロック単位で出力を切り替えることで基準となる波形(バースト信号)を作り出し、その波形との位相のずれで色を作り出すというもののようです。
ArduinoとC言語だけでなんとかなるものではなさそうだということがわかりました。
モノクロの出力については同期の問題だけでなんとかなるようでした。
NTSCの規格?(RS-170A)については、

RS-170A NTSCビデオ信号タイミング規格の概要
http://elm-chan.org/docs/rs170a/spec_j.html

ここが一番正確なようでした。
AVRでビデオ出力をしているサイトをいくつか見てみると、あまりこの規格通りにやっているところはなさそうで、テレビの調整力に頼っている印象でした。
Arduinoでちょっくらこの規格通りやってみるかと頑張ってみましたが、ちょっと試したところで挫折しました。

そこで本家に行きます。TVout Library というものがあります。

Arduino Playground - TVout
http://playground.arduino.cc/Main/TVout

ただ、これどうしたらいいの?ということで、ライブラリの設定などを映像にしてくれているところを見つけました。
英語で話していて、Windowsではありませんでしたが、なんとか設定できました。

Arduino TVout Library Setup - YouTube
http://www.youtube.com/watch?v=LMu7EASMfUY

この映像を再生、停止、早送りをしながら自分がやったことを文章にしてみます。
Uno + Arduino 1.0.5-r2 で動作確認しました。

1. ライブラリをダウンロードする
  ( http://code.google.com/p/arduino-tvout/ → Dounloads → TVoutBeta1.zip )
  そして展開する
2. Arduino IDEを起動し、スケッチブックの保存場所を確認する
  (ファイル → 環境設定 → スケッチブックの保存場所)
  そして一旦Arduino IDEは終了
3. 先ほど確認したスケッチブックの保存場所に「libraries」というフォルダを作成する
4. librariesフォルダに展開した3つのフォルダをコピーする
5. Arduino IDEを再度起動
6. スケッチ → ライブラリを使用 で、ユーザ提供 以下にライブラリが追加されていることを確認
7. ファイル → スケッチブック → libraries → TVout → DemoNTSC を開いてみる

という感じです。
Arduinoでここまでできるのかと感心いたしました。

ところで、ブレッドボードで実験の際に、

RCAジャックDIP化キット(黄): 組み立てキット 秋月電子通商 電子部品 ネット通販
http://akizukidenshi.com/catalog/g/gK-06522/
k-06522.jpg
こんなものを使ってみました。
ちょっと残念だったのは、細ピンヘッダが付属しており、通常のピンヘッダは使えないということです。
ビデオコードとつなぐとテコの原理でブレッドボードから抜けやすいのです。




手っ取り早くマトリックスLEDを使う その2 [Arduino]

前回のスケッチだと、マトリックスLEDに何か表示することが目的となっており他の処理がしづらい状態でした。
表示自体は割り込みを使って、CPUを解放してみました。

// Arduino Pro Miniで手っ取り早くマトリックスLEDを使うスケッチ (Arduino Pro Mini専用)
//   (SZ420788K: 8x8, 0.8inch, カソードコモン)
//   timer2使用
const uint8_t MATRIX_ROW[] = {  2,  7, 17,  5, 10, 16, 11, 14 };  // 行 → デジタルピン番号
const uint8_t MATRIX_COL[] = {  9,  8,  4, 15,  3, 13, 12,  6 };  // 列 → デジタルピン番号 (左からMSB -> LSB)
uint8_t *MATRIX_IMAGE;        // イメージのポインタ

uint8_t face_smile[] = {      // にこにこ
  B00111100,
  B01000010,
  B10100101,
  B10000001,
  B10100101,
  B10011001,
  B01000010,
  B00111100 };

uint8_t face_angry[] = {      // ぷんぷん
  B00111100,
  B01000010,
  B10100101,
  B10000001,
  B10011001,
  B10100101,
  B01000010,
  B00111100 };
  
void setup() {
  for( int i = 2; i <= 17; i++ ) pinMode( i, OUTPUT );
  TCCR2A = B00000000;         // Timer2 (8bit) のオーバーフローで割り込む。ちらつきがない分周比は
  TCCR2B = B00000010;         // dot毎なら010(8分周まで),line毎なら101(128分周まで)くらい。
  TIMSK2 = B00000001;         // TOIE2 (オーバーフロー割り込み許可)
}

void loop() {
  MATRIX_IMAGE = face_smile;
  delay(1000);
  MATRIX_IMAGE = face_angry;
  delay(1000);
}

ISR( TIMER2_OVF_vect ) {
  static uint8_t row, col;
  digitalWrite( MATRIX_COL[ col ], LOW  );
  if( ++col == 8 ) {
    col = 0;
    digitalWrite( MATRIX_ROW[ row ], HIGH );
    row = ( row + 1 ) % 8;
    digitalWrite( MATRIX_ROW[ row ], LOW  );
  }
  digitalWrite( MATRIX_COL[ col ], ( MATRIX_IMAGE[ row ] >> col ) & 1 );
}

交互に顔が変わります。
matrix_angry.jpg
loop() 関数内は、Lチカみたいな感じかな?


Arduino Pro Mini 328 5V 16MHz

Arduino Pro Mini 328 5V 16MHz

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス


前の10件 | -

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。