Всем доброго времени суток! В общем ситуация следующая: есть: 1)шаговый двигатель, 2)контроллер шагового двигателя, Arduino UNO. задача: управлять шаговиком с двух кнопок (вкл\выкл, направление). Контроллер управляется по трем каналам (enable,dir,step). пытаюсь написать скетч , чтоб при нажатии кнопки 1 на pin 7 был HIGH, после повторного нажатия его состояние было LOW. при начати кнопки 2 пин 10 был HIGH, при повторном нажатии был LOW. а на пин 11 допустим постоянно посылалось HIGH/LOW c задержкой допустим 1 милисикунда. начитавшись всего и насмотревшись видео от Блюма, на основе его скетча с светодиодами набрасал свой но он не работет, точней работает но не полностью когда нажимаю кнопку вкл.вык все работает, а вот кнопка управления направлением не работает. чую что ощибка какаято глупая, но найти не могу. не судите строго, к програмированию , да и вообще к электронике притронулся только 2 недели назад (работа заставила). собстенно вот и мой скетч: Код (Text): #define buttonOn 2 // кнопка включения двигателя #define onPin 10 // выход сигнала включения #define buttonDir 13 // кнопка выбора направления #define dirPin 7 // выход выбора направления #define stepPin 11 // выход управления шагом boolean lastButton = LOW; boolean currentButton = LOW; boolean lastButton2 = LOW; boolean currentButton2 = LOW; boolean motorOn = false; // переменная состояния выхода управления сигналом включения boolean dirMotor = false; // пременная состояния выхода управления сигналом включения void setup() { pinMode(buttonOn, INPUT); pinMode(onPin, OUTPUT); pinMode(buttonDir, INPUT); pinMode(dirPin, OUTPUT); pinMode(stepPin, OUTPUT); digitalWrite(stepPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW digitalWrite(dirPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW digitalWrite(dirPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW } boolean debounce(boolean last) { boolean current = digitalRead(buttonOn); if (last != current) { delay(5); current = digitalRead(buttonOn); } return current; } boolean debounce2(boolean last) { boolean current = digitalRead(buttonDir); if (last != current) { delay(5); current = digitalRead(buttonDir); } return current; } void loop() { currentButton = debounce(lastButton); if (lastButton == LOW && currentButton == HIGH) { motorOn = !motorOn; } lastButton = currentButton; digitalWrite(onPin, motorOn); currentButton2 = debounce(lastButton2); if (lastButton2 == LOW && currentButton2 == HIGH) { dirMotor = !dirMotor; } lastButton2 = currentButton2; digitalWrite(dirPin, dirMotor); digitalWrite(11, HIGH); delay(1); digitalWrite(11, LOW); delay(1); }
Зачем своя реализация debounce, да еще и дважды (причем вторая функция не используется), когда есть библиотека? В сетапе дважды инициализируется один и тот же пин - очепятка.
буду безмерно благодарен если вы мне поподробнее укажете, где дважды пин идеализируется, реализация debounce не своя, я ее взял из ролика Джерими Блюма урок 2, скажу честно, до конца ее не понял , только примерно, и следуя логике того что это реализация для одной пары, кнопка- выход, ее повторил дважды (повторюсь я только только начал интересоваться программированием и пока не до конца понял правила создания программ) немоглибы вы показать как по правельному должен выглядить мой скетч.
Код (Text): #include <Bounce.h> #define BOUNCE_TIME 40 // время подавления дребезга в мс #define STEP_TIME 1 // время на шаг двигателя #define PRESSED_BTN_STATE HIGH// состояние нажатой кнопки #define PIN_BTN_ON 2 // кнопка включения двигателя #define PIN_ON 10 // выход сигнала включения #define PIN_BTN_DIR 13 // кнопка выбора направления #define PIN_DIR 7 // выход выбора направления #define PIN_STEP 11 // выход управления шагом // эти объекты отловят нажатие кнопок, не используя функцию delay() Bounce _btnOn = Bounce(PIN_BTN_ON, BOUNCE_TIME); Bounce _btnDir = Bounce(PIN_BTN_DIR, BOUNCE_TIME); boolean _onState = LOW; // переменная состояния выхода управления сигналом включения boolean _dirState = LOW; // пременная состояния выхода управления сигналом направления boolean _stepState = LOW; // переменная состояния сигнала, формирующего шаги unsigned long _prevTime = 0; // переменная для хранения момента времени, когда произошел очередной шаг // обработчик кнопки "on/off" void buttonOnHandler() { _onState = !_onState; digitalWrite(PIN_ON, _onState); } // обработчик кнопки "dir" void buttonDirHandler() { _dirState = !_dirState; digitalWrite(PIN_DIR, _dirState); } void setup() { pinMode(PIN_BTN_ON, INPUT); // ножки кнопок на ввод pinMode(PIN_BTN_DIR, INPUT); // ножки кнопок на ввод pinMode(PIN_ON, OUTPUT); // ножки управления мотором на вывод pinMode(PIN_DIR, OUTPUT); // ножки управления мотором на вывод pinMode(PIN_STEP, OUTPUT); // ножки управления мотором на вывод digitalWrite(PIN_ON, _onState); // с начала программы все выходы в исходное состояние digitalWrite(PIN_DIR, _dirState); // с начала программы все выходы в исходное состояние digitalWrite(PIN_STEP, _stepState);// с начала программы все выходы в исходное состояние } void loop() { // ловим нажатие кнопки и вызываем обработчик if(_btnOn.update() && _btnOn.read() == PRESSED_BTN_STATE) buttonOnHandler(); // ловим нажатие кнопки и вызываем обработчик if(_btnDir.update() && _btnDir.read() == PRESSED_BTN_STATE) buttonDirHandler(); // берем текущее время unsigned long currentTime = millis(); if(currentTime - _prevTime >= STEP_TIME) { digitalWrite(11, _stepState); _stepState != _stepState; _prevTime = currentTime; } }
собственно спасибо за совет про библиотеку, вроде разобрался, работает. сделал так: Код (Text): #include <Bounce.h> #define buttonOn 2 // кнопка включения двигателя #define onPin 10 // выход сигнала включения #define buttonDir 13 // кнопка выбора направления #define dirPin 7 // выход выбора направления #define stepPin 11 // выход управления шагом int onValue; int dirValue; Bounce bouncer = Bounce( buttonOn, 5 ); Bounce bouncer2 = Bounce( buttonDir, 5 ); void setup() { pinMode(buttonOn, INPUT); pinMode(onPin, OUTPUT); pinMode(buttonDir, INPUT); pinMode(dirPin, OUTPUT); pinMode(stepPin, OUTPUT); digitalWrite(stepPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW digitalWrite(dirPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW digitalWrite(dirPin, LOW); //чтобы не запутатся с начала программы все выходы на LOW } void loop() { if ( bouncer.update() ) { if ( bouncer.read() == HIGH) { if ( onValue == LOW ) { onValue = HIGH; } else { onValue = LOW; } digitalWrite(onPin,onValue); } } if ( bouncer2.update() ) { if ( bouncer2.read() == HIGH) { if ( dirValue == LOW ) { dirValue = HIGH; } else { dirValue = LOW; } digitalWrite(dirPin,dirValue); } } digitalWrite(11, HIGH); delay(1); digitalWrite(11, LOW); delay(1); } вопрос: я правильно оформил тело программы? теперь осталась одна задача, управление скоростью двигателя. тоесть мне нужно управлять частотой посылаемого сигнада на пин stepPin. собственно посоветуйте как лучше это реализовать , поставить патанциометр и в зависимости от значения на входе менять значения задержки между посылом 0 и 1 или есть какието другие команды посылающие подобный сигнал
В коде, который я выложил выше, задефайнена константа STEP_TIME, равная 1 мс. Т.е. частота импульсов тогда получится 2 мс. Можно этот параметр вынести в переменную и просто менять ее значение, считывая показания потенциометра. Вот так: Код (Text): #include <Bounce.h> #define BOUNCE_TIME 40 // время подавления дребезга в мс #define PRESSED_BTN_STATE HIGH// состояние нажатой кнопки #define PIN_BTN_ON 2 // кнопка включения двигателя #define PIN_ON 10 // выход сигнала включения #define PIN_BTN_DIR 13 // кнопка выбора направления #define PIN_DIR 7 // выход выбора направления #define PIN_STEP 11 // выход управления шагом #define PIN_POT A0 // вход потенциометра // эти объекты отловят нажатие кнопок, не используя функцию delay() Bounce _btnOn = Bounce(PIN_BTN_ON, BOUNCE_TIME); Bounce _btnDir = Bounce(PIN_BTN_DIR, BOUNCE_TIME); boolean _onState = LOW; // переменная состояния выхода управления сигналом включения boolean _dirState = LOW; // пременная состояния выхода управления сигналом направления boolean _stepState = LOW; // переменная состояния сигнала, формирующего шаги unsigned long _prevTime = 0; // переменная для хранения момента времени, когда произошел очередной шаг int _stepTime = 1; // время полушага в мс // обработчик кнопки "on/off" void buttonOnHandler() { _onState = !_onState; digitalWrite(PIN_ON, _onState); } // обработчик кнопки "dir" void buttonDirHandler() { _dirState = !_dirState; digitalWrite(PIN_DIR, _dirState); } void setup() { pinMode(PIN_BTN_ON, INPUT); // ножки кнопок на ввод pinMode(PIN_BTN_DIR, INPUT); // ножки кнопок на ввод pinMode(PIN_POT, INPUT); // ножка потенциометра на вход pinMode(PIN_ON, OUTPUT); // ножки управления мотором на вывод pinMode(PIN_DIR, OUTPUT); // ножки управления мотором на вывод pinMode(PIN_STEP, OUTPUT); // ножки управления мотором на вывод digitalWrite(PIN_ON, _onState); // с начала программы все выходы в исходное состояние digitalWrite(PIN_DIR, _dirState); // с начала программы все выходы в исходное состояние digitalWrite(PIN_STEP, _stepState);// с начала программы все выходы в исходное состояние } void loop() { // ловим нажатие кнопки и вызываем обработчик if(_btnOn.update() && _btnOn.read() == PRESSED_BTN_STATE) buttonOnHandler(); // ловим нажатие кнопки и вызываем обработчик if(_btnDir.update() && _btnDir.read() == PRESSED_BTN_STATE) buttonDirHandler(); // читаем значение с потенциометра int potValue = analogRead(PIN_POT); // длительность полушага будет меняться от 0 до 255 (делим 0..1023 на 4) _stepTime = potValue >> 4; // берем текущее время unsigned long currentTime = millis(); if(currentTime - _prevTime >= _stepTime) { digitalWrite(11, _stepState); _stepState != _stepState; _prevTime = currentTime; } }
Не за что) Правильно делаете, что пишете комментарии. Советую еще посмотреть, как в моем коде названы переменные - такой способ значительно упрощает чтение длинных исходников. Не обязательно именно так, стилей разных много, но нужно выбрать один и придерживаться его. А в целом очень неплохое начало, так держать!
Я Вам показал, как надо делать, дальше отлаживайте. У меня мотора нет, проверять не на чем. Сделайте отладочный вывод, посмотрите, как меняются переменные при нажатии кнопок и верчении потенциометра.
Вот так: Код (Text): int a = 5; Serial.print("a = "); Serial.print(a, DEC); Попробуйте сделать вывод из обработчиков кнопок и из ветки, которая импульсы формирует. Выводите состояние переменных и текущее время, например - поймете, в каком месте алгоритм не не работает.