AVRのサーボ制御で困っています。
AVRマイコンを用いてサーボを8個制御するプログラムをC言語で作っています。使っているマイコンはATmega64LでサーボはフタバのS3003、AVRstudio4.17とAVR-GCCを用いてコンパイルやシュミレートをしています。
プログラムはサーボを8個動かすために
タイマ2の比較一致割り込みで2.5msの周期をつくり
タイマ0の比較一致割り込みで0.5ms~2.5msのパルスをつくり
main関数でサーボの角度を制御するというものです。サーボ8個の角度の保持にはグローバル変数を用いています。
「サーボ初期位置→サーボ2個移動して固定」はうまくいくんですが「サーボ初期位置→※サーボ2個移動→さらに他のサーボ2個移動→はじめに動かしたサーボ2個を初期位置へ」というプログラムを書いたら、なぜか※をつけた「サーボ2個移動」の部分が実行されずその次の行動から実行されてしまいます。これはAVRに書き込んで確認したもので、シュミレータで確認するためにwait()などの待つ処理を除いてシュミレートしてみたのですが、「サーボ2個移動」の2行を飛ばして実行してしまっています。
具体的に飛ばされている部分は後述のソースコードのdo{・・・}while(1);の中の
servopos[FR_LEG]=31;
servopos[RL_LEG]=31;
で、do{・・・}while(1);の無限ループはservopos[FR_JOINT]=70;からservopos[RL_LEG]=94;を無限ループしています。
電気回路、C言語ともに初心者なので見当がつかず、いろいろ試したり調べてみてもわかりませんでした。
質問は「なぜこのようにプログラムを数行飛ばして実行してしまっているのか」です。ソースコードの指摘をしていただけると有り難いです。
ソースコード
#include <avr/io.h>
#include <avr/interrupt.h>
#define RL_JOINT 0
#define FR_JOINT 1
#define FL_LEG 2
#define RL_LEG 3
#define FL_JOINT 4
#define RR_JOINT 5
#define RR_LEG 6
#define FR_LEG 7
uint8_t phase=0;
uint8_t servopos[8]={94,94,94,94,94,94,94,94};
/*
void wait(uint16_t w){
while(w--){
volatile uint16_t i=200;
while(i--);
}
}
*/
ISR(TIMER2_COMP_vect){
PORTC=0x00;
TCNT0=0;
}
ISR(TIMER0_COMP_vect){
PORTC |= (1<<phase);
OCR0 = servopos[phase];
phase++;
if(phase>7){phase=0;}
}
int main( void ){
//ポート設定
DDRC=0xFF;
PORTC=0x00;
//タイマ0設定
OCR0 = 94;
TCCR0 |= (1<<WGM01)|(1<<CS02)|(1<<CS00);
TIMSK |= (1<<OCIE0);
//タイマ2設定
OCR2 = 79;
TCCR2 |= (1<<WGM21)|(1<<CS22);
TIMSK |= (1<<OCIE2);
// 全体割り込み許可
sei();
do{
// wait(10000);
servopos[FR_LEG]=31;
servopos[RL_LEG]=31;
// wait(1000);
servopos[FR_JOINT]=70;
servopos[RL_JOINT]=70;
// wait(1000);
servopos[FR_LEG]=94;
servopos[RL_LEG]=94;
}while(1);
}
お礼
ありがとうございます。そして返信遅れました。 私は、コンピュータ制御なのだからデジタル信号のほうが誤動作が少ないとか、アナログ信号だとAD変換をしてからコンピュータで制御しなきゃいけない(だから手間がかかる) などの理由が思い浮かびました。 ・・・普通に考えれば当然ですよね。 参考になりました!ありがとうございました。