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

ATtiny85のタイマーを使う [Arduino]

生のATtiny85とDigisparkとではタイマーの使い方が違っていました。

C:\Users\(user)\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny\core_build_options.h より、
/*
  For various reasons, Timer 1 is a better choice for the millis timer on the
  '85 processor.
*/
#define TIMER_TO_USE_FOR_MILLIS                   1

Digisparkでは、やんごとなき理由でミリ秒のカウント用にタイマー1を使っているそうです。

タイマー0を使うか、タイマー1の割り込みを殺すかになります。

PWM使用(8bit高速PWM(TOP=0xff), 分周なし)の時のATtiny85用設定の覚え。
// PLLCSR - PLL制御/状態レジスタ (PLL Control and Status Register)
PLLCSR = B00000110;             // 0x06 (初期値)

// TIMSK - タイマ/カウンタ割り込み許可レジスタ (Timer/Counter Interrupt Mask Register)
TIMSK &= ~_BV(TOIE0);           // Timer0の割り込みを殺す場合
TIMSK &= ~_BV(TOIE1);           // Timer1の割り込みを殺す場合

// TCCR0A - タイマ/カウンタ0制御レジスタA (Timer/Counter0 Control Register A)
//         COM0A1 | COM0A0 | COM0B1 | COM0B0 | - | - | WGM01 | WGM00
TCCR0A = B10100011;             // OC0x比較一致でLow (表11-3参照)
                                // WGM02-0:8ビット高速PWM動作 (TOP値 $FF) (表11-5参照)

// TCCR0B - タイマ/カウンタ0制御レジスタB (Timer/Counter0 Control Register B)
//         FOC0A | FOC0B | - | - | WGM02 | CS02 | CS01 | CS00
TCCR0B = B00000001;             // CS02-1:前置分周なし (表11-6参照)

// TCCR1 - タイマ/カウンタ1制御レジスタ (Timer/Counter0 Control Register)
//         CTC1 | PWM1A | COM1A1 | COM1A0 | CS13 | CS12 | CS11 | CS10
TCCR1  = B01100001;             //  PWM動作A許可, OC1A比較一致でLow, ~OC1Aピン接続断 (表12-1参照), CK×16 (PCK)
                                //  PWM1A=1, COM1A1=1, COM1A0=0, CS13=0, CS12=0, CS11=0, CS10=1

// GTCCR - 一般タイマ/カウンタ制御レジスタ (General Timer/Counter Control Register)
//         TSM | PWM1B | COM1B1 | COM1B0 | FOC1B | FOC1A | PSR1 | PSR0
GTCCR  = B01100000;             //  PWM動作B許可, OC1B比較一致でLow, ~OC1Bピン接続断 (表12-1参照)
                                //  PWM1B=1, COM1B1=1, COM1B0=0
//OCR1C - タイマ/カウンタ1 比較Cレジスタ (Timer/Counter1 Output Compare Register C)
OCR1C  = 255;                   //  OCR1Cはタイマ/カウンタ1の最大値(比較一致での解除値)

// 高速PWM動作時に COM0x1 を 0 で標準ポート動作 (OC0x切断) (WGM02=0のとき)
// 高速PWM動作時に COM1x1 を 0 で標準ポート動作 (OC1x切断)

// TIFR - タイマ/カウンタ割り込み要求フラグ レジスタ (Timer/Counter Interrupt Flag Register)
while( !(TIFR & _BV(TOV0)) );   // タイマー0がオーバーフローするのを待つ
TIFR |= _BV(TOV0);              // Timer/Counter0 Overflow Flag をクリア 
                                //   (論理1を書くことによってもTOV0は解除(0)できる)
while( !(TIFR & _BV(TOV1)) );   // タイマー1がオーバーフローするのを待つ
TIFR |= _BV(TOV1);              // Timer/Counter1 Overflow Flag をクリア
                                //   (論理1を書くことによってもTOV1は解除(0)できる)

