Внешнее прерывание Arduino недостаточно быстро

Я пытался измерить время, в течение которого линия на Arduino находится на высоком уровне. Он становится высоким, затем остается высоким в течение нескольких миллисекунд. Затем он становится низким на 1 мкс, а затем возвращается к высокому уровню. Мой код, похоже, не распознает линию, которая становится низкой. 1us слишком быстро для прерывания? Как я могу замедлить его?

Спасибо

EDIT Я думаю использовать RC-фильтр в сочетании с диодом, чтобы замедлить время нарастания, достаточное для того, чтобы Arduino смог распознать изменение, но только тогда, когда изменение происходит от принимающей линии. Это жизнеспособно? Или можно таким же образом использовать микросхему расширителя импульсов с диодом?

#define ESC 2 //the digital pin the esc signal line is attached to

int throttlePos = 0;

volatile unsigned long timer_start;
volatile int last_interrupt_time;
volatile int pulse_time;

void setup() {
 // put your setup code here, to run once:
 pinMode(ESC, OUTPUT); //originally set the ESC's line to output to keep line high ready for throttle armature
 digitalWrite(ESC, HIGH); //keep the pulse high due to inverted throttle pulse
 Serial.begin(115200); //opens the serial port for use when testing
 timer_start = 0; 
   attachInterrupt(digitalPinToInterrupt(ESC), calcSignal, CHANGE);
 for(throttlePos = 0; throttlePos <= 1000; throttlePos += 1) //these for loops arm the ESC by emulating an inverted PWM pulse, process takes two seconds
 {
   digitalWrite(ESC, LOW);
   delayMicroseconds(1500);
   digitalWrite(ESC, HIGH);
   delayMicroseconds(100);
 }
 for(throttlePos = 1000; throttlePos <= 2000; throttlePos += 1)
 {
   digitalWrite(ESC, LOW);
   delayMicroseconds(1000);
   digitalWrite(ESC, HIGH);
   delayMicroseconds(100);
 }
}

void loop() {
 digitalWrite(ESC, LOW);
 delayMicroseconds(1200);
 digitalWrite(ESC, HIGH);
 delayMicroseconds(100);
 delay(19);
 Serial.println(pulse_time);
}
void calcSignal() 
{
   //record the interrupt time so that we can tell if the receiver has a signal from the transmitter 
   last_interrupt_time = micros(); 
   //if the pin has gone HIGH, record the microseconds since the Arduino started up 
   if(digitalRead(ESC) == HIGH) 
   { 
       timer_start = micros();
   } 
   //otherwise, the pin has gone LOW 
   else
   { 
       //only worry about this if the timer has actually started
       if(timer_start != 0)
       { 
           //record the pulse time
           pulse_time = ((volatile int)micros() - timer_start);
           //restart the timer
           timer_start = 0;
       }
   } 
}

осциллограф


person Peter    schedule 15.02.2016    source источник


Ответы (1)


1/1 мкс это 1МГц. Учитывая, что ваша Arduino выполняет инструкции на частоте 16 МГц (в лучшем случае некоторые инструкции занимают больше времени), ваш обработчик прерываний может легко что-то пропустить. Однако прерывание все равно должно выполняться, даже если условие прерывания устранено до завершения прерывания.

Используете ли вы библиотеки Arduino для прерываний или настраиваете прерывания смены контактов непосредственно на уровне регистров?

Вы убедились, что импульс в Arduino электрически исправен? Не зная больше о вашей схеме, трудно предложить исправление.

person uint128_t    schedule 15.02.2016
comment
Я добавил фотографию к своему ответу в редактировании. Я посылаю инвертированный сигнал PWM. Тик возвращается приемником, замыкающим линию на землю на 1 мкс. - person Peter; 16.02.2016
comment
Хм. Похоже, что Arduino должен захватить этот импульс. Всегда ли он терпит неудачу или только иногда? - person uint128_t; 16.02.2016
comment
Выпадает 11 из 12 импульсов ШИМ. Это позволяет провести калибровку. Я добавил свой код в редактирование, чтобы увидеть, найдете ли вы какие-либо ошибки. Прямо сейчас он просто распечатывает время, когда сигнал был высоким между импульсами газа. - person Peter; 16.02.2016