Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
担心Arduino程序中micros()值的漂移_Arduino_Interrupt_Isr - Fatal编程技术网

担心Arduino程序中micros()值的漂移

担心Arduino程序中micros()值的漂移,arduino,interrupt,isr,Arduino,Interrupt,Isr,我有一个利用伺服库和外部中断程序的程序。据我所知,伺服库使用定时器1中断向伺服发送脉冲以保持位置。我想知道这对micros()计数有什么影响,因为它在中断期间不会增加 我的代码中的外部中断程序是针对转速表的。它使用micros()确定脉冲之间的时间。我担心伺服库会导致毫秒()和微秒()计数器漂移,使速度不准确。转速表可能需要感应10000转/分的转速,约167赫兹。 最后,我将使用伺服和转速表实现PID控制 volatile unsigned long period; unsigned long

我有一个利用伺服库和外部中断程序的程序。据我所知,伺服库使用定时器1中断向伺服发送脉冲以保持位置。我想知道这对micros()计数有什么影响,因为它在中断期间不会增加

我的代码中的外部中断程序是针对转速表的。它使用micros()确定脉冲之间的时间。我担心伺服库会导致毫秒()和微秒()计数器漂移,使速度不准确。转速表可能需要感应10000转/分的转速,约167赫兹。 最后,我将使用伺服和转速表实现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();
}
即使是
tachometer()
和更新
millis()
的函数也会从中断中调用,因此即使是它也会“破坏”您的代码

这会毁了你的演讲多少?不多。Arduino 2009使用16MHz的晶体,在一天中有很多秒的漂移。Arduino Uno使用的是精度较低的振荡器,它的漂移会大得多

因此,除非您在中断例程中进行大量计算,否则一切正常。还请记住,一个micros()调用需要花费4µs(事实上,您会看到它以4乘4的速度增长……或者这是因为计时器每秒溢出0?请查看计时器预分频器;如果它不破坏伺服库,您可以更改它。它将破坏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(只需少调用一个函数,而且函数调用相对昂贵,因为您必须使用堆栈和寄存器)

另外,不要使用micros(),它可以做很多事情(读取计时器0的实际计数,并将计数计算到µs,这是一个函数调用);只需直接读取计时器寄存器,并用该值进行差分,然后将计数转换为µs到
loop()
。那样的话,速度应该快得多

我不是在写代码,因为你只需要打开Arduino的库,看看他们做了什么,然后自己复制它。这是很容易的,因为你有一个工作的例子,一个ATmega数据表和大量的教程定时器,中断,甚至PWM