Линейная интерполяция

everlast
Offline
Зарегистрирован: 29.10.2015

Доброго времени суток.

Прошу помочь в решении проблемы. У меня система из 2-х шаговых двигателей(ШД) и CNC Shield c драйверами. Смог сделать так. В COM-порт посылаю номер мотора и количество шагов. Он откручивает. Теперь надо сделать линейную  интерполяцию (типа движение по диагонали). Т.о. работают два мотора одновременно. подскажите как сделать!

P.S. Видел в интернете hex файлы для прошивки 3 осей и одного лазера, которые работают с G - кодами для ЧПУ, но это не подходит.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

надо сделать линейную  интерполяцию (типа движение по диагонали). 

Это совсем разные вещи. Что Вам нужно-то нормальными словами?

everlast пишет:

Т.о. работают два мотора одновременно. подскажите как сделать!

 
Ага, Вам надо проехать по прямой так, чтоюы по оси Х это было n сантиметров/оборотов, а по оси Y - m. Так?
Ну так считайте по теореме Пифагора.
 
Или я что-то неправильно понял?
 
everlast
Offline
Зарегистрирован: 29.10.2015

Да. Правильно. По прямой. Один проезжает по X сколько-то шагов, другой по Y. При этом поподая в нужную точку. По теореме Пифагора? Это каким образом?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

Да. Правильно. По прямой. Один проезжает по X сколько-то шагов, другой по Y. При этом поподая в нужную точку. По теореме Пифагора? Это каким образом?

Ну, Вы объясните что нужно. Про Пифагора я имел в виду, если Вы знаете две стороны  треугольника, а надо посчитать третью. Но, теперь, мне кажется. что Вам нужно не это. А что - я никак не пойму. Ну, поехали по одной оси 5 см., а по друго 8, а что Вам надо-то? У Вас проблема с одновременностью работы моторов или с чем?

everlast
Offline
Зарегистрирован: 29.10.2015

Мне нужно, чтобы работал 2 ШД работали, которые двигают платформу, как в ЧПУ станке т.е. дновременно ехали. Один столько, другой столько и попадали в нужную мне точку. Я пишу в COM порт этим движкам координаты в шагах. И они одновременн едут, продвигая мою подвижку по платформу. http://upload.akusherstvo.ru/image925489.jpg

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, Вы говорите, что по одной оси они у Вас ездят. Так? По любой ездят? И по и X и по Y - но тольео не одновременно. Правильно я понял? Так может хоть код покажете. как оно сейчас сделано?

everlast
Offline
Зарегистрирован: 29.10.2015

Сейчас так: я в COM порт посылаю номер мотора и количество шагов и он делает. Потом выбираю другой и делаю тоже самое. А мне нужно, то , что я описал выше. Как я понял, интерполяция делается в ЧПУ станках так. Ты задал конечную точку, а он движет то одним мотором, то другим поочередно, сответственн приходя в нужную нам точку. http://postprocessor.su/linear_moves.html

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я Вам писал

ЕвгенийП пишет:

может хоть код покажете, как оно сейчас сделано?

Вы же вместо кода

everlast пишет:

Сейчас так: я в COM порт посылаю номер мотора и количество шагов и он делает. Потом выбираю другой и делаю тоже самое. 

Вы издеваетесь? Не хотите показывать код (боитесь, что я украду) - дело хозяйское, только тогда и разбирайтесь сами.

everlast
Offline
Зарегистрирован: 29.10.2015
/* массивы перемен */
int motorNumb; // номер мотора
char CurChar; // текущий символ для установки флага мотора или шага
char Com_Step = 0; // флаг установки шага
char Com_Motor = 0; // флаг выбора мотора
int dirPin1 = 5; // pin для направления
int dirPin2 = 6;
int stepPin1 = 2; // pin для шагов
int stepPin2 = 3; 
int openmotorPin = 8; // pin для запуска мотора
int val_btn1=0;           // значение кнопки
int val_btn2=0;                
int btnPin1 = 15;         // pin для кнопки
int btnPin2 = 14; 
int speedmotor = 2000;   // задаем скорость мотора
int stepsvar = 0;      // значение шагов, которое задаем мотору
int flag_zero=1;  //флаг установки нулей
int flag1_motor=1;
int flag2_motor=1;


