3

サーボ ライブラリと外部割り込みルーチンを使用するプログラムがあります。私の理解では、サーボ ライブラリは Timer1 割り込みを使用してパルスをサーボに送信し、位置を維持します。割り込み中に増加しないため、micros() カウントにどのような影響があるのか​​ 疑問に思っています。

私のコードの外部割り込みルーチンはタコメーター用です。これは、micros() を使用してパルス間​​の時間を決定します。Servo ライブラリが millis() および micros() カウンターのドリフトを引き起こし、速度が不正確になることが懸念されます。タコメーターは、10,000 RPM の速度を感知する必要がある場合があるため、約 167 Hz になります。最終的にはサーボとタコメーターを使ったPID制御を実装します。

volatile unsigned long period;
unsigned long microseconds;

void setup(){
    Serial.begin(9600);
    pinMode(tachometerPin, INPUT);

    pinMode(led, OUTPUT);

    attachInterrupt(0, tachometer, RISING); // set external interrupt

    throttle.attach(throttlePin); // attach servo objects to pins
    fuel.attach(fuelPin);
    throttle.writeMicroseconds(throttle_idle); // set servo positions
    fuel.writeMicroseconds(fuel_neutral);
}
void loop(){
    Serial.println(calculateSpeed());
}

float calculateSpeed(){
    /* Calculate speed of engine in RPM */
    float s = 60.0/(period*0.000001);
    return(s);
}
void tachometer() {

    /* Determine time between rotations of engine (pulses from tachometer) */
    period = micros() - microseconds;
    microseconds = micros();
}
4

1 に答える 1

3

さらにtachometer()、更新する関数millis()は割り込みから呼び出されるため、コードを「壊す」ことさえあります。

これはあなたの講義をどれだけ台無しにするでしょうか?それほどでもない。Arduino 2009 は、16 MHz 用の水晶を使用しており、1 日で数秒のドリフトがあります。精度の低い発振器を使用する Arduino Uno は、さらにドリフトします。

したがって、割り込みルーチンで多くの計算を行っていない限り、問題ありません。また、micros() の呼び出しには 4 µs のコストがかかることも覚えておいてください (実際には、4 x 4 ずつ増加することがわかります... または、これは Timer0 が毎秒オーバーフローするためでしたか? タイマー プリスケーラーを見てください。それは Servo lib を壊しません. millis() と micros() を壊します.Timer1 または Timer2 を使うことができますが,Timer0 は唯一の 16 ビット タイマーなので、あなた次第です.キラー。

割り込みでの関数呼び出しを排除することをお勧めします。

unsigned long tmpTime;
void tachometer() {

    /* Determine time between rotations of engine (pulses from tachometer) */
    tmpTime = micros();
    period = tmpTime - microseconds;
    microseconds = tmpTime;
}

そして、 attachInterrupt でさえ、関数を呼び出す ISR を呼び出します。attachInterrupt を自分で実装して、ISR を直接実装することもできます (関数呼び出しが 1 つ少なくなり、スタックとレジスタを操作する必要があるため、関数呼び出しは比較的高価になります)。

また、多くのことを行う micros() も使用しないでください (Timer0 の実際のカウントを読み取り、カウントを µs まで計算し、関数呼び出しを行います)。タイマーレジスタを直接読み取り、その値との差を計算し、カウントからμsへの変換を行いますloop()。そうすれば、はるかに高速になるはずです。

コードを書いているわけではありません。Arduino のライブラリを開いてその動作を確認し、それを自分で複製するだけでよいからです。実際の例、ATmega データシート、およびタイマー、割り込み、さらには PWM に関する多くのチュートリアルがあるため、非常に簡単です。

于 2014-03-26T09:50:22.373 に答える