Использование концевого выключателя для остановки шагового двигателя

Я строю машину с подвижной станиной, которая движется вперед и назад. Мне нужно включить концевой выключатель на двух концах, который гарантирует, что двигатели остановятся в двух крайних точках. У меня есть 2 шаговых двигателя, управляемых драйверами двигателей TB6600, я пытаюсь начать с 1 концевого выключателя (SS-5Gl2) и продвигаться оттуда.

Мой первый вопрос: как мне получить код для остановки шаговых двигателей, если концевой выключатель замкнут?

// Определяем подключения шагового двигателя и количество шагов на оборот:
#define dirPin1 2
#define stepPin1 3
#define dirPin2 5
#define stepPin2 6
#define stepsPerRevolution 200 // Нам может понадобиться изменить 200 на 1600, чтобы получить более точное управление, т.е. десятичные дроби вместо целых чисел


#define Lim1 8


int direction = 0;
int remainder = 0;
long travel = 0;
long revolutions = 0;


void setup() {


  // Объявить выводы выводом:
  pinMode(stepPin1, OUTPUT);
  pinMode(dirPin1, OUTPUT);
  pinMode(stepPin2, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  
  pinMode(Lim1, OUTPUT);


 //Желаемое расстояние перемещения в мм !!!! ставь сюда!!!!
travel = 1;
//Желаемое направление!!!! ставь сюда!!!! переместить кубик внутрь (против часовой стрелки) = 1, вернуться назад (по часовой стрелке) = 0 !!!!
//направление = 0; не сработало, нужно логическое значение?



// Установите направление вращения против часовой стрелки (затухание) или по часовой стрелке (затухание):
//if(direction = 1) digitalWrite(dirPin, HIGH);
//if(direction = 0) digitalWrite(dirPin, LOW);


//устанавливаем направление вручную, раскомментируем HIGH для входа, LOW для возврата
digitalWrite(dirPin1, LOW);
digitalWrite(dirPin2, LOW);
//digitalWrite(dirPin, LOW);


digitalWrite(Lim1, OFF) //


// вычисление количества оборотов на основе введенных мм. Пока не учитывает частичные обороты - переменная усечена, по умолчанию используются целые числа. Потребуется еще один цикл для обработки остатка
// Константа 6,659 (микрон) основана на шаге винта привода 1,25 мм и передаточном отношении в редукторе
revolutions = 1000.00*travel/6.659;
//попытка вывести сохраненное значение на ПК для целей отладки

Serial.print("revolutions = ");
Serial.print(revolutions,4);
}


void loop() {


   // Шаговый двигатель делает X оборотов быстро, скорость (задержка), по-видимому, ограничена напряжением. 42v должно идти быстрее?
   // Требуется вложенный цикл, потому что целые числа в UNO ограничены ~ 32k
  for (int i = 0; i < revolutions; i++) {


   if (digitalRead(Lim1 == OFF)){}


   else {
      for (int j = 0; j < stepsPerRevolution; j++) {
       // Эти четыре строки дают 1 оборот:
      digitalWrite(stepPin1, HIGH);
      digitalWrite(stepPin2, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin1, LOW);
      digitalWrite(stepPin2, LOW);
      delayMicroseconds(250);
      }
  }
  }
 
   while(1){}
  
}

, 👍0

Обсуждение

// Эти четыре строки приводят к 1 обороту: ... это должно сказать // Эти шесть строк приводят к 1 шагу:, @jsotola


2 ответа


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

0

Вы выполняете каждый шаг вручную непосредственно с помощью digitalWrite(), поэтому принципом будет чтение вывода концевого выключателя на каждой итерации внутреннего цикла for в Оператор if. Что делать в этом операторе if, зависит от того, что вы хотите сделать при нажатии концевого выключателя. В настоящее время у вас есть бесконечный пустой цикл после вашего кода двигателя. Поэтому, если вы хотите остановиться навсегда, в этом случае вы можете создать еще один бесконечный цикл. Итак, что-то вроде этого:

...
for (int j = 0; j < stepsPerRevolution; j++) {
   if(!digitalRead(Lim1)){
       while(true);
   }
   // These four lines result in 1 revolution:
   digitalWrite(stepPin1, HIGH);
   digitalWrite(stepPin2, HIGH);
   delayMicroseconds(250);
   digitalWrite(stepPin1, LOW);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(250);
}

Обратите внимание, что это предполагает, что вы подключили концевой выключатель к земле и используете цифровой контакт с подтягивающим резистором.


Но у вас есть еще 2 проблемы с кодом концевого выключателя:

  1. Вы устанавливаете контакт концевого выключателя Lim1 в качестве вывода, хотя для считывания переключателя необходимо настроить его как ввод. И если вы хотите использовать подтягивающий резистор (в отличие от подтягивающего резистора), вы можете активировать внутреннюю подтяжку на том же шаге:

    ...
    for (int j = 0; j < stepsPerRevolution; j++) {
       if(!digitalRead(Lim1)){
           while(true);
       }
       // These four lines result in 1 revolution:
       digitalWrite(stepPin1, HIGH);
       digitalWrite(stepPin2, HIGH);
       delayMicroseconds(250);
       digitalWrite(stepPin1, LOW);
       digitalWrite(stepPin2, LOW);
       delayMicroseconds(250);
    }
    
  2. При чтении концевого выключателя внутри внешнего цикла for вы пишете

     pinMode(Lim1, INPUT_PULLUP);
    

    Вы выполняете сравнение на равенство между OFF и номером контакта, а не между OFF и возвращаемым значением digitalRead(). Здесь нужно правильно расставить скобки:

     if (digitalRead(Lim1 == OFF)){}
    

    Выше я использовал эквивалентную форму

     if(digitalRead(Lim1) == OFF){}
    

    с оператором отрицания !

Помимо того, что вам не хватает Serial.begin() со скоростью передачи данных, которую вы хотите использовать, в setup().

,

Спасибо за ваш ответ, я действительно новичок и полностью запутался., @303jw1095


-1
// Определяем подключения шагового двигателя и количество шагов на оборот:
#define dirPin1 5
#define stepPin1 2
#define dirPin2 6
#define stepPin2 3
#define stepsPerRevolution 200 // Нам может понадобиться изменить 200 на 1600 на
get more precise control, i.e. decimals verse integers'
#define limPin1 8
#define CW 0x1
#define CCW 0x0

int remainder = 0;
long travel = 0;
long revolutions = 0;
bool homed = false;

void setup() {

  // Объявить выводы выводом:
  pinMode(stepPin1, OUTPUT);
  pinMode(dirPin1, OUTPUT);
  pinMode(stepPin2, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  pinMode(limPin1, INPUT_PULLUP);

//Желаемое направление!!!! ставь сюда!!!! переместить кубик (против часовой стрелки) = 1, назад
out(cw) = 0 !!!!
//направление = 0; не сработало, нужно логическое значение?

// Устанавливаем направление вращения против часовой стрелки (умираем) или по часовой стрелке
(die out):
//if(direction = 1) digitalWrite(dirPin, HIGH);
//if(direction = 0) digitalWrite(dirPin, LOW);

//устанавливаем направление вручную, раскомментируем HIGH для затвердевания, LOW для затухания
out
digitalWrite(dirPin1, LOW);
digitalWrite(dirPin2, LOW);

//попытка вывести сохраненное значение на ПК для целей отладки
Serial.begin(9600);
Serial.println("test");
}

// основная процедура
void loop() {
Homing();
}

void Homing() {
     // Быстро вращаем шаговый двигатель X оборотов, скорость (задержка)
     apparently limited by voltage. 42v should go faster?
     //Требуется вложенный цикл, потому что целые числа в UNO ограничены
     ~32k
     if (homed == false)
  {
    // вычисление количества оборотов на основе введенных мм. еще не
   account for partial revs - variable is truncated, integers are 
default. 
   Would need another loop to handle the remainder
        // Константа 6,659 (микрон) основана на 1,25 мм приводном винте
pitch, 
    and ratio in gearbox
        float travel = 2.0;
        float revolutions = 1000.00*travel/6.659;
    int totalStepsOut = revolutions * stepsPerRevolution;
    Serial.print("revolutions = ");
    Serial.println(revolutions,4);
    digitalWrite(dirPin1, CCW);
    digitalWrite(dirPin2, CCW);
    for (int j = 0; j < totalStepsOut; j++) {
      bool limState = digitalRead(limPin1);
      if (limState == false)
      {
        // Лимит срабатывает
        HomingReturn();
        break;
    }
    else
    {
        //Лимит не срабатывает
        // Эти шесть строк приводят к 1 обороту:
      digitalWrite(stepPin1, HIGH);
      digitalWrite(stepPin2, HIGH);
      delayMicroseconds(250);
      digitalWrite(stepPin1, LOW);
      digitalWrite(stepPin2, LOW);
      delayMicroseconds(250);
      }
    }
   }
   // Добавьте сюда вещи, чтобы делать все, что вы хотите, после возвращения домой
   Serial.println("Homed");
}

void HomingReturn()
{
  //задаем направление для реверса
  digitalWrite(dirPin1, CW);
  digitalWrite(dirPin2, CW);
  Serial.println("Reversing");
  //Желаемое расстояние перемещения в мм !!!! ставь сюда!!!!
  float travel = 0.1; 
  float revolutions = 1000.00*travel/6.659;
  int totalStepsOut = revolutions * stepsPerRevolution;
  for (int j = 0; j < totalStepsOut; j++) {
    //веди машину обратно
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2, HIGH);
    delayMicroseconds(250);
    digitalWrite(stepPin1, LOW);
    digitalWrite(stepPin2, LOW);
    delayMicroseconds(250);
      }
      homed = true;
     Serial.println("Done");
   }
,

Как сейчас написано, ваш ответ неясен. Пожалуйста, [изменить], чтобы добавить дополнительные сведения, которые помогут другим понять, как это относится к заданному вопросу. Дополнительную информацию о том, как писать хорошие ответы, можно найти [в справочном центре](/help/how-to-answer)., @Community