Простое кодирование устранения дребезга

Я полный новичок в программировании на 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));
  }
}

Может ли кто-нибудь взглянуть на эти скетчи и подсказать мне: а) совместимы ли они и б) как включить код устранения дребезга в рабочий скетч?

Заранее спасибо от настоящего программиста (шотландское выражение!)

, 👍2

Обсуждение

какова цель digitalWrite(LED_BUILTIN, HIGH); в первом коде? ... нет смысла выполнять его повторно, @jsotola

«Кажется, автор разделил код на две части» ... автор использовал функцию ... она группирует код в разделы, которыми легче управлять., @jsotola

Существует несколько простых в использовании библиотек для устранения дребезга. Я предлагаю вам просто использовать одну из них вместо того, чтобы программировать логику устранения дребезга самостоятельно., @Edgar Bonet

Прошу прощения, я пытался использовать цифровую запись для внутреннего светодиода, чтобы проверить, смогу ли я определить момент перехода с высокого уровня на низкий. Спасибо за указание на то, что автор использовал функцию, но на моём уровне знаний это всё ещё ничего мне не говорит. Имейте в виду, я полный новичок в программировании. Поэтому я и обращаюсь к вам за помощью. Дайте мне кусок алюминия, и я изготовлю самое сложное устройство, какое только можно, но покажите мне скетч для Arduino, и мой мозг не сможет сообразить., @Solmod

Эдгар Бонет: Я знаю, что существуют простые библиотеки для устранения дребезга, но я даже не знаю, как добавить библиотеку в мой простой код, который работает. Кроме того, я не могу отличить «простую» библиотеку от сложной, поэтому мне и нужна помощь., @Solmod

Я пытался использовать цифровую запись для внутреннего светодиода, чтобы посмотреть, смогу ли я определить момент перехода с Hi на Lo ... этого нельзя добиться, слепо включая светодиод через несколько микросекунд после запуска программы и никогда его не выключая... установите для него значение setdir вместо значения HIGH, @jsotola


2 ответа


Лучший ответ:

0

Вы можете попробовать заменить функцию 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


0

Я полагаю, что функция 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