Помогите новичку! Запутался

Тема в разделе "Arduino & Shields", создана пользователем klark, 1 мар 2013.

  1. klark

    klark Нуб

    Всем доброго времени суток!
    В общем ситуация следующая:
    есть: 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);      
     
    }
     
  2. Megakoteyka

    Megakoteyka Оракул Модератор

    Зачем своя реализация debounce, да еще и дважды (причем вторая функция не используется), когда есть библиотека?
    В сетапе дважды инициализируется один и тот же пин - очепятка.
     
  3. klark

    klark Нуб

    буду безмерно благодарен если вы мне поподробнее укажете, где дважды пин идеализируется, реализация debounce не своя, я ее взял из ролика Джерими Блюма урок 2, скажу честно, до конца ее не понял , только примерно, и следуя логике того что это реализация для одной пары, кнопка- выход, ее повторил дважды (повторюсь я только только начал интересоваться программированием и пока не до конца понял правила создания программ) немоглибы вы показать как по правельному должен выглядить мой скетч.
     
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Код (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;
      }
    }
     
  5. klark

    klark Нуб

    собственно спасибо за совет про библиотеку, вроде разобрался, работает.
    сделал так:
    Код (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 или есть какието другие команды посылающие подобный сигнал
     
  6. klark

    klark Нуб

    спасибо за ответ пока писал пост вы ответили :)
     
  7. Megakoteyka

    Megakoteyka Оракул Модератор

    В коде, который я выложил выше, задефайнена константа 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;
      }
    }
     
  8. Megakoteyka

    Megakoteyka Оракул Модератор

    Не за что)
    Правильно делаете, что пишете комментарии. Советую еще посмотреть, как в моем коде названы переменные - такой способ значительно упрощает чтение длинных исходников. Не обязательно именно так, стилей разных много, но нужно выбрать один и придерживаться его.
    А в целом очень неплохое начало, так держать!
     
  9. klark

    klark Нуб

    очень жаль но ваш скетч не работает
     
  10. Megakoteyka

    Megakoteyka Оракул Модератор

    Я Вам показал, как надо делать, дальше отлаживайте. У меня мотора нет, проверять не на чем.
    Сделайте отладочный вывод, посмотрите, как меняются переменные при нажатии кнопок и верчении потенциометра.
     
  11. klark

    klark Нуб

    спасибо за уделенное время, буду разбираться. а как реализовать отладочный вывод?
     
  12. Megakoteyka

    Megakoteyka Оракул Модератор

    Вот так:
    Код (Text):
    int a = 5;
    Serial.print("a = ");
    Serial.print(a, DEC);
    Попробуйте сделать вывод из обработчиков кнопок и из ветки, которая импульсы формирует. Выводите состояние переменных и текущее время, например - поймете, в каком месте алгоритм не не работает.