Аппаратное прерывание срабатывает случайным образом
Итак, есть довольно общая часть моего проекта, которая включает в себя запуск ISR, который переворачивает логическое значение. Я настроил программную часть следующим образом:
void setup() {
attachInterrupt(digitalPinToInterrupt(2), displayConvergence, FALLING);
}
void loop() {
if(flashConvergence) {
//Делаем то, что занимает несколько секунд
delay(3000);
flashConvergence = false;
}
}
void displayConvergence() {
if (!flashConvergence) {
flashConvergence = true;
}
}
Схема выглядит следующим образом:
Но поведение моей схемы меня удивило, так как прерывание контакта срабатывало случайным образом с частотой (примерно здесь) 3 раза в секунду.
Странно, подумал я. Я повозился и обнаружил, что когда 180В повышающего преобразователя не подключены к какой-либо нагрузке, служба прерывания срабатывает, как и ожидалось, т.к. она начинает работать корректно. Поэтому я подумал, что, возможно, проблема в каком-то шуме, создаваемом повышающим преобразователем.
Я изменил схему, добавив конденсатор на переключатель:
Сначала я попробовал 1 мкФ, но это не помогло, как и 10 мкФ. Однако, когда я попробовал 100 мкФ (я думал, что развязывающие конденсаторы обычно имеют емкость от 0,1 мкФ до 1 мкФ, не слишком ли велико значение, которое я использую?), все работает, как и ожидалось, за исключением того, что когда я держу переключатель в замкнутом положении положении в течение длительного времени, затем дайте ему вернуться в открытое положение, служба прерывания может быть запущена случайным образом на короткий период сразу после того, как я отпущу переключатель.
Правильно ли мое первоначальное предположение, что ISR срабатывает случайным образом из-за электромагнитных помех от повышающего преобразователя? Возможно, есть другие причины, которые я не рассматриваю? Есть ли способ заставить эту работу работать на 100% (например, решить проблему сразу после того, как переключатель будет переведен в открытое положение)?
Спасибо за помощь!
@Alex H, 👍0
Обсуждение3 ответа
Лучший ответ:
Мне стало известно, что я никогда не писал об этом, но на самом деле я смог решить эту проблему, экранировав провод, идущий от коммутатора к Arduino. Провод переключателя был длиной от 2 до 3 дюймов, и я обернул его алюминиевой фольгой, которая защитила сигнал от того, что, как я подозревал, было вызвано электромагнитными помехами, вызванными переключающими преобразователями.
Альтернативный подход — отключить обработчик прерывания и использовать внутренний подтягивающий резистор вместо внешнего резистора (и конденсатора).
const int BUTTON = 2;
volatile bool flashConverage = false;
void setup()
{
setmode(BUTTON, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON), displayConvergence, FALLING);
}
void loop()
{
if (!flashConvergence) return;
// Делаем то, что занимает несколько секунд
delay(3000);
flashConvergence = false;
attachInterrupt(digitalPinToInterrupt(BUTTON), displayConvergence, FALLING);
}
void displayConvergence()
{
detachInterrupt(digitalPinToInterrupt(BUTTON));
flashConvergence = true;
}
Обработка ("вещи, которые занимают несколько секунд") устранят дребезг кнопки (или, по крайней мере, проигнорируют ее :).
Ура!
Проблема не (только) в дребезге переключателя. Это ложные срабатывания. Этот код не поможет с этим., @Gerben
Итак, мы предоставили несколько решений для тестирования. Я согласен, что шум от преобразователя может быть проблемой. Также может помочь перемещение конденсатора на 100 мкФ для фильтрации шума при питании (5 В)., @Mikael Patel
Если у вас нет большой емкости (100 мкФ или около того) на блоке питания логики, у вас будут проблемы с шумом. Вы также должны использовать меньше (1 мкФ и 0,1 мкФ), чтобы обеспечить обход высокочастотного шума в системе питания.
Гленн
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Серийное прерывание
- Влияет ли `millis()` на длинные ISR?
- Как прервать функцию цикла и перезапустить ее?
- Какой правильный способ запроса устройства I2C из процедуры обслуживания прерывания?
- Чтение квадратурного энкодера в реальном времени с полным разрешением только с одним прерыванием на ATmega328
- Как выйти из прерывания таймера (ISR(TIMER1_COMPA_vect))
- Правильное использование SPI с ISR
Вы можете попробовать; опускание подтягивающего резистора. Отодвиньте кнопку от повышающего преобразователя и его проводов. Переместите подтяжку ближе к контакту 2. Используйте систему подтягивания (поменяв местами R1 и SW1) вместо подтягивания. PS конденсатор здесь используется не для развязки, а как фильтр нижних частот., @Gerben
Почему вытягивающая система имеет большую помехозащищенность, чем вытягивающая?, @Alex H
Я не уверен, что это так, но, возможно, стоит попробовать., @Gerben
Преобразователи Buck-Boost довольно шумные. Если прерывание запускается случайным образом, даже если вы даже не касаетесь переключателя, это означает, что какой-то шум определенно вызывает проблему. Если у вас есть осциллограф, вы можете подключить его к D2, чтобы увидеть, что происходит. Попробуйте добавить 100 мкФ и 0,1 мкФ колпачок на 5 В, прежде чем он подключится к схеме Arduino., @Fahad
Я думаю, что если вы хотите только перевернуть значение логического значения, попробуйте использовать это только в ISR «flashConvergence = !flashConvergence;» это сэкономит массу места и будет менее сложным., @Shams M.Monem