Концевики и шаговый двигатель

Тема в разделе "Arduino & Shields", создана пользователем Airo, 4 июн 2023.

  1. Airo

    Airo Нерд

    Код (C++):
    const int dirPin = 3;
    const int stepPin = 2;
    #define ENABLE_PIN 4
    const int stepsPerRevolution = 2000;

    unsigned long myTimer6, myTimer7;
    unsigned long  myTimer1,myTimer2, myTimer3, myTimer4, myTimer5;
    #define CLK 5       // пин энкодера
    #define DT 6      // пин энкодера
    #define SW 7
    #include <GyverEncoder.h>
    Encoder enc (CLK, DT, SW);
    int val = 0;
    void setup()
    {
      pinMode(ENABLE_PIN , OUTPUT);

      pinMode(8, INPUT_PULLUP);//ставить вдали от двигателя
      pinMode(9, INPUT_PULLUP);//ставить возле двигателя


      pinMode(stepPin, OUTPUT);
      pinMode(dirPin, OUTPUT);

      Serial.begin (9600);
      enc.setType(TYPE2);
    }
    void loop()
    {

    if (millis() - myTimer3 > 0 && millis() - myTimer3 < 300)
      {digitalWrite(ENABLE_PIN , LOW);
         if(digitalRead(8)){
           digitalWrite(ENABLE_PIN , HIGH);
         }
           else{
        digitalWrite(dirPin, LOW);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(390+val);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(390+val);
           }
      }
    if (millis() - myTimer4 > 350 && millis() - myTimer4 < 650)
      {
        digitalWrite(ENABLE_PIN , LOW);
        if(digitalRead(9)){
          digitalWrite(ENABLE_PIN , HIGH);
         }
           else{
        digitalWrite(dirPin, HIGH);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(390+val);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(390+val);
      }
      }
    if (millis() - myTimer5 > 700){
       myTimer3= millis();
       myTimer4= millis();
       myTimer5= millis();
    }

    enc.tick();
      if (enc.isTurn())
      {
      if (enc.isRight ()) val++;          //крутим увеличиваем на 1
      if (enc.isLeft ()) val--;           //крутим уменьшаем на 1
      if (enc.isRightH ()) val += 5;      //удерживаем кнопку и крутим увеличиваем на 5
      if (enc.isLeftH ()) val -= 5;       //удерживаем кнопку и крутим уменьшаем на 5
      Serial.println (val);
      }

      if (enc.isClick()) Serial.println ("click");
      if (enc.isHolded()) Serial.println ("holded");
      if (enc.isDouble()) Serial.println ("double");

      if (enc.isFastR ()) val += 10;       //быстро крутишь увеличивается на 10
      if (enc.isFastL ()) val -= 10;       //быстро крутишь уменьшается на 10

    }
    Здравствуйте! Нужно помощь в доработке скетча.
    Создал направляющую по которой двигается коретка. Задача состоит в том что бы двигатель вращался 1, сек в оду и 1 сек в другую сторону (время будет еще меняться). И в случае если коретка достигает концевика менялось направление движения коретки.
    В данный момент при контакте с концевиком двигатель выключается в ожидании следующего цикла.
     
    Последнее редактирование: 4 июн 2023
  2. Airbus

    Airbus Радиохулиган Модератор

  3. Airo

    Airo Нерд

    Извините. Изменил.
     
    Airbus нравится это.
  4. Sergku

    Sergku Нерд

    Кнопки пуллап, подтянуты к +. Нажатие проверяется if (!digitalRead(8))
     
    Airbus нравится это.
  5. Airo

    Airo Нерд

    Если вы имеете ввиду что то вроде этого кода
    Код (C++):
     if(digitalRead(8)) {
        digitalWrite(dirPin, HIGH);

        digitalWrite(stepPin, HIGH);
        delayMicroseconds(390);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(390);
        }
        else{
        digitalWrite(dirPin, LOW);

        digitalWrite(stepPin, HIGH);
        delayMicroseconds(390);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(390);
        }
         
    Уже побывал не работает. Когда задевает концевик коретка на мгновение движится в другую сторону до того момента пока не выйдет с зоны действия оптического концевика, а потом опять движится к нему обратно и по сути происходит баг движится дуда сюда на месте пока не закончится время if(millis()- myTimer3 >0&& millis()- myTimer3 <300).
     
  6. Airbus

    Airbus Радиохулиган Модератор

    У Вас в коде строка if(digitalRead(8)); будет все время TRUE пртому как кнопки подтянуты к питанию. На них всегда единица тобишь HIGH. И блок кода следующий за ним
    {
    digitalWrite(dirPin, HIGH);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(390);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(390);
    }
    Будет выполнятся всегда а блок кода после else-никогда. Попробуйте так
    if(digitalRead(8)==LOW);
    Ну или как Вам уже сказали
     
  7. Sergku

    Sergku Нерд

    кстати, я бы сначала просто моторами покрутил (туды, сюды), вот рыба:

    Код (C++):

    unsigned long
        motorTmr = 0,
        processTmr= 0;
               
    int
        processDelay = 1000, // Общее вращение
        motorDelay = 10; // Для обмоток мотора

    boolean
        currentDirection = false;

    void setup(){
        motorTmr = processTmr = millis();
    }

    void loop(){

        if (millis() - processTmr <= processDelay){
            if(millis() - motorTmr >= motorDelay){
                motorTmr = millis();
                if(currentDirection){
                    // Крутим вправо
                }
                else{
                    // Крутим влево
                }      
            }
         
        } else {
            processTmr = millis();
            currentDirection = !currentDirection;
        }
     
    }
     
  8. Airo

    Airo Нерд

    Я понял что вы имеете в виду, но вы не правы. Все как раз наоборот.
    Код (C++):
    if(digitalRead(8)){
           digitalWrite(dirPin, HIGH);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(390);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(390);
         }
           else{  
        digitalWrite(dirPin, LOW);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(500);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(500);
           }
    На постоянке используется то что в else а есле я сделаю инверсию как предлагали выше
    if(!digitalRead(8)). То в этом случае будет на постоянке использоваться то что под ним, а уже в случае если активируется концевик то будет работать, то что в else. Я так понимаю это потому что используется не обычная кнопка, а оптический датчик и он как раз срабатывает на разрыве.
     
  9. Airo

    Airo Нерд

    С вращением проблем нет. Все работает как я и хотел. Проблема в том что когда концевик активируется и идет движение обратно, но только до тех пор, пока его не отожмут. тогда опять идет движение к нему и по кругу пока не закончится время
    if (millis() - myTimer3 > 0 && millis() - myTimer3 < 3000).
     
  10. Airo

    Airo Нерд

    Может я не достаточно понятно разъясняю конечно. Попробую привести аналогию когда кнопка не нажата работает движение влево. Когда кнопка зажата идет движение вправо. И получается что кнопка нажимается и отжимается КЛАЦ-КЛАЦ-КЛАЦ-КЛАЦ-КЛАЦ-КЛАЦ.
    Использую вот такие концевики.
     

    Вложения:

    • 6341298552.jpg
      6341298552.jpg
      Размер файла:
      178,7 КБ
      Просмотров:
      101
  11. Airo

    Airo Нерд

    Сейчас пытаюсь сделать вот так
    Код (C++):

    const int dirPin = 3;
    const int stepPin = 2;
    #define ENABLE_PIN 4

    unsigned long  myTimer6, myTimer7;
    unsigned long  myTimer1,myTimer2, myTimer3, myTimer4, myTimer5;

    void setup() {
      pinMode(8, INPUT_PULLUP);//ставить вдали от двигателя
      pinMode(9, INPUT_PULLUP);//ставить возле двигателя
      pinMode(stepPin, OUTPUT);
      pinMode(dirPin, OUTPUT);
      Serial.begin (9600);
    }

    void loop() {
      if(digitalRead(8)){
         Serial.println (1);
         myTimer3 = 3100;
         myTimer5 = 3000;

         }

      if(digitalRead(9)){
         myTimer3 = 0;
         myTimer5 = 0;
         myTimer3= millis();
         myTimer4= millis();
         myTimer5= millis();

         }

      if (millis() - myTimer3 < 3000){
       Serial.println (3);
      }

      if (millis() - myTimer3 > 3000){
       Serial.println (4);
      }

      if (millis() - myTimer5 > 6000){
        myTimer5 = 0;
        myTimer3 = 0;
        myTimer3= millis();
        myTimer5= millis();

    }
    }

     
    Что то вроде если if(digitalRead(8) то время становится больше 3000 и тогда начинает работать Serial.println (4); ну и если if(digitalRead(9) то меньше 3000 и работает Serial.println (3);. Но почему то работает только с 9 пином он переводит в Serial.println (3);. А 8 пин почему то тоже переводит к Serial.println (3);. По сути хочу что бы при контакте с концевиком принудительно переходил к другому условию. Если задет 8 пин то что бы вкючался Serial.println (4);, а если 9 то Serial.println (3);
     
  12. Sergku

    Sergku Нерд

    Непонятно, что вы вообще хотите... думаю это поможет определить

    Код (C++):
     
    if(digitalRead(8))
        Serial.println("digitalRead(8) NOT PUSH");
    else
        Serial.println("digitalRead(8) PUSH");
     
  13. ivan_alexoff

    ivan_alexoff Гик

    Флаги используй, кртуиш в одну сторону - ставишь флаг "крутим туды", сработал концевик - поднимаешь флаг " крутим сюды" и т.д туды-сюды-обратно ...
     
  14. Airo

    Airo Нерд

    Да вы почти поняли то что я хочу только с еще одним условием. Попробую пояснить. Есть ость Х по ней движется объект, управляется все шаговым двигателем. Он движется туда-сюда с периодичностью в 3сек (это значение будет еще меняться, но пака для удобства 3 сек на движение в одном направление после чего 3 сек в другое направление). Концевики нужны для того что бы если объект дотронется до концевика он должен сменить направление движения.
    Условие:
    1)Объект движется вправо и не дотрагивается до концевика, заканчивается время (3сек) он разворачивается влево.
    2)Объект движется влево и не дотрагивается до концевика, заканчивается время (3сек) он разворачивается вправо.
    3) Если при движении влево задевается левый концевик даже если время (3сек) не прошло он должен начать движение вправо.
    4) Если при движении вправо задевается правый концевик даже если время (3сек) не прошло он должен начать движение влево.
    Концевики своего рода крайние точки оси. До них объект в идеале не должен доходить, но если случиться это он должен пойти в противоположном направление. Концевики используются как предохранитель, что бы объект не уперся в край ОСИ и не начал об нее биться (это может случиться по разным причинам к примеру не ровность ОСИ или какое-то воздействие на объект).
     

    Вложения:

  15. Airo

    Airo Нерд

    Я пробовал. digitalWrite(dirPin, HIGH); это по сути и есть флаг (HIGH-враво, LOW-влево). Но проблема в том что при контакте с концевиком флаг меняется, но только до того момента пока кнопка не отожмется (так как используется оптический концевик у него кнопку заменяет лазер. В активном состоянии он выдает Folse, если лазер прерывается True.) и как только лазер становиться опять Folse движение объекта опять стремиться к нему.
     
  16. Sergku

    Sergku Нерд

    Допустим, он встретил концевик, и развернулся, время обратного движения снова в 3 секунды устанавливается?
     
  17. Airo

    Airo Нерд

    Если мои объяснения неясны скажите, попробую как то объяснить по другому.
     
  18. Airo

    Airo Нерд

    Да.
     
  19. Sergku

    Sergku Нерд

    на основе шаблона, что я кидал выше, должно заработать:

    Код (C++):

    unsigned long
      motorTmr = 0,
      processTmr= 0;
             
    int
      processDelay = 3000, // Общее вращение
      motorDelay = 10; // Для обмоток мотора

    boolean
        currentDirection = false;

    const byte
      leftSensor = 8,
      rightSensor = 9,
      dirPin = 3,
      stepPin = 2;
     

    void setup(){
      pinMode(leftSensor, INPUT_PULLUP);
      pinMode(rightSensor, INPUT_PULLUP);
      pinMode(dirPin, OUTPUT);
      pinMode(stepPin, OUTPUT);
      motorTmr = processTmr = millis();
    }

    void loop(){

        if(!digitalRead(leftSensor)){
            processTmr = millis();
            currentDirection = !currentDirection;
        }

        if(!digitalRead(rightSensor)){
            processTmr = millis();
            currentDirection = !currentDirection;
        }
       
        if (millis() - processTmr <= processDelay){
            if(millis() - motorTmr >= motorDelay){
                motorTmr = millis();
                digitalWrite(dirPin, currentDirection);
                digitalWrite(stepPin, !digitalRead(stepPin));
            }    
        } else {
            processTmr = millis();
            currentDirection = !currentDirection;
        }
    }
     
  20. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Вы должны ущучивать не только текущее состояние сенсора, но и момент перехода состояния, и направление перехода.
    Например в цикле - считать текущее состояние сенсора - запомнить его. В очередной итерации - считать состояние, сравнить с запомненным, и снова запомнить новое состояние. Если оно не изменилось - игнорировать. Если изменилось (напр. 0->1) - предпринять действие. Если изменилось наоборот - снова игнорировать и тд.
    ПС. При использовании механизма прерываний - можно как раз настроить пин входа на отслеживание - либо уровня на пине, либо направления изменения уровня на пине.
    ППС. В случае мех. сенсоров, вам придется бороться с дребезгом, но в вашем случае оптических сенсоров - вряд ли это надо.
     
    Последнее редактирование: 6 июн 2023