/* Функция установки pin и открытия com-порт */
void setup() 
{
  // задаем, что этот pin на выход
  pinMode(dirPin1, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  pinMode(stepPin1, OUTPUT);
  pinMode(stepPin2, OUTPUT);
  pinMode(openmotorPin, OUTPUT);
  pinMode(btnPin1,INPUT_PULLUP);
  pinMode(btnPin2,INPUT_PULLUP);
  // открываем com-порт со скоростью передачи 9600
  Serial.begin(9600);  
}


/* функция, отвечающая за вращение мотора №1 */
void step1(boolean dir,int steps)
{
  digitalWrite(dirPin1,dir);
   for(int i=0;i<steps;i++)
   {
    // если на pin кнопки что-то пришло, то выходим из цикла принудительно
    val_btn1= digitalRead(btnPin1);
    if(val_btn1==LOW)
    {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);
   flag1_motor=1;}
    if((val_btn1==HIGH)&&(flag1_motor==1))
   {flag1_motor=0;
   break;
   }
   if((val_btn1==HIGH)&&(flag1_motor==0))
   {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* функция, отвечающая за вращение мотора №2 */
void step2(boolean dir,int steps)
{
  digitalWrite(dirPin2,dir);
   for(int i=0;i<steps;i++)
   {
    val_btn2= digitalRead(btnPin2);
    if(val_btn2==LOW)
    {digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);
   flag2_motor=1;}
    if((val_btn2==HIGH)&&(flag2_motor==1))
   {flag2_motor=0;
   break;
   }
   if((val_btn2==HIGH)&&(flag2_motor==0))
   {digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);}
   }

}

 /*При введение символа 'M' или 'S' устанавливается 
 флаг мотора или флаг шага*/
 if ((Serial.available() > 0)&&(Com_Step == 0)&& (Com_Motor == 0)) 
  {
    //читаем байт из порта
    CurChar = Serial.read();
    //если это символ S то устанавливаем флаг начала установки шага
    if (CurChar == 'S') 
    {
      Com_Step = 1;
      Serial.println("Select Steps");
    } else 
    {
      //если это символ M то устанавливаем флаг выбора мотора
      if (CurChar == 'M') 
      {
        Com_Motor = 1;
        Serial.println("Selection motor");
      }
    }
  }  


  /* Устанавливаем какой мотор будет работать */
  //если в порту есть хоть один символ и установлен флаг выбора мотора
  if ((Serial.available() > 0)&&(Com_Motor == 1)) 
  {
    // сбрасываем флаг
    Com_Motor = 0;
    Serial.print("Motor: ");
    motorNumb = Serial.parseInt();
    Serial.println(motorNumb);
     
  }
   

  /* Устанавливаем сколько шагов должен сделать мотор */
  //если в порту есть хоть один символ и установлен флаг установки шага//
  if ((Serial.available() > 0)&&(Com_Step == 1))
  {
    // сбрасываем флаг установки шага
    Com_Step = 0;
    Serial.print("Steps: ");
    stepsvar=Serial.parseInt();
    Serial.println(stepsvar);

    //в зависимости от того какой номер мотора
    //назначен выполняется определенный case
    switch (motorNumb)
    {

      case 1:
      if (stepsvar > 0)
      {
        step1(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step1(false,stepsvar);
      }
      break;

      case 2:
      if (stepsvar > 0)
      {
        step2(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step2(false,stepsvar);
      }
      break;
 
    }
  }
    
}

Да нет я его искал. Вот сейчас и кидаю. Слишком много скетчей у меня.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А где функция loop()? Давайте-ка работающий скетч, прямо копи-пастом из IDE.

everlast
Offline
Зарегистрирован: 29.10.2015
/* массивы перемен */
int motorNumb; // номер мотора
char CurChar; // текущий символ для установки флага мотора или шага
char Com_Step = 0; // флаг установки шага
char Com_Motor = 0; // флаг выбора мотора
int dirPin1 = 5; // pin для направления
int dirPin2 = 6;
int stepPin1 = 2; // pin для шагов
int stepPin2 = 3; 
int openmotorPin = 8; // pin для запуска мотора
int val_btn1=0;           // значение кнопки
int val_btn2=0;                
int btnPin1 = 15;         // pin для кнопки
int btnPin2 = 14; 
int speedmotor = 2000;   // задаем скорость мотора
int stepsvar = 0;      // значение шагов, которое задаем мотору
int flag_zero=1;  //флаг установки нулей
int flag1_motor=1;
int flag2_motor=1;


/* Функция установки pin и открытия com-порт */
void setup() 
{
  // задаем, что этот pin на выход
  pinMode(dirPin1, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  pinMode(stepPin1, OUTPUT);
  pinMode(stepPin2, OUTPUT);
  pinMode(openmotorPin, OUTPUT);
  pinMode(btnPin1,INPUT_PULLUP);
  pinMode(btnPin2,INPUT_PULLUP);
  // открываем com-порт со скоростью передачи 9600
  Serial.begin(9600);  
}


/* функция, отвечающая за вращение мотора №1 */
void step1(boolean dir,int steps)
{
  digitalWrite(dirPin1,dir);
   for(int i=0;i<steps;i++)
   {
    // если на pin кнопки что-то пришло, то выходим из цикла принудительно
    val_btn1= digitalRead(btnPin1);
    if(val_btn1==LOW)
    {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);
   flag1_motor=1;}
    if((val_btn1==HIGH)&&(flag1_motor==1))
   {flag1_motor=0;
   break;
   }
   if((val_btn1==HIGH)&&(flag1_motor==0))
   {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* функция, отвечающая за вращение мотора №2 */
void step2(boolean dir,int steps)
{
  digitalWrite(dirPin2,dir);
   for(int i=0;i<steps;i++)
   {
    val_btn2= digitalRead(btnPin2);
    if(val_btn2==LOW)
    {digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);
   flag2_motor=1;}
    if((val_btn2==HIGH)&&(flag2_motor==1))
    flag2_motor=0;
   break;
   }
   if((val_btn2==HIGH)&&(flag2_motor==0))
   {digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* Функция работает по кругу(зациклена) */
void loop ()
{ 

 /*При введение символа 'M' или 'S' устанавливается 
 флаг мотора или флаг шага*/
 if ((Serial.available() > 0)&&(Com_Step == 0)&& (Com_Motor == 0)) 
  {
    //читаем байт из порта
    CurChar = Serial.read();
    //если это символ S то устанавливаем флаг начала установки шага
    if (CurChar == 'S') 
    {
      Com_Step = 1;
      Serial.println("Select Steps");
    } else 
    {
      //если это символ M то устанавливаем флаг выбора мотора
      if (CurChar == 'M') 
      {
        Com_Motor = 1;
        Serial.println("Selection motor");
      }
    }
  }  


  /* Устанавливаем какой мотор будет работать */
  //если в порту есть хоть один символ и установлен флаг выбора мотора
  if ((Serial.available() > 0)&&(Com_Motor == 1)) 
  {
    // сбрасываем флаг
    Com_Motor = 0;
    Serial.print("Motor: ");
    motorNumb = Serial.parseInt();
    Serial.println(motorNumb);
     
  }
   

  /* Устанавливаем сколько шагов должен сделать мотор */
  //если в порту есть хоть один символ и установлен флаг установки шага//
  if ((Serial.available() > 0)&&(Com_Step == 1))
  {
    // сбрасываем флаг установки шага
    Com_Step = 0;
    Serial.print("Steps: ");
    stepsvar=Serial.parseInt();
    Serial.println(stepsvar);

    //в зависимости от того какой номер мотора
    //назначен выполняется определенный case
    switch (motorNumb)
    {

      case 1:
 
      if (stepsvar > 0)
      {
        step1(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step1(false,stepsvar);
      }
      break;

      case 2:
      if (stepsvar > 0)
      {
        step2(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step2(false,stepsvar);
      }
      break;

  }
    
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, понятно.

У Вас структура программы заточена по то, что пока мотор не отработает нужные шаги, программа не воспринимает никаких других команд. Чтобы иметь возможность гонять их параллельно, надо менять структуру программы - т.е. переписывать её.

Вы готовы на это? В принципе Вы ничего не выиграете - конечная скорость прибытия в нужную точку будет такой же. Просто ехать будет "вправо-вверх" как сейчас, а по диалоналям.

Если готовы, могу дать некую отправную точку, как переписать. Где-то через час-другой освобожусь и могу показать.

Только, по мне, так смысла в этом не вижу.

everlast
Offline
Зарегистрирован: 29.10.2015

 Я был бы рад, если бы помогли! Я тоже так думаю, но мне это нужно под проект, поэтому, если подскажите - будет здорово!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, вот попробуйте вот такой скетч.

Сразу должен сказать:

1. я пока не понял что Вы хотели сделать с кнопками - у меня никаких кнопок нет, если надо - добавим, но мне надо понимать что они делают.

2. Команды я подавал из монитора порта не по одному числу, а сразу командой. Формат команд:

N S <символ новой строки>

где
N - номер мотора (1 или 2). Если 0 - то команда относится к обоим моторам сразу.
S - количество шагов. Если положительное, то (как было у Вас dir будет HIGH, иначе - LOW. Если S равно нулю, то команда немедленно останавливает мотор.

Значит так, по мере поступления команды мотор(ы) начинают движение. Если во время движения поступает новая команда - мотор забывает старую и выполняет указанное количество шагов из той точки в которой в данный момент находится. В случае если поступила команда на 0 шагов - мотор останавливается немедленно.

Я не испытывал на моторах - у меня их нет, я просто наблюдал за выводом в сериал. Управление моторами мне испытать не на чем. Само по себе управление я просто переписал у Вас - проверьте, не ляпнул ли чего, если ляпнул - поправим.

Вот скетч:

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

class Motor {
public:
	Motor(const int8_t dirPin, const int8_t stepPin, const char * motorName) {
    	m_dirPin = dirPin;
    	m_stepPin = stepPin;
    	pinMode(m_dirPin, OUTPUT);
		pinMode(m_stepPin, OUTPUT);
		m_stepsToDo = 0;
		m_direction = LOW;
		m_Name = (char *) motorName;
	}

	void doOneStep(void) {
		if (! m_stepsToDo) return;
		m_stepsToDo--;
		digitalWrite(m_dirPin, m_direction);
		digitalWrite(m_stepPin, HIGH);
		delayMicroseconds(speedMotor);
		digitalWrite(m_stepPin, LOW);
		delayMicroseconds(speedMotor);
		Serial << m_Name << ": doing step. " << m_stepsToDo << " steps left. Direction=" << m_direction << "\n";
	}
	inline void SetSteps (const int steps) { m_stepsToDo = (m_direction = (steps > 0)) ? steps : -steps; }
private:
	static int speedMotor; 
	int8_t m_dirPin, m_stepPin, m_direction;
	int m_stepsToDo;
	char * m_Name;
};

char *sm1 = "X motor", *sm2 = "Y motor";
int Motor::speedMotor = 2000;

Motor motors[2] = { Motor(5, 2, sm1), Motor(6, 3, sm2) };

void setup() {
	Serial.begin(115200);
}

const bool readCommand(int &steps, int &motor) {
	static char commandBuffer[16] = {0};
	static int8_t ptr = 0;
	static const int8_t BufferSize = sizeof(commandBuffer)/sizeof(commandBuffer[1]) - 1;
	char symbol = 0;
	while (Serial.available() && ptr < BufferSize) {
		symbol = Serial.read();
		if (symbol == '\n') break;
		commandBuffer[ptr++] = symbol;
	}
	if (ptr == BufferSize) {
		ptr = 0;
		motor = -1;
		Serial << "Input buffer OVERFLOW\n";
		return true;
	}
	if (symbol != '\n') return false;
	commandBuffer[ptr] = 0;
	Serial << "Command read: \"" << commandBuffer << "\"\n";
	sscanf(commandBuffer, "%d %d", &motor, &steps);
	ptr = 0;
	return true;
}

void loop () {
	motors[0].doOneStep();
	motors[1].doOneStep();
	int steps, motor;
	if (! readCommand(steps, motor)) return;
	if (motor < 0 || motor > 2) {
		Serial << "Command not recognized\n";
	} else if (motor == 0) {
		motors[0].SetSteps(steps);
		motors[1].SetSteps(steps);
	} else {
		motors[motor-1].SetSteps(steps);
	}
}

а вот протокол исполнения (то, что в Сериале напечаталось, я только комментарии добавил для Вас)

Command read: "1 3"   --- ввёл команду 1 3 - мотор 1 выполнил 3 шага вперёд
X motor: doing step. 2 steps left. Direction=1
X motor: doing step. 1 steps left. Direction=1
X motor: doing step. 0 steps left. Direction=1
Command read: "2 -4"    --- ввёл команду 2 -4 - мотор 4 выполнил 4 шага назад
Y motor: doing step. 3 steps left. Direction=0
Y motor: doing step. 2 steps left. Direction=0
Y motor: doing step. 1 steps left. Direction=0
Y motor: doing step. 0 steps left. Direction=0
Command read: "3 4"    --- ввёл команду 3 4 - мотора 3 не бывает
Command not recognized
Command read: "0 3"    --- ввёл команду 0 3 - оба мотора сделали 3 шага вперёд
X motor: doing step. 2 steps left. Direction=1
Y motor: doing step. 2 steps left. Direction=1
X motor: doing step. 1 steps left. Direction=1
Y motor: doing step. 1 steps left. Direction=1
X motor: doing step. 0 steps left. Direction=1
Y motor: doing step. 0 steps left. Direction=1
Command read: "0 20000"    --- ввёл команду 0 20000 - оба мотора "поехали"
X motor: doing step. 19999 steps left. Direction=1
Y motor: doing step. 19999 steps left. Direction=1
X motor: doing step. 19998 steps left. Direction=1
Y motor: doing step. 19998 steps left. Direction=1
X motor: doing step. 19997 steps left. Direction=1
Y motor: doing step. 19997 steps left. Direction=1
Command read: "0 0"   --- ввёл команду 0 0- оба мотора остановились

Ктстати, останавливать можно и по одному, разумеется.

Как видите.я завёл "тип дланных" Motor  и определил две переменные этого типа. Чтобы отличать их друг от друга при печати, я добавил им имена. Никакой другой нагрузки имена не несут и их из окончательной версии можно выбросить.

Между числами в команде обязан быть хотя бы один пробел (или табуляция). Можно больше, но суммарная длина буфера команды - 16 символов. Если превысить, скетч ругнётся.
 

Вроде, всё. Код краткий и простой, но если есть вопросы - задавайте. Только испытайте сначала, не надо спрашивать "а что будет, если ..." На такие вопросы лучший ответ - попробовать.

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

До интерполяции не дотягивает.

Было красным, стало синим. Интерполяция зеленым. Почему бы не включать моторы одновременно - будет движение по диагонали.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Andy пишет:

Почему бы не включать моторы одновременно - будет движение по диагонали.

Я так понял задачу. Если нужно как-то по-другому, пусть ТС скажет.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Да, по диагонали. Под углом 45 градусов.

Чтобы изменить угол нужно хотя-бы по одной оси изменить скорость.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

trembo пишет:

Да, по диагонали. Под углом 45 градусов.

Чтобы изменить угол нужно хотя-бы по одной оси изменить скорость.

В данном скетче нельзя - она static. Но если ТС скажет, что это ему нужно - поменяем.

vladimir62
vladimir62 аватар
Offline
Зарегистрирован: 10.11.2015

А почему от G-кодов отказались? Ну или AccelStepper использовать. 

everlast
Offline
Зарегистрирован: 29.10.2015

Спасибо за скетч! Как вы правильно сказали нужно прверить всё. И сам скетч разберу и вам отпишусь. А кнопки - концевки, которыми я создаю ноль-пункт. Могу выслать как это у меня получилось.

Про интерполяцию мне было сказано, как писал выше Andy(зелёная линия, хотя и движение по синей линии может подойти).

Как в arduino использовать G - коды без лишних программ, типа grbl я не знаю! А ещё обязательно использование COM-порта, и мне кажется проще посылать шаги мотору, чем G- код. Хотя может я не прав.

С помощью  библиотеки AccelStepper вы предлагаете использовать различные скорости моторов? Если - да, то данный вариант не очень подходит. 

vladimir62
vladimir62 аватар
Offline
Зарегистрирован: 10.11.2015

 А что они (эти два ШД) делают то? Если стандартные и проверенные приемы управления ШД не подходят?

vladimir62
vladimir62 аватар
Offline
Зарегистрирован: 10.11.2015

 И еще, я посмотрел вашу программу, длительность периода между шагами у вас 2 миллисекунды. Предположим, что у вас стандартный мотор  с шагом 1.8 градуса, т.е. 200 шагов на оборот. Вы упоминаете о шилде с драйверами, на драйверах всегда есть функция деления шага, зачем нужен микрошаг понаписано много. Я не знаю что у вас установлено на драйверах. ну допустим деления нет , т.е. 1:1. Следовательно ШД у вас вращается 2.5 оборота в секунду. А где разгон и торможение в вашей программе ? Я думаю вы пытались увеличить частоту вращения уменьшением переменной speedmotor  и на каком значении происходит срыв? AccelStepper о котором я упомянул тоже имеет минусы. но разгоняет и тормозит он корректно. Насчет G-кодов согласен, с ними связываться надо при сборке 3D принтера или HomeCNC станка.

everlast
Offline
Зарегистрирован: 29.10.2015

Да у ШД 200 шагов на оборот. Делений нет, пока не требуются, но на шилде они естественно есть. Срыв честно говоря не помню, надо проверить(я выставил её стандартно и всё). Разгонно-тормозную характеристику делать буду позже. Мне сейчас нужно разобраться с интерполяцией.

everlast
Offline
Зарегистрирован: 29.10.2015

Да у ШД 200 шагов на оборот. Делений нет, пока не требуются, но на шилде они естественно есть. Срыв честно говоря не помню, надо проверить(я выставил её стандартно и всё). Разгонно-тормозную характеристику делать буду позже. Мне сейчас нужно разобраться с интерполяцией.

vladimir62
vladimir62 аватар
Offline
Зарегистрирован: 10.11.2015

Я вчера ошибся у вас длительность сигнала Step 2 миллисекунды (обычно на порядок меньше), а период 4 миллисекунды,т.е. скорость вращения 1.25 об/сек. Вы так и не сказали, что делаете из движков, но судя по всему координатный стол, тогда в программировании вы кружным путем пошли. Если нет, то еще раз 

everlast пишет:

Мне нужно, чтобы работал 2 ШД работали, которые двигают платформу, как в ЧПУ станке т.е. дновременно ехали. Один столько, другой столько и попадали в нужную мне точку. Я пишу в COM порт этим движкам координаты в шагах. И они одновременн едут, продвигая мою подвижку по платформу. http://upload.akusherstvo.ru/image925489.jpg

Для этой картинки операция интерполяции вырождается в одно деление 4/2=2. т.е. чтобы двум движкам прийти в эту точку одновременно, надо чтобы ШД Х сделал в два раза больше шагов чем ШД У и со скоростью в два раза большей чем у ШД У. Все!

Не буду цитировать ЕвгенияП, но он вам абсолютно верно пишет об одновременности работы движков, и программу он вам хорошую написал, если вы делаете манипулятор перередвижения для фигур на шахматной доске, только конем придется ходить в два приема.

everlast
Offline
Зарегистрирован: 29.10.2015

ЕвгенийП, здравствуйте. 

Изучил программу и опробовал её. Моторами не крутит и в COM порт ничего не выдаёт, кроме Input buffer OVERFLOWCommand not recognized если подать одно и тоже ( типа 1 700 несколько раз). Подумал из-за несовпадения скрости COM порта  у вас 112500 и у меня 9600. Изменил - ничего не случилось. А вот подумал , что у вас не прописан 8 пин, который управляет разрешением мотора - двигаться или не двигаться(enable). Прписал его в 

void setup() {
	Serial.begin(9600);
pinMode(8, OUTPUT);
}

Тоже не помогло. Вот и не в чём тут дело. И кидаю код с кнопками и 3-им мотором.

/* массивы перемен */
int motorNumb; // номер мотора
char CurChar; // текущий символ для установки флага мотора или шага
char Com_Step = 0; // флаг установки шага
char Com_Motor = 0; // флаг выбора мотора
int dirPin1 = 5; // pin для направления
int dirPin2 = 6;
int dirPin3 = 13;  
int stepPin1 = 2; // pin для шагов
int stepPin2 = 3; 
int stepPin3 = 12; 
int openmotorPin = 8; // pin для запуска мотора
int val_btn1=0;           // значение кнопки
int val_btn2=0;
boolean val_btn3=0;                  
int btnPin1 = 15;         // pin для кнопки
int btnPin2 = 14; 
int btnPin3 = 9; 
int speedmotor = 2000;   // задаем скорость мотора
int stepsvar = 0;      // значение шагов, которое задаем мотору
int flag_zero=1;  //флаг установки нулей
int flag1_motor=1;
int flag2_motor=1;
int flag3_motor=1;
int steps_shagovik1=1200; // весь диапазон шагового мотора
int steps_shagovik2=800;
int steps_shtok=360; // весь диапазон штокового мотора
int solenoidPin = 10; // pin для соленоида


/* Функция установки pin и открытия com-порт */
void setup() 
{
  // задаем, что этот pin на выход
  pinMode(dirPin1, OUTPUT);
  pinMode(dirPin2, OUTPUT);
  pinMode(dirPin3, OUTPUT);
  pinMode(stepPin1, OUTPUT);
  pinMode(stepPin2, OUTPUT);
  pinMode(stepPin3, OUTPUT);
  pinMode(openmotorPin, OUTPUT);
  pinMode(btnPin1,INPUT_PULLUP);
  pinMode(btnPin2,INPUT_PULLUP);
  pinMode(btnPin3,INPUT_PULLUP);
  pinMode(solenoidPin, OUTPUT);
  // открываем com-порт со скоростью передачи 9600
  Serial.begin(9600);  
}


/* функция, отвечающая за вращение мотора №1 */
void step1(boolean dir,int steps)
{
  digitalWrite(dirPin1,dir);
   for(int i=0;i<steps;i++)
   {
    // если на pin кнопки что-то пришло, то выходим из цикла принудительно
    val_btn1= digitalRead(btnPin1);
    if(val_btn1==LOW)
    {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);
   flag1_motor=1;}
    if((val_btn1==HIGH)&&(flag1_motor==1))
   {flag1_motor=0;
   break;
   }
   if((val_btn1==HIGH)&&(flag1_motor==0))
   {digitalWrite(stepPin1, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin1, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* функция, отвечающая за вращение мотора №2 */
void step2(boolean dir,int steps)
{
  digitalWrite(dirPin2,dir);
   for(int i=0;i<steps;i++)
   {
    val_btn2= digitalRead(btnPin2);
    if(val_btn2==LOW)
    {digitalWrite(solenoidPin,LOW);
      digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);
   digitalWrite(solenoidPin,HIGH);
   flag2_motor=1;}
    if((val_btn2==HIGH)&&(flag2_motor==1))
   {digitalWrite(solenoidPin,HIGH);
    flag2_motor=0;
   break;
   }
   if((val_btn2==HIGH)&&(flag2_motor==0))
   {digitalWrite(solenoidPin,LOW);
    digitalWrite(stepPin2, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin2, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* функция, отвечающая за вращение мотора №3 */
void step3(boolean dir,long steps){
   digitalWrite(dirPin3,dir);
   for(int i=0;i<steps;i++){
   val_btn3= digitalRead(btnPin3);
    if(val_btn3==HIGH)
    {digitalWrite(stepPin3, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin3, LOW);
   delayMicroseconds(speedmotor);
   flag3_motor=1;}
    if((val_btn3==LOW)&&(flag3_motor==1))
   {flag3_motor=0;
   break;
   }if((val_btn3==LOW)&&(flag3_motor==0))
   {digitalWrite(stepPin3, HIGH);
   delayMicroseconds(speedmotor);
   digitalWrite(stepPin3, LOW);
   delayMicroseconds(speedmotor);}
   }

}

/* Функция работает по кругу(зациклена) */
void loop ()
{ 

  /* Установка нулей для моторов */
  while(flag_zero==1)
  {
    digitalWrite(solenoidPin,HIGH);
    // Установка нулей для шагового мотора №1
    // Мотор доходит до кнопки (в качестве шагов весь диапазон)
    step1(true,steps_shagovik1);
    //Считываем значение кнопки
    val_btn1=digitalRead(btnPin1);

    if (val_btn1==HIGH)
    {
      delay(1000);
      Serial.println("Push button 1");
      //Мотор отходит на середину диапазона
      step1(false,(steps_shagovik1/2));
      Serial.println("Function step1");
    }
      delay(1000);
     //Установка нулей для шагового мотора №2
    step2(false,steps_shagovik2);
    val_btn2=digitalRead(btnPin2);
    if (val_btn2==HIGH)
    {
      delay(1000);
      Serial.println("Push button 2");
      step2(true,(steps_shagovik2/2));
    }
      delay(1000);
   //  Установка нулей для штокового мотора
    step3(true,steps_shtok);
    
    //Считываем значение кнопки
    val_btn3=digitalRead(btnPin3);
    if (val_btn3==LOW)
    {
      delay(1000);
      Serial.println("Push button 3");
      step3(false,(steps_shtok/2));
    }
    flag_zero=0;
  }

  
 /*При введение символа 'M' или 'S' устанавливается 
 флаг мотора или флаг шага*/
 if ((Serial.available() > 0)&&(Com_Step == 0)&& (Com_Motor == 0)) 
  {
    //читаем байт из порта
    CurChar = Serial.read();
    //если это символ S то устанавливаем флаг начала установки шага
    if (CurChar == 'S') 
    {
      Com_Step = 1;
      Serial.println("Select Steps");
    } else 
    {
      //если это символ M то устанавливаем флаг выбора мотора
      if (CurChar == 'M') 
      {
        Com_Motor = 1;
        Serial.println("Selection motor");
      }
    }
  }  


  /* Устанавливаем какой мотор будет работать */
  //если в порту есть хоть один символ и установлен флаг выбора мотора
  if ((Serial.available() > 0)&&(Com_Motor == 1)) 
  {
    // сбрасываем флаг
    Com_Motor = 0;
    Serial.print("Motor: ");
    motorNumb = Serial.parseInt();
    Serial.println(motorNumb);
     
  }
   

  /* Устанавливаем сколько шагов должен сделать мотор */
  //если в порту есть хоть один символ и установлен флаг установки шага//
  if ((Serial.available() > 0)&&(Com_Step == 1))
  {
    // сбрасываем флаг установки шага
    Com_Step = 0;
    Serial.print("Steps: ");
    stepsvar=Serial.parseInt();
    Serial.println(stepsvar);

    //в зависимости от того какой номер мотора
    //назначен выполняется определенный case
    switch (motorNumb)
    {

      case 1:
      digitalWrite(solenoidPin, HIGH);
      if (stepsvar > 0)
      {
        step1(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step1(false,stepsvar);
      }
      digitalWrite(solenoidPin, LOW);
      break;

      case 2:
      if (stepsvar > 0)
      {
        step2(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step2(false,stepsvar);
      }
      break;

      case 3:
      if (stepsvar > 0)
      {
        step3(true,stepsvar);
      }
      else if (stepsvar < 0)
      {
        stepsvar=-1*stepsvar;
        step3(false,stepsvar);
      }
      break;
 
    }
  }
    
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

ЕвгенийП, здравствуйте. 

Изучил программу и опробовал её. Моторами не крутит и в COM порт ничего не выдаёт, кроме Input buffer OVERFLOWCommand not recognized если подать одно и тоже ( типа 1 700 несколько раз). Подумал из-за несовпадения скрости COM порта  у вас 112500 и у меня 9600. Изменил - ничего не случилось. А вот подумал , что у вас не прописан 8 пин, который управляет разрешением мотора - двигаться или не двигаться(enable). 

Так, нет, так не пойдёт. Если Вы хотите довести всё до ума и заставить её ездить по диагоналям и как-то там ещё, я готов Вам помогать, но давайте идти шаг за шагом и не мешать в одну кучу всех мух и котлеты.

Будь мы вместе за компьютером, мы бы дожали это за пару часов, но так придётся потратить неделю, но мы дожмём. Для этого Вы должны 1) чётко делать что я говорю, и 2) давать мне точно ту информацию, которуя я прошу.

Поехали. Про пин пока забудьте и про моторы тоже. Отключите их. Подключим позже. Пока же:

1. Возьмите мой скетч из поста №14.
2. в мониторе установите ту же скорость, что и у меня в коде
3. В выпадающем списке, что находится рядом с выбором скорости в мониторе установите "новая строка"

После этого перезапустите скетч и вводите (по одной!!!) команды

1 3

2 -4

0 3

Команды вводите по одной. После каждой команды давите Ентер.

В результате Вы должны получить примерно ту же печать, что и у меня в посте №14. Если получите то же. что и у меня, напишите мне об этом. Если получите что-то другое, то дайте мне следующее:

1. Копипасту того, что напечатано в мониторе
2. скриншот монитора. чтобы я видел настройки скорости и новой строки.

Это самое главное - это логика работы всей программы. Когда дожмём это, перейдём к движкам. Дожмём их, перейдём к диагонали. Дожмём её, подумаем над разными скоростями. давайте по порядку.

Жду информации.

everlast
Offline
Зарегистрирован: 29.10.2015

Да. Всё получилось как у вас.

everlast
Offline
Зарегистрирован: 29.10.2015

Я попробовал с моторами. Они крутятся. Поробовал команду 0 500 оба крутит. Единственное они оба 500 крутят. А если надо записать ) 500 200. Хотя я спешу наверное. И я не очень понял вы пишете на C++? Просто я не все строчки понимаю. Например 1-ую.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

Я попробовал с моторами. Они крутятся. Поробовал команду 0 500 оба крутит. Единственное они оба 500 крутят. А если надо записать ) 500 200. Хотя я спешу наверное. И я не очень понял вы пишете на C++? Просто я не все строчки понимаю. Например 1-ую.

Отлично. Теперь, плавно переходим к "500 200".

Вам нужна единая команда типа 0 200 500? Не проблема. Сделаем.

Пока же её нет, делаем так:

1. вводим команду 1 500 <enter>
2. НЕ ДОЖИДАЯСЬ пока мотор остановится вводим 2 200 <enter>

Должны крутиться оба. Если 500 мало (не успеваете вторую команду ввести, а первый движок уже стал, введите в первой команде больше, 1000 там - сколько надо). Они должны крутиться оба но не совсем вместе. Должно быть так: один дёрнется, потом другой, потом снова первый и т.д.

Если это работает, перейдём одновременному кручению.

Пожалуйста

1) опишите что у Вас получилось и
2) Вы там добавляли какой-то пин. Выложите текущий скетч полностью, чтобы у нас одинаковые были.

 

everlast
Offline
Зарегистрирован: 29.10.2015

Всё так и есть, запускаем сначал один 1 1500, птм второй 2 1500 и они ходят дёргано - шаг за шагом.

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

class Motor {
public:
	Motor(const int8_t dirPin, const int8_t stepPin, const char * motorName) {
    	m_dirPin = dirPin;
    	m_stepPin = stepPin;
    	pinMode(m_dirPin, OUTPUT);
		pinMode(m_stepPin, OUTPUT);
		m_stepsToDo = 0;
		m_direction = LOW;
		m_Name = (char *) motorName;
	}

	void doOneStep(void) {
		if (! m_stepsToDo) return;
		m_stepsToDo--;
		digitalWrite(m_dirPin, m_direction);
		digitalWrite(m_stepPin, HIGH);
		delayMicroseconds(speedMotor);
		digitalWrite(m_stepPin, LOW);
		delayMicroseconds(speedMotor);
		Serial << m_Name << ": doing step. " << m_stepsToDo << " steps left. Direction=" << m_direction << "\n";
	}
	inline void SetSteps (const int steps) { m_stepsToDo = (m_direction = (steps > 0)) ? steps : -steps; }
private:
	static int speedMotor; 
	int8_t m_dirPin, m_stepPin, m_direction;
	int m_stepsToDo;
	char * m_Name;
};

char *sm1 = "X motor", *sm2 = "Y motor";
int Motor::speedMotor = 2000;

Motor motors[2] = { Motor(5, 2, sm1), Motor(6, 3, sm2) };

void setup() {
	Serial.begin(115200);
        pinMode(8, OUTPUT);
}

const bool readCommand(int &steps, int &motor) {
	static char commandBuffer[16] = {0};
	static int8_t ptr = 0;
	static const int8_t BufferSize = sizeof(commandBuffer)/sizeof(commandBuffer[1]) - 1;
	char symbol = 0;
	while (Serial.available() && ptr < BufferSize) {
		symbol = Serial.read();
		if (symbol == '\n') break;
		commandBuffer[ptr++] = symbol;
	}
	if (ptr == BufferSize) {
		ptr = 0;
		motor = -1;
		Serial << "Input buffer OVERFLOW\n";
		return true;
	}
	if (symbol != '\n') return false;
	commandBuffer[ptr] = 0;
	Serial << "Command read: \"" << commandBuffer << "\"\n";
	sscanf(commandBuffer, "%d %d", &motor, &steps);
	ptr = 0;
	return true;
}

void loop () {
	motors[0].doOneStep();
	motors[1].doOneStep();
	int steps, motor;
	if (! readCommand(steps, motor)) return;
	if (motor < 0 || motor > 2) {
		Serial << "Command not recognized\n";
	} else if (motor == 0) {
		motors[0].SetSteps(steps);
		motors[1].SetSteps(steps);
	} else {
		motors[motor-1].SetSteps(steps);
	}
}

 

sva1509
Offline
Зарегистрирован: 07.12.2012

2 everlast 

Вам поможет алгоритм Брезенхема:

https://ru.wikipedia.org/wiki/Алгоритм_Брезенхэма

причем он работает без умножения и деления (для быстроты)

 

everlast
Offline
Зарегистрирован: 29.10.2015

sva1509 Спасибо! Посмотрю!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

Всё так и есть, запускаем сначал один 1 1500, птм второй 2 1500 и они ходят дёргано - шаг за шагом.

Всё здорово. Сегодня чуть попозже попробуем ходить н дёргано.

А пока, знаете, я в прошлый раз забыл - комадна для двух двигателей у нас ведь есть, только там нельзя разные дистанции задать. Попробуйте 0 1500 - должны также дёргано по диагонали ехать. Скажите мне работает ли.

Дерганность сегодня победим, надеюсь, чуть позже. Только скажите мне пожалуйста две вещи:

1. Имею ли я право занимать таймер(ы). Они у Вас для чего-то ещё используются? Или я могу занимать оба? Или один?

2. Нужно ли Вам будет делать задежку (которая сейчас 2000мкс) разной для разных двигателей или она всегда будет одинаковой для обоих?

everlast
Offline
Зарегистрирован: 29.10.2015

У меня диапозон движения не такой большой, поэтому писал 0 500 и едут они диагонали. Дёрганость на самой платформе(когда едут два движка) не видно.

1. Я не пользовался таймерами и пока не знаю как ими работать;

2. Вы имеете ввиду вот это?Скорость моторов? Я пока не знаю.

int Motor::speedMotor = 2000;

Вот что я думаю по поводу скорости моторов.Получается так, если я задаю 0 500 он движется по диагонали, и оба мотора приходят в одну точку. А когда будет по прямугольнику, то один закончит движение раньше другого 0 500 100. Получается, чтобы они пришли одновременно в одну точку по диагонали прямоугольника нужно варьировать скорость или использовать https://ru.wikipedia.org/wiki/Алгоритм_Брезенхэма ?! 

Ну и еще. Я не очень понимаю на каком языке вы написали? Мне просто надо прописать ноль-пункты для моторов и кнопки...Всё то, что описано в моём коде!  Я пока не знаю как сделать с вашей переделанной программой!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

Мне просто надо прописать ноль-пункты для моторов и кнопки...Всё то, что описано в моём коде!  Я пока не знаю как сделать с вашей переделанной программой!

Доберёмся. Всё будет. Давайте дожмём, чтобы всё хорошо ездило.

everlast
Offline
Зарегистрирован: 29.10.2015

Хорошо.

everlast
Offline
Зарегистрирован: 29.10.2015

ЕвгенийП Нашёл ещё один интересный скетч, как раз для ЧПУ станка. Что думаете?

int motorPins[3][2] = {{2,5},{3,6},{12, 13}};
int count;
int count2[3] = {0,0,0};
int val = 0;
int rot=0;
int incomingByte = 0;
int sign=1;
long delayTime;

//Процедура настройки прошивки
void setup() {
pinMode(8, OUTPUT);
int i;
Serial.begin(115200);  //Эта скорость должна совпадать со скоростью, установленной в программе

for (i=0; i<3; i++) {
for (count = 0; count < 2; count++) {
pinMode(motorPins[i][count], OUTPUT); //установка режима работы цифровых pin'ов Ардуино
}
}
delayTime=2000;
}

//Поворот двигателя с номерм sm на один шаг вперёд
void moveForward(int sm) {
digitalWrite(motorPins[sm][1], HIGH); //Задаём направление
digitalWrite(motorPins[sm][0], HIGH);
digitalWrite(motorPins[sm][0], LOW);
}


//Поворот двигателя с номерм sm на один шаг назад
void moveBackward(int sm) {
digitalWrite(motorPins[sm][1], LOW);
digitalWrite(motorPins[sm][0], HIGH);
digitalWrite(motorPins[sm][0], LOW);
}

//Задержка в микосекундах
void delayMicros(long wt){
unsigned long mls;
unsigned int mks;

mls=(unsigned long)(wt / 1000);
mks=(unsigned int)(wt % 1000);
if (mls>0) delay(mls);
if (mks>0) delayMicroseconds(mks);
}

//Одновременный поворот двигателей 0, 1, 2 на x, y, z шагов соответственно
void MoveSM(long x, long y, long z) {
long c[3], c2[3];
double c1[3], d[3];
long m, i;
boolean flg;

c[0] = x;
c[1] = y;
c[2] = z;

m = 1;
for (i=0; i<3; i++) {
if (m < abs(c[i])) m = abs(c[i]);
}

for (i=0; i<3; i++) {
c1[i] = 0;
d[i] = 1.0 * c[i] / m;
c2[i] = 0;
}

flg = false;
for (i=0; i<3; i++) {
if (abs(c1[i]) < abs(c[i])) flg=true;
}
while (flg) {
flg=false;
for (i=0; i<3; i++) {
 if (abs(c1[i]) < abs(c[i]))
 c1[i] += d[i];
 if (abs(c1[i]) - abs(c2[i]) >= 0.5) {
 if (c[i]>0) {
 c2[i]++;
 moveForward(i);
 } else {
 c2[i]--;
 moveBackward(i);
 }
 }
 if (abs(c1[i]) < abs(c[i])) flg=true;
}
delayMicros(delayTime);
}
}

//Основной цикл
void loop() {
if (Serial.available() > 0) { //Пришла команда
long c[4]={0,0,0,0};
int i;
sign=1;
i=0;
incomingByte = Serial.read();
while (incomingByte!=';') { //Читаем входящую строку, признак конца строки знак "точка с запятой"
if (c[i]==0) {
if (incomingByte=='-')
 sign=-1;
}
if (incomingByte==',') {
c[i]*=sign;
sign=1;
i++;
} else if (incomingByte>='0' && incomingByte<='9') {
c[i]=c[i]*10+incomingByte-'0';
}
while (Serial.available() == 0) {
delayMicroseconds(1); //Ждём очередной символ, если не пришел
}
incomingByte = Serial.read();
}
c[i]*=sign;
if (c[3]>0) delayTime=c[3];
MoveSM(c[0],c[1],c[2]); //Вращаем двигатели на заданное число шагов
Serial.println("OK"); //Отправляем компьютеру сообщение "OK", значит можно высылать новую команду
}
else
delayMicroseconds(1); //Если ничего не пришло, ждём 1 микросекуду.
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ага, вот посмотрите. Они в строках 26-28 дёргают двигатесь на шаг.

Вы же в аналогичной ситуации делаете задержку - строки 19-21 нашего скетча.

Разница в том, что у них задержки (наша строка 20) нет. Вместо этого они делают единую задержку после "многократных дёргов" обоих двигателей в строке 92.

Вы можете объяснить для чего эта задержка? Она нам сильно нужна? Или можно без неё, но просто большее количество раз дёргать? Честно говоря, я как раз над ней думал, она сильно мешает и ради неё придётся "ногой до уха доставать". Если она Вам нужна. чтобы знать сколько именно проехал мотор, то может это сделать по-другому?

Попробуйте убрать (закомментировать) задержку в строке 20 и скажите, как получается. Должно быть более плавное движение по дигонали, а не рыскание то по одной оси, то по другой. Получается?

 

everlast
Offline
Зарегистрирован: 29.10.2015
//delayMicroseconds(speedMotor);

Закоментировал эту строку в нашем скетче. Стало дергаться сильно. А если раскоментировать, то нет.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тогда попробуйте вот так и скажите что получится.

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

class Motor {
public:
	Motor(const int8_t dirPin, const int8_t stepPin, const char * motorName) {
    	m_dirPin = dirPin;
    	m_stepPin = stepPin;
    	pinMode(m_dirPin, OUTPUT);
		pinMode(m_stepPin, OUTPUT);
		m_stepsToDo = 0;
		m_direction = LOW;
		m_Name = (char *) motorName;
	}

	void doOneStep(void) {
		if (! m_stepsToDo) return;
		m_stepsToDo--;
		digitalWrite(m_dirPin, m_direction);
		digitalWrite(m_stepPin, HIGH);
	}
	void finishOneStep(void) {
		digitalWrite(m_stepPin, LOW);
	}
	inline void SetSteps (const int steps) { m_stepsToDo = (m_direction = (steps > 0)) ? steps : -steps; }
private:
	static int speedMotor; 
	int8_t m_dirPin, m_stepPin, m_direction;
	int m_stepsToDo;
	char * m_Name;
};

char *sm1 = "X motor", *sm2 = "Y motor";
int Motor::speedMotor = 2000;

Motor motors[2] = { Motor(5, 2, sm1), Motor(6, 3, sm2) };

void setup() {
	Serial.begin(115200);
        pinMode(8, OUTPUT);
}

const bool readCommand(int &steps, int &motor) {
	static char commandBuffer[16] = {0};
	static int8_t ptr = 0;
	static const int8_t BufferSize = sizeof(commandBuffer)/sizeof(commandBuffer[1]) - 1;
	char symbol = 0;
	while (Serial.available() && ptr < BufferSize) {
		symbol = Serial.read();
		if (symbol == '\n') break;
		commandBuffer[ptr++] = symbol;
	}
	if (ptr == BufferSize) {
		ptr = 0;
		motor = -1;
		Serial << "Input buffer OVERFLOW\n";
		return true;
	}
	if (symbol != '\n') return false;
	commandBuffer[ptr] = 0;
	Serial << "Command read: \"" << commandBuffer << "\"\n";
	sscanf(commandBuffer, "%d %d", &motor, &steps);
	ptr = 0;
	return true;
}

void loop () {
	motors[0].doOneStep();
	motors[1].doOneStep();
	delayMicroseconds(2000);
	motors[0].finishOneStep();
	motors[1].finishOneStep();
	delayMicroseconds(2000);
	int steps, motor;
	if (! readCommand(steps, motor)) return;
	if (motor < 0 || motor > 2) {
		Serial << "Command not recognized\n";
	} else if (motor == 0) {
		motors[0].SetSteps(steps);
		motors[1].SetSteps(steps);
	} else {
		motors[motor-1].SetSteps(steps);
	}
}

 

everlast
Offline
Зарегистрирован: 29.10.2015

Да, явно лучше.Не чувствуются шаги.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, теперь скажите нам пора переходить к кнопкам или мы ещё будем движение улучшать.

К кнопкам переходим тогда, когда движение нам нравится и больше мы его менять не хотим. Поэспериментируйте и скажите. Если хотим, что чего хотим добиться.

everlast
Offline
Зарегистрирован: 29.10.2015

Andy пишет:

До интерполяции не дотягивает.

Было красным, стало синим. Интерполяция зеленым. Почему бы не включать моторы одновременно - будет движение по диагонали.

Получается мне нужно как на рисунке зелёным. А сейчас получается что красным или синим. Еще получается нужно команду 0 200 500, чтобы платфрма ехала по прямоугольнику, а то 0 500 или 0 200 получается по квадрату, а нужно попадать в любую точку XY плоскости. Как я понял, к примеру, мы задаём 0 3 500, по X он едет 3, а по Y 500 т.е. он делает так: X-мотор проезжает 1 шаг , Y-мотор  165 шагов, и так три раз. И видимо остальные шаги по Y(165*3=495, 500-495=5) т.е. 5 шагов он доделывает сам.

А сейчас получается так если я задам 0 3 500, то получится так: по X сделает сразу 3 шага, а по Y будет крутить 500. 

vladimir62
vladimir62 аватар
Offline
Зарегистрирован: 10.11.2015

ЕвгениюП, с удовольствием читаю ваши этюды, хотя это требует усилий. Я хотел бы обратить внимание, что шаговый двигатель не просто "штучка" в которую через пины забиваются "единички" и "нули". Это сложное устройство, теорию ШД я вам не предлагаю читать, но думаю, что в силу вашей профессии вы ознакомитесь с материлом на http://avrdoc.narod.ru/index/0-7. А  может и Everlast почитает.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

everlast пишет:

Получается мне нужно как на рисунке зелёным. А сейчас получается что красным или синим. 

Знаете, я тут сильно напрягся, даже попытался раздобыть движки для пробы. Дело в том, я ожидал что сейчас они будут ехать по диагонали. Пусть рывками, но по диагонали. Если это не так, то, боюсь, я что заочно мне это не отладить, а движков у меня нет. Извините, похоже я переоценил возможности заочной отладки. Простите.

everlast
Offline
Зарегистрирован: 29.10.2015

ЕвгенийП 

Ничего страшного. Вы мне и так очень сильно помогли! А по поводу движения. Они движуться. Только, как я писал, при 0 500 или 0 2000 и т.д.(они движуться по квадрату). А у меня должна быть возможность попасть в любую точку плоскости XY c тем движением моторов, как описано мною выше.

Спасибо за то, что откликнулись и помогли мне в решении данной проблемы!