論文みたいなタイトルつけてみましたw書いた事無いですが
AVRの8bitタイマ(Timer0,Timer2)の高速PWMモードでブラシレスアンプを制御することができました。
もちろんサーボモーターにも応用できるはずです。(信号部分は共通だが初期化部分は不要)
詳しい信号については他のページを参照していただきたいです。
なぜこのページが有用かといえば、AVRからサーボモータやブラシレスアンプを制御する資料はなぜか周期20msにこだわって数少ない16bitタイマー(Timer1)を使用するものばかりだからです。
Timer1を使うとAVR1つあたり1つしか使用できないサーボモータやブラシレスアンプを、これなら4つ同時に制御できます!
今回使用したのはヘリ用ののアンプ。
初期設定のまま使用しました。
ブレーキなし、一方向の回転のみ(これは変わりませんが)です。
まず悩んだのは初期化の仕方。
初期化なしでは全く回りませんでした。そこで
AVR Tiny13を用いて信号解析用にブレッドボードで回路を製作。
そして試行錯誤の結果出た結論が
「暫く1.5msのパルス→ブッブッブッブッブッ→暫く2.0msのパルス→プププッ→初期化完了!」
というフローチャートです。
もちろんサーボモータなら初期化いりませんが。
そして早速プログラムへ実装!
(開発環境はAVR Studio4,WinAVR使用)
※HTMLの関係から、<は<に、/は/に直してからご使用ください
/*
PWMによるブラシレス制御(アンプ使用)
rev 2 :2011/8/2
ATMega328P,16MHz
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define PWM1 OCR0A
#define PWM2 OCR0B
#define PWM3 OCR2A
#define PWM4 OCR2B
#define PWM_FOR 31//2ms
#define PWM_NEUTRAL 23//1.5ms
#define PWM_STOP 15//1ms
uint16_t i;
void delay_ms(uint16_t ms){
while(ms–){
_delay_ms(1);
}
}
void delay_us(uint16_t us){
while(us–){
_delay_us(1);
}
}
void ioinit(){
DDRD|=0b01101000;//PWM
DDRB|=0b00001000;//PWM
}
void set_pwm(uint8_t pw1,uint8_t pw2,uint8_t pw3,uint8_t pw4){
PWM1=pw1;
PWM2=pw2;
PWM3=pw3;
PWM4=pw4;
}
void init_pwm(){
//タイマー0
TCCR0A = 0b10100011; //非反転 8ビット高速PWMモード
TCCR0B = 0×05; //1024分周
//タイマー2
TCCR2A = 0b10100011; //非反転 8ビット高速PWMモード
TCCR2B = 0×07; //1024分周
}
int main(){
delay_ms(500);//起動待ち
ioinit();delay_ms(10);
init_pwm();delay_ms(10);
/*初期化*/
set_pwm(PWM_NEUTRAL,PWM_NEUTRAL,PWM_NEUTRAL,PWM_NEUTRAL);
delay_ms(5000);
set_pwm(PWM_STOP,PWM_STOP,PWM_STOP,PWM_STOP);
delay_ms(5000);
while(1){
set_pwm(PWM_FOR,PWM_FOR,PWM_FOR,PWM_FOR);
delay_ms(1000);
set_pwm(PWM_STOP,PWM_STOP,PWM_STOP,PWM_STOP);
delay_ms(1000);
}
}
以上です。
サーボモーターの場合は/*初期化*/の下の4行が不要ですね。
速度調節は16段階できるようになっています。(試したところあのアンプはパルス幅1.0ms~2.0msまで順々に速度が上がっていくようです)
やはり同時に多数の特殊モーターを制御できるのは嬉しいですね!
9/1追記:
初期化不要で、サーボモーターも動きました。
9/13追記:
プログラムのPWMの初期化部分がコメントはあってるのに値が間違っていたのを修正(TCCR2Bレジスタ)