// タイマーを殺したときのdelay
void delayCentiseconds16M5Hz( uint16_t ds ) {       // 16.5MHz動作時 0.01sec単位のdelay
  while( ds-- )  _delay_loop_2( 41250 );            // 1MHzなら 2500
}

void delayCentiseconds16MHz( uint16_t ds ) {        // 16.5MHz動作時 0.01sec単位のdelay
  while( ds-- )  _delay_loop_2( 40000 );            // 1MHzなら 2500
}

(参考) wiring_private.h の cbi(), sbi()
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

digispark_wav.jpg
DigisparkでWAVファイル配列化したものを再生する。
// Digispark(Default 16.5MHz)で WAVファイル(8bit, 4kHz, monoral) を配列化したものを再生する。
#include <util/delay_basic.h>   // _delay_loop_2() を使うため
#include <avr/pgmspace.h>       // PROGMEM使用時のお約束
#include "hello4.h"             // 音声データ hello4[]  =「こんにちは」8bit,  4kHz,  monoral

void setup() {
  pinMode( 1, OUTPUT);          //  OC1A(PB1)
  TCCR1 = B01100001;            //  8ビット タイマ/カウンタ1用レジスタ (PWM動作A許可, OC1A比較一致でLow, ~OC1Aピン接続断)
  OCR1C = 255;                  //  タイマ/カウンタ1 比較Cレジスタ
  TIMSK &= ~_BV(TOIE1);         //  タイマ/カウンタ1溢れ割り込み許可(TOIE1) 取り消し
}

void loop() {
  playWav( hello4 );            // hello4[]を再生
  delayCentiseconds16M5Hz(100); // 100センチ秒 = 1秒まつ 
}

void playWav( const uint8_t d[] ) { 
  uint8_t  cyc;                                     // 次の1byte読み込むまでのサイクル数カウンタ(cyc)
  uint16_t i, len = pgm_read_word_near(&d[0x28]);   // データサイズ
  for( i = 0x2c; i < len;) {
    if(!(cyc = ++cyc % 16))  OCR1A =  pgm_read_byte_near(&d[ i++ ]);  // 8kHzの音声なら 除数を16→8へ
    while( !(TIFR & _BV(TOV1)) );                   // タイマのオーバーフロー待ち (256cycle @ 16.5MHz≒15.5usec毎)
    TIFR |= _BV(TOV1);                              // Timer/Counter1 Overflow Flag をクリア
  }
}

void delayCentiseconds16M5Hz( uint16_t ds ) {       // 16.5MHz動作時 0.01sec単位のdelay
  while( ds-- )  _delay_loop_2( 41250 );            // 1MHzなら 2500
}

Arduinoとスピーカだけで音声を出す [Arduino]

ATmega328はフラッシュメモリーが32kBあるので、非圧縮 8bit 8kHz モノラルならプログラムに使う領域を除くと約4秒弱再生できるはずです。
短いように思いますが、ちょっとした効果音や音声くらいなら意外といけます。
探せば同様のプログラムはありそうですが練習も兼ねてちょっと作ってみました。
ATmega328搭載で16MHz駆動のArduinoで、8bit, モノラル, 4/8/16kHzのみの対応です。
hello4816.jpg
再生音声の素材は以下から。

効果音ラボ - フリー、商用無料、報告不用の効果音素材をダウンロード:
http://soundeffect-lab.info/

から、

日常セリフ(元気な女の子)|声素材|効果音ラボ:
http://soundeffect-lab.info/sound/voice/line-girl1.html

の「こんにちは」をいただきました。ありがとうございました。
これを、フリーのサウンド編集ソフト「Audacity」をつかって変換します。

Audacity:
http://www.audacityteam.org/

無音の部分があるので、波形のあるところだけトリミングして、左下にある「プロジェクトのサンプリング周波数(Hz)」を16000 / 8000 / 4000 のいずれかにします。(4000の場合は手入力)
「ファイル」→「オーディオの書き出し...」→「ファイルの種類:その他の非圧縮ファイル」→「ヘッダ:WAV (Microsoft)」→「エンコーディング:Unsigned 8-bit PCM」として「保存」します。ファイルの拡張子がaiffになりますが、中身はWAVファイルになっているようです。
これを先日の「PROGMEM作蔵さん」で変換します。変数名だけ適当に変えておきます。
それをヘッダファイルにして、以下のスケッチと同じフォルダに入れておきます。

・メインのスケッチ
// WAVファイル(8bit, 4/8/16kHz, monoral) を配列化したものを再生する。
#include <avr/pgmspace.h>       // PROGMEM使用時のお約束だが、実はなぜだか書かなくても動く
#include "hello16.h"            // 音声データ hello16[] =「こんにちは」8bit, 16kHz,  monoral
#include "hello8.h"             // 音声データ hello8[]  =「こんにちは」8bit,  8kHz,  monoral
#include "hello4.h"             // 音声データ hello4[]  =「こんにちは」8bit,  4kHz,  monoral

const uint8_t C16kHz[] = { 3,4,4,4,4,4,4,4,4,4,4,3,4,4,4,4,4,4,4,4,4,4,3,4,4,4,4,4,4,4,4,4 };   // サンプリングレート調整用配列 (16kHz)
const uint8_t C8kHz[]  = { 7,8,8,8,8,7,8,8,8,8,7,8,8,8,8,8 };                                   // サンプリングレート調整用配列 (8kHz)
const uint8_t C4kHz[]  = { 15,16,16,15,16,16,15,16 };                                           // サンプリングレート調整用配列 (4kHz)

void setup() {
  pinMode( 9, OUTPUT);          // OC1A(PB1)
  pinMode(10, OUTPUT);          // OC1B(PB2)   逆位相波で出力を上げるより、同出力の2ピンをまとめることで電流を上げる
    // 8bit高速PWM(TOP=0xff), 分周なし, コンペアマッチでLow (256clock毎に割り込み)
  TCCR1A = B10100001;           // コンペアマッチでLow(COM1A1=1, COM1A0=0, COM1B1=1, COM1B0=0), タイマモード設定(一部)(WGM11=0, WGM10=1) 
  TCCR1B = B00001001;           // タイマモード設定(一部)(WGM13=0, WGM12=1), クロック分周の設定(CS12=0, CS11=0, CS10=1)
}

void loop() {
  playWav( hello16 );
  delay(1000);
  playWav( hello8 );
  delay(1000);
  playWav( hello4 );
  delay(2000);
}

void playWav( const uint8_t d[] ) { 
  uint8_t  c = 0, cyc = 1;                      // 次の1byte読み込むまでのサイクル数カウンタ(cyc)とサイクル数調整用配列のポインタ(c)
  uint16_t i, rate, len;
  rate = pgm_read_word_near(&d[ 0x18 ]);        // サンプリングレート (本来は32bitのデータだが下位の16bitで十分)
  len  = pgm_read_word_near(&d[ 0x28 ]);        // データサイズ       (本来は32bitのデータだがATmega328では32kB以下なので十分)
  for( i=0; i<128;) {  while(!(TIFR1 & _BV(TOV1)));  TIFR1|=_BV(TOV1);  OCR1A=OCR1B=i++;  }     // ポップノイズ軽減
  for( i = 0x2c; i < len;) {
    if( --cyc == 0 ) {                          // サイクル(16usec)のカウントダウンが終わったら次のデータへ
      OCR1A = OCR1B = pgm_read_byte_near( &d[ i++ ] ); 
      cyc = ( rate == 16000 ) ? C16kHz[ c++ & B11111 ] : ( rate == 8000 ) ? C8kHz[ c++ & B1111 ] : C4kHz[ c++ & B111 ];
    }
    while( !(TIFR1 & _BV(TOV1)) );              // タイマーがオーバーフローするのを待つ (256cycle @ 16MHz = 16usec毎)
    TIFR1 |= _BV(TOV1);                         // Timer/Counter1 Overflow Flag をクリア (論理1を書くことによってもTOV1は解除(0)できる)
  }
  for( i=127; i;  ) {  while(!(TIFR1 & _BV(TOV1)));  TIFR1|=_BV(TOV1);  OCR1A=OCR1B=--i;  }     // ポップノイズ軽減
}

・音声のヘッダファイル(.h) (ファイルを変換後、変数bindata[]のところは適当に名前を付ける)
// file name : hello16k.aiff
// file size : 12043 bytes

const uint8_t hello16[] PROGMEM = {
  0x52,0x49,0x46,0x46,0x03,0x2f,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,
  0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x80,0x3e,0x00,0x00,0x80,0x3e,0x00,0x00,
  0x01,0x00,0x08,0x00,0x64,0x61,0x74,0x61,0xdf,0x2e,0x00,0x00,0x80,0x80,0x80,0x80,
 ~ 略 ~ 
  0x80,0x80,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7f,0x7f,0x80
};

16 / 8 / 4 kHzの聞き比べでは、16kHzがいいのはもちろんですが、8kHzでもやや高音のキレがないものの十分聞くに堪えられます。4kHzはもごもごした感じでやや厳しいです。
タグ: 音声 wav

バイナリファイルをC言語のデータ配列に変換する [Arduino]

大きなデータを扱うにあたり、ファイル操作が可能なシステムならファイルの読み書きで対応が可能ですが、Arduino単体ではプログラム領域上にデータを持つしかありません。
数~数10kBのFlashメモリにデータを置き、そこから読み込むということになります。
テキストデータならプログラム上に載せるのもなんとかなりそうですが、バイナリデータの場合にはデータをどうやって持ってくるか考えてしまいます。
通常大きなデータというのはファイルに保存されているので、それをそのまま配列に変換するのが現実的と思います。
というわけで、HTML5 + JavaScript で変換スクリプトつくりました。
サンプルプログラムの寄せ集め+スタイルシートが雑ですが、Drag & Dropするだけなので使いやすいと思います。

pgmsakuzo.png
次のコードをテキストエディタでhtmlとして保存します。HTML5なのでUnicode(UTF-8)です。

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>PROGMEM作蔵さん</title>
<style>
  html, body {  height: 90%;  background:#ffffff;  }
  h1         {  border:dotted 2px;  border-radius:20px;  padding:20px;  }
  h1, h3, p  {  color:#776666;  text-align:center;  margin:50px;  }
  code       {  color:#444444;  font-size:75%;  }
</style>
<script>
function DragOver( event ) {
    event.preventDefault();                 // ブラウザデフォルト処理(禁止マーク)を阻止
}
function Drop( event ) {
    event.preventDefault();                 // ブラウザデフォルト処理(ページ移動)を阻止
    var f = event.dataTransfer.files[0];    // イベントに格納されたファイルを取り出し
    var code = "<pre><code>"
    code += "// " + "file name : " + f.name + "\n";
    code += "// " + "file size : " + f.size + " bytes\n\n";
    code += "const uint8_t bindata[] PROGMEM = {";
    var reader = new FileReader();
    reader.onloadend = function(){
        var uint8array = new Uint8Array(reader.result);
        for( var i = 0; i < f.size; i++) {
            if( i != 0 )    code += ",";
            if( !(i % 16) ) code += "\n  ";
            code += ( uint8array[i] > 15 ? "0x" : "0x0" );
            code += ( uint8array[i].toString(16) );
        }
        code += "\n};\n\n</code></pre>";
        document.getElementById("main").innerHTML = code;
    };
    reader.readAsArrayBuffer( f );
}
</script>
<body ondragover="DragOver(event);" ondrop="Drop(event);" id="main" >
<h1>PROGMEM作蔵さん</h1>
<h3>バイナリファイルをC言語のデータ形式に変換</h3>
<p>ここにファイルをドロップ</p>
</body>
</html>

const uint8_t bindata[] PROGMEM = { ... };
のかわりに、
var bindata = [ ... ]; (最近はvarよりlet, const?)
にすれば、JavaScript にも応用が可能です。

Arduino 1.6時代のATtiny開発 - その5 [Arduino]

あと環境整備としては ATtiny13 です。

AVRマイコン ATTINY13A-PU: マイコン関連 秋月電子通商 電子部品 ネット通販:
http://akizukidenshi.com/catalog/g/gI-02911/

tx30-13a-pu.jpg

1個 ¥50(税込)ということで魅力的ではあります。
これを1.6.x環境で使うためにいろいろ探していたら見つけてしまいました。

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

other_chips.png
ATtiny13はもちろん、いろんなAtmelチップに対応できるようです。
Boards Manager URLがついているものであれば簡単にセットアップが可能っぽい。
便利な時代になりました。
タグ:ATtiny ATtiny13

Arduino 1.6時代のATtiny開発 - その4 [Arduino]

今回はoptibootについて、、
自分では試していません。とりあえず情報だけ。
そもそもですが、ISPで書き込めるのに、あえてシリアル通信で書き込む必要があるかどうか。

<メリット>
・既存のUSBシリアル変換器が使える
・もともとシリアル通信をするハードをつくる予定なら共用できて便利
・ISPよりI/Oピン数を減らせる(VCC, GND, Resetを除くと 3→2本ですむ)

<デメリット>
リセットのパーツが必要
・プログラムの書き込み容量が減る
・optibootはあるか?ボードマネージャで簡単インストールできるか?

前回のボードマネージャでの追加で、ATtiny 841, 1634, 828, 167, 87 にはoptibootがありましたが、ATtiny85は、、、
optibootありました。

GitHub - TCWORLD/ATTinyCore: ATTiny Core for Arduino 1.0+:
https://github.com/TCWORLD/ATTinyCore

さらに探すとボードマネージャもありました。

Bootload Your ATtiny85 - Hackster.io:
https://www.hackster.io/porrey/bootload-your-attiny85-625387

どうやら、Snapduino というプロジェクトのようです。

Snapduino - Hackster.io:
https://www.hackster.io/porrey/snapduino-e5f0a5

Snapduino_bb.png

Arduino 1.6時代のATtiny開発 - その3 [Arduino]

ATtiny85での開発には、「Adafruit Trinket」や「8pino」や「Digispark USB Development Board」 というボードを使う手もあります。
「Adafruit Trinket」≒「8pino」ですが、≠「Digispark USB Development Board」なので注意が必要です。

一番安いのは「Digispark USB Development Board」の互換製品で、microUSBバージョンもあり、Amazon.co.jpやAliExpressにて安価で手に入ります。
digispark.jpg

Digispark USB Development Board - Digistump:
http://digistump.com/products/1

ここの「Resources」というタブを選択し、
「Software:Download Page」をクリックし移動すると、
http://digistump.com/wiki/digispark/tutorials/connecting
ページがかわります。Bootloaderは書き込んであるはずなので、
Installation Instructions:
をよく読んで設定していきます。

さて、この手のアイテムで気になるのは、「ピン・ソケット・表裏問題」。
ピンをつけるのか、ソケットをつけるのか、表につけるのか、裏につけるのか。

さらに問題を複雑化させているのが、I/Oピンと電源関連ピンが直交していること。

いろいろ考えた末、裏にピンをつけて、ブレッドボードで運用することにしました。
ただ、ピンのつけ方とブレッドボードの選択に注意が必要です。

電源関連ピンは、5VとGNDのみにピンをはんだ付けして、VINは使用しないことにしました。
(ボード上のレギュレータは無駄になります。)
digispark_m.jpg
よくあるブレッドボードは電源ラインのピッチが半分ずれているので使えませんが、サンハヤトのブレッドボード(ニューブレッドボード SAD-101)ならOKでした。
他にはボード上の極性の記号が逆にはなりますが「Cake Board」もささりそう。

ただこの Digispark で ISR(TIMER1_OVF_vect) を使おうと思ったらすでに使われているらしく使えませんでした。USBasp で ATtiny85 マイコンに直書きしたときには使えたのに、、。
若干の違いはあるみたいです。


サンハヤト SAD-101 ニューブレッドボード

サンハヤト SAD-101 ニューブレッドボード

  • 出版社/メーカー: サンハヤト
  • メディア: Tools & Hardware


Cake Board ケーキボード LEGOフレンドリー 新ブレッドボード

Cake Board ケーキボード LEGOフレンドリー 新ブレッドボード

  • 出版社/メーカー: BreadBoardManiac
  • メディア: エレクトロニクス


Arduino 1.6時代のATtiny開発 - その2 [Arduino]

さて、ATtinyへの書き込みはどうしたものでしょうか?

その1 で紹介したものからボードを選択するところには、
(optiboot)
なんてものがありました。
シリアル通信で書き込みができるようですが、そもそもそのブートローダーが書き込めない。

現実的な選択肢としては、Arduino as ISP か、USBasp か、AVRISP mkII かのいずれか。

Arduino as ISP は簡易的ですが、ついついATtiny用の自作スケッチを ATtiny ではなく Arduino本体に書き込むという間違いをしがちで、あまり好きではありません。

AVRISP mkIIは、電源が来ていないのであんまり使わなかったら、どこかに行ってしまったし。

ということで、USBaspを使用することにしました。
ところがうまく行きません。
解決方法が以下にありました。

[SOLVED]Problems using USBasp with Arduino IDE 1.6.10/Arduino AVR Boards 1.6.12:
https://forum.arduino.cc/index.php?topic=415210.0
1. Plug in USBasp
2. Download Zadig from http://zadig.akeo.ie
3. Start zadig
4. Options > List all devices
5. Select USBasp from the drop down menu
6. Select libusbK(v3.0.7.0) driver
7. Click Install

Zadigは以前にも紹介しましたが、「libusbK」を選択するのが肝のようです。

6ピンのUSBaspはなかなか見かけませんが、AliExpressで「AVR Programmer 6PIN Wire」と検索すると出てきます。
usbasp6pin.jpg
(ちゃんと6ピンのものが届くかどうか保証するものではありません。)

私がもっているUSBaspはこんな感じで、
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: warning: cannot set sck period. please check for usbasp firmware update.

firmware updateをするようにwarningが出ますが、書き込めています。
タグ:ISP USBasp

Arduino 1.6時代のATtiny開発 - その1 [Arduino]

久しぶりに電子工作にもどってきました。
Arduino IDEも大きく進化していました。
arduino1_6.png
Arduino 1.6時代に入り、ATtinyでの開発環境の整備ががらりと変化していました。

High-Low Tech – Programming an ATtiny w/ Arduino 1.6 (or 1.0):
http://highlowtech.org/?p=1695

GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8:
https://github.com/SpenceKonde/ATTinyCore

などを参照するといとも簡単にATtinyの開発環境ができあがります。

私は ATtiny45, ATtiny85, ATtiny44, ATtiny84 以外にも ATtiny 2313などにも興味があったので後者を選択しました。
「Installation」をクリックすると下記のページに移り、(英語で)インストールの方法が記載してあります。

ATTinyCore/Installation.md at master · SpenceKonde/ATTinyCore · GitHub:
https://github.com/SpenceKonde/ATTinyCore/blob/master/Installation.md

注意点ですが、、
Arduino 1.6.9 はOK、1.6.10 はだめなどバージョンに注意が必要そうです。
Arduino Software Release Notes には、
ARDUINO 1.6.11 - 2016.08.17

[ide]
* Fixed a serious bug that prevented some 3rd party boards, installed through external index.json URL, to work correctly.
 ...

と、書いてあったので、1.6.11 以降ならよさそう?

タグ:IDE ATtiny

モータードライバでモーターを動かしてみる。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



タグ:モーター
前の10件 | -

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