Простое кодирование устранения дребезга
Я полный новичок в программировании на Arduino, хотя уже несколько лет использую его, копируя чужой код. Я понимаю лишь малую часть схемы скетча и был бы очень благодарен за помощь в решении, на мой взгляд, простой задачи.
У меня есть скетч для управления скоростью и направлением шагового двигателя:-
/*
Stepper Motor Test
stepper-test01.ino
Uses MA860H or similar Stepper Driver Unit
Has speed control & reverse switch
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Определить контакты
int reverseSwitch = 2; // Нажмите кнопку для реверса
int driverPUL = 7; // PUL-пин
int driverDIR = 6; // DIR-pin
int spd = A0; // Потенциометр
// Переменные
int pd = 500; // Период задержки импульса
boolean setdir = LOW; // Установить направление
// Обработчик прерываний
void revmotor (){
setdir = !setdir;
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
}
void loop() {
pd = map((analogRead(spd)),0,1023,1000,150);
digitalWrite(driverDIR,setdir);
digitalWrite(driverPUL,HIGH);
digitalWrite(LED_BUILTIN, HIGH);
delayMicroseconds(pd);
digitalWrite(driverPUL,LOW);
delayMicroseconds(pd);
}
Это прекрасно работает с моим драйвером шагового двигателя и шаговым двигателем с хорошим управлением скоростью. Однако автор предупреждал, что дребезг может быть проблемой, и это действительно так. Я понимаю принцип дребезга и изучил несколько скетчей с этой функцией, а также понимаю метод его уменьшения с помощью задержки в несколько миллисекунд. Я считаю, что следующий код максимально прост, но я понятия не имею, как это реализовать в скетче выше.
bool debounce() {
static uint16_t state = 0;
state = (state<<1) | digitalRead(btn) | 0xfe00;
return (state == 0xff00);
}
(Кажется, автор разделил код на две части (я так думаю)
#define btn 2 //предполагая, что мы используем D2 на Arduino
void setup() {
pinMode(btn, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (debounce()) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
Может ли кто-нибудь взглянуть на эти скетчи и подсказать мне: а) совместимы ли они и б) как включить код устранения дребезга в рабочий скетч?
Заранее спасибо от настоящего программиста (шотландское выражение!)
@Solmod, 👍2
Обсуждение2 ответа
Лучший ответ:
Вы можете попробовать заменить функцию revmotor() этим кодом. Вместо использования отдельного кода устранения дребезга, который вы нашли. Принцип работы заключается в блокировке нажатий переключателя в течение 100 мс после последнего нажатия.
void revmotor (){
static uint32_t lastSwitchAtMs = 0 ;
if ( millis() - lastSwitchAtMs > 100UL ) { // дребезг 100 мс
setdir = !setdir;
}
lastSwitchAtMs = millis() ;
}
Обратите внимание, что переменная setdir на самом деле должна быть объявлена так: volatile boolean setdir = LOW; // Установить направление
РЕДАКТИРОВАТЬ:
Кстати, нашёл статью, которой вы следовали, здесь: https://dronebotworkshop.com/big-stepper-motors/, которая включает код и принципиальную схему.
Всё работает отлично. Спасибо. Я увеличил задержку дребезга до 400 миллисекунд, что лучше всего подходит для моего коммутатора. Ещё раз спасибо., @Solmod
@Solmod 400 мс? Должно быть, это какой-то старый, но, в любом случае, я рад, что у вас есть что-то, что можно использовать. Приведённый мной код — особый случай, поскольку не так уж часто используется процедура обработки прерываний для чтения состояния переключателя/кнопки (перебор или кувалда для раскалывания ореха), но бывают случаи, когда это допустимо, например, когда цикл содержит блокирующий код., @6v6gt
Пока что этот "переключатель" представляет собой оголённый конец двух проводов, пока я не смогу всё настроить. Теперь, когда всё работает, я буду собирать физическую схему в блоке управления с качественным кнопочным переключателем — возможно, после этого мне удастся сократить этот период ;-). В любом случае, спасибо за помощь — она мне очень помогла., @Solmod
Я полагаю, что функция debounce() и пример были взяты из моей записи в блоге Простейшее решение проблемы дребезга кнопок. На самом деле, я не был первым, кто её написал, я адаптировал её из книги Джека Ганссалла Руководство по дребезгу - Часть 2, которая была впервые опубликована ещё в 2004 году.
В вашем случае все, что вам нужно сделать, — это при возникновении события revmotor() вызвать функцию debounce и изменить состояние setdir только в том случае, если debounce возвращает true.
int reverseSwitch = 2; // Нажмите кнопку для реверса
void revmotor (){
if (debounce())
setdir = !setdir;
}
bool debounce() {
static uint16_t state = 0;
state = (state<<1) | digitalRead(reverseSwitch) | 0xfe00;
return (state == 0xff00);
}
void setup() {
// здесь ваш код настройки пин-кода
pinMode(reverseSwitch, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
}
Должен сказать, что я не тестировал этот конкретный код перед публикацией этого ответа, но я использовал его в похожих случаях в прошлом много раз.
Спасибо за участие — я это очень ценю. Я постарался следовать вашим рекомендациям и соответствующим образом изменил свой код, однако получаю сообщение об ошибке «debounced» (не объявлено в этой области). Не уверен, что правильно понял, но вижу, что оператор if (debounced) предшествует оператору Bool debounce. Влияет ли это на программу?, @Solmod
Теперь мой код выглядит так: void revmotor (){ если (debounced()) setdir = !setdir; } bool debounce() { статическое состояние uint16_t = 0; состояние = (состояние <<1) | digitalRead(reverseSwitch) | 0xfe00; возврат (состояние == 0xff00); } void setup() { pinMode (driverPUL, OUTPUT); pinMode (driverDIR, OUTPUT); attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING); }, @Solmod
ОК — проблема решена — небольшая орфографическая ошибка debounce / debounced. Код теперь работает, хотя debounce всё ещё немного хаотичен. Продолжу экспериментировать. Спасибо., @Solmod
Вы можете изменить 0xfe00 на 0x8000 и 0xff00 на 0xc000, чтобы увеличить период устранения дребезга., @hcheung
Ещё раз спасибо за ваш вклад. Чтобы я понимал, что значат эти изменения, не могли бы вы объяснить, что они означают?, @Solmod
0xfe00 — это B1111,1110,0000,0000, поскольку кнопка колебалась между 1 и 0, пока наконец не достигла стабильного 0. Функция debounce(), по сути, ищет серию последовательных нулей после последнего колебания. 0xfe00 ищет серию последовательных 8-битных нулей. 0x8000 ищет более длинную последовательность 14-битных нулей (0x8000 — это B1000,0000,0000,0000), то есть после последнего колебания (т.е. 1). Подробнее читайте в моём блоге или в статье Джека Гансла., @hcheung
Если этого все еще недостаточно для обработки дребезга, вы можете добавить небольшую задержку(1) в debounce() для повышения надежности., @hcheung
- Устранение дребезга кнопки с помощью прерывания
- Хорошая кнопка debouncing/Библиотека StateChange
- минимальный код для устранения дребезга нескольких кнопок
- Управление несколькими светодиодами с помощью нескольких кнопок
- Будет ли простой RC-фильтр работать с механическим поворотным энкодером или понадобится триггер Шмитта?
- Прерывание при нажатии кнопки + устранение дребезга
- Кодировщик + Библиотека Bounce2
- Прерывание срабатывает дважды при установке на ПАДЕНИЕ
какова цель
digitalWrite(LED_BUILTIN, HIGH);в первом коде? ... нет смысла выполнять его повторно, @jsotola«Кажется, автор разделил код на две части» ... автор использовал функцию ... она группирует код в разделы, которыми легче управлять., @jsotola
Существует несколько простых в использовании библиотек для устранения дребезга. Я предлагаю вам просто использовать одну из них вместо того, чтобы программировать логику устранения дребезга самостоятельно., @Edgar Bonet
Прошу прощения, я пытался использовать цифровую запись для внутреннего светодиода, чтобы проверить, смогу ли я определить момент перехода с высокого уровня на низкий. Спасибо за указание на то, что автор использовал функцию, но на моём уровне знаний это всё ещё ничего мне не говорит. Имейте в виду, я полный новичок в программировании. Поэтому я и обращаюсь к вам за помощью. Дайте мне кусок алюминия, и я изготовлю самое сложное устройство, какое только можно, но покажите мне скетч для Arduino, и мой мозг не сможет сообразить., @Solmod
Эдгар Бонет: Я знаю, что существуют простые библиотеки для устранения дребезга, но я даже не знаю, как добавить библиотеку в мой простой код, который работает. Кроме того, я не могу отличить «простую» библиотеку от сложной, поэтому мне и нужна помощь., @Solmod
Я пытался использовать цифровую запись для внутреннего светодиода, чтобы посмотреть, смогу ли я определить момент перехода с Hi на Lo... этого нельзя добиться, слепо включая светодиод через несколько микросекунд после запуска программы и никогда его не выключая... установите для него значениеsetdirвместо значенияHIGH, @jsotola