Помогите с управлением шаговиками.
- Войдите на сайт для отправки комментариев
Вс, 24/09/2017 - 20:41
Несколько дней бьюсь, но выхлопа ноль. Хочу управлять тремя шаговиками одновременно. Двигатели 17HS4401. Стандартные для CNC. Пробовал через библиотеку AccelStepper - вообще не крутится шаговик. Если подключать к ней MultiStepper, то работает, но я не знаю как регулировать в ней скорость вращения. Пробовал через такой код: http://www.ecnc.ru/flash/l298n_mill , но тогда двигатель крутится в разные стороны. При чём не понятен алгоритм стороны. При одинаковых "коммандах" (типа крутанутся на 200 шагов по часовой) может три раза крутится по часовой, потом один раз против, потом опять по часовой и т.д.
Подскажите чем можно управлять ОДНОВРЕМЕННО тремя двигателями!
Если собираете ЧПУ на ардуине, то "копайте" сразу в сторону GBRL.
Про GRBL в курсе. Но хочу своё.
#include <AccelStepper.h> #include <MultiStepper.h> AccelStepper stepper1(AccelStepper::FULL4WIRE, 40, 42, 44, 46); AccelStepper stepper2(AccelStepper::FULL4WIRE, 22, 24, 26, 28); MultiStepper steppers; void setup() { stepper1.setMaxSpeed(200); stepper2.setMaxSpeed(200); steppers.addStepper(stepper1); steppers.addStepper(stepper2); } void loop() { long positions[2]; positions[0] = s1; positions[1] = 50; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); // Move to a different coordinate positions[0] = s2; positions[1] = 100; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); }Вот так работает. s1, s2, s3 - задаю через COM порт. НО s3 должна задавать скорость вращения, однако скорость не меняется. Может я не правильно задаю? Может не stepper1.setSpeed(s3);?
#include <AccelStepper.h> #include <MultiStepper.h> AccelStepper stepper1(AccelStepper::FULL4WIRE, 40, 42, 44, 46); AccelStepper stepper2(AccelStepper::FULL4WIRE, 22, 24, 26, 28); MultiStepper steppers; void setup() { stepper1.setMaxSpeed(200); stepper2.setMaxSpeed(200); steppers.addStepper(stepper1); steppers.addStepper(stepper2); } void loop() { long positions[2]; positions[0] = s1; positions[1] = 50; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); // Move to a different coordinate positions[0] = s2; positions[1] = 100; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); }Вот так работает. s1, s2, s3 - задаю через COM порт. НО s3 должна задавать скорость вращения, однако скорость не меняется. Может я не правильно задаю? Может не stepper1.setSpeed(s3);?
Зачем там вообще символ s? Где принимаются значения через порт?
Пробовал через такой код: http://www.ecnc.ru/flash/l298n_mill ,
Там в функции moveDir в switch по моему неправильная очерёдность дрыганья пинами.
Высокий уровень на пинах должен смещаться при каждом шаге, как бы волной, а там непонятно как.
Попробуйте заменить switch на:
switch (count2[sm]) { case 1: digitalWrite(motorPins[sm][0],HIGH); digitalWrite(motorPins[sm][1],LOW); digitalWrite(motorPins[sm][2],LOW); digitalWrite(motorPins[sm][3],LOW); break; case 2: digitalWrite(motorPins[sm][0],LOW); digitalWrite(motorPins[sm][1],HIGH); digitalWrite(motorPins[sm][2],LOW); digitalWrite(motorPins[sm][3],LOW); break; case 3: digitalWrite(motorPins[sm][0],LOW); digitalWrite(motorPins[sm][1],LOW); digitalWrite(motorPins[sm][2],HIGH); digitalWrite(motorPins[sm][3],LOW); break; case 4: digitalWrite(motorPins[sm][0],LOW); digitalWrite(motorPins[sm][1],LOW); digitalWrite(motorPins[sm][2],LOW); digitalWrite(motorPins[sm][3],HIGH); break; }Зачем там вообще символ s? Где принимаются значения через порт?
Я код не полный выложил. Но если надо:
#include <string.h> #include <AccelStepper.h> #include <MultiStepper.h> AccelStepper stepper1(AccelStepper::FULL4WIRE, 40, 42, 44, 46); AccelStepper stepper2(AccelStepper::FULL4WIRE, 22, 24, 26, 28); MultiStepper steppers; //int startPosH = 0; //int startPosV = 0; //long runtime = 0; //float SpeedH = 0; //float SpeedV = 0; /*int motorPins[3][4] = {{40, 42, 44, 46},{22, 24, 26, 28},{30, 32, 34, 36}}; int count; int count2[3] = {0,0,0}; int val = 0; int rot=0; int incomingByte = 0; int sign=1; long delayTime;*/ int brightness = 0; // яркость светодиода int fadeAmount = 1; // шаг изменения яркости int Relay = 23; //Реле на включение блока питания int Mosfet = 7; //Mosfet на фрезу int ULN1 = 25; //ULS2003A int ULN2 = 29; //ULS2003A int ULN3 = 31; //ULS2003A int ULN4 = 33; //ULS2003A //const int koncevikx = 27; int r = 11; int g = 12; int b = 10; int enterprog = 0; //Переменная для подключения программы (0 - не подключена, 1 - подключилась) int enterscreen = 0; //Переменная для главного экрана программы (0 - другой экран, 1 - главный экран) int shimfreza = 255; //Переменная для ШИМ фрезы % int freza = 0; //Включена ли фреза int error = 0; //Переменная для "ошибка" int errorr = 1; //Включаем при ошибке красный int errorb = 0; //Включаем при ошибке синий // buttonState = 0; char buffer[50]; long s1, s2, s3, s4, s5; String inString = ""; void setup() { // put your setup code here, to run once: pinMode(Relay, OUTPUT); digitalWrite(Relay, HIGH); pinMode(Mosfet, OUTPUT); pinMode(ULN1, OUTPUT); pinMode(ULN2, OUTPUT); pinMode(ULN3, OUTPUT); pinMode(ULN4, OUTPUT); pinMode(r, OUTPUT); pinMode(g, OUTPUT); pinMode(b, OUTPUT); //pinMode(koncevikx, INPUT); //digitalWrite(Relay, LOW); // реле ключено Serial.begin(9600); stepper1.setMaxSpeed(200); stepper2.setMaxSpeed(200); // stepper2.setMaxSpeed(200); steppers.addStepper(stepper1); steppers.addStepper(stepper2); /*int i; pinMode(22, OUTPUT); pinMode(24, OUTPUT); pinMode(26, OUTPUT); pinMode(28, OUTPUT); pinMode(30, OUTPUT); pinMode(32, OUTPUT); pinMode(34, OUTPUT); pinMode(36, OUTPUT); pinMode(40, OUTPUT); pinMode(42, OUTPUT); pinMode(44, OUTPUT); pinMode(46, OUTPUT); delayTime=2000;*/ } //Поворот двигателя с номерм sm на один шаг вперёд в направлении st (-1 или 1) /*void moveDir(int sm, int st) { if ((st==1 ) && (count2[sm]) == 4) count2[sm] = 0; if ((st==-1) && (count2[sm]) == 1) count2[sm] = 5; count2[sm]+=st; switch (count2[sm]) { case 1: digitalWrite(motorPins[sm][0],HIGH); digitalWrite(motorPins[sm][1],LOW); digitalWrite(motorPins[sm][2],HIGH); digitalWrite(motorPins[sm][3],LOW); break; case 2: digitalWrite(motorPins[sm][0],LOW); digitalWrite(motorPins[sm][1],HIGH); digitalWrite(motorPins[sm][2],HIGH); digitalWrite(motorPins[sm][3],LOW); break; case 3: digitalWrite(motorPins[sm][0],LOW); digitalWrite(motorPins[sm][1],HIGH); digitalWrite(motorPins[sm][2],LOW); digitalWrite(motorPins[sm][3],HIGH); break; case 4: digitalWrite(motorPins[sm][0],HIGH); digitalWrite(motorPins[sm][1],LOW); digitalWrite(motorPins[sm][2],LOW); digitalWrite(motorPins[sm][3],HIGH); break; } } //Поворот двигателя с номерм sm на один шаг вперёд void moveForward(int sm) { moveDir(sm,1); } //Поворот двигателя с номерм sm на один шаг назад void moveBackward(int sm) { moveDir(sm,-1); } //Задержка в микосекундах 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 if (c[i]<0) { c2[i]--; moveBackward(i); } } if (abs(c1[i]) < abs(c[i])) flg=true; } delayMicros(delayTime); } }*/ void loop() { // put your main code here, to run repeatedly: long positions[2]; unsigned long currentMillis = millis(); if (error == 1) { if (errorr == 1) { analogWrite(r, brightness); } if (errorb == 1) { analogWrite(b, brightness); } //analogWrite(g, brightness); //analogWrite(b, brightness); brightness = brightness + fadeAmount; // прибавляем шаг изменения яркости, которая установится в следующем цикле if (brightness == 0|| brightness == 255) { // Условие fadeAmount = -fadeAmount ; // Меняем знак if (brightness == 0 && errorr == 1) { errorr = 0; errorb = 1; brightness = 1; } if (brightness == 0 && errorb == 1) { errorb = 0; errorr = 1; } } delay(1); } if (enterprog == 0) { analogWrite(r, brightness); analogWrite(g, brightness); analogWrite(b, brightness); brightness = brightness + fadeAmount; // прибавляем шаг изменения яркости, которая установится в следующем цикле if (brightness == 0|| brightness == 255) { // Условие fadeAmount = -fadeAmount ; // Меняем знак } delay(1); } if (enterscreen == 1) { digitalWrite(g, HIGH); } if(digitalRead(27)==HIGH)//если кнопка нажата ... { digitalWrite(ULN1, LOW); } //else//если не нажата... //{ //digitalWrite(13,LOW);//выключаем //} while (Serial.available() > 0) { int inChar = Serial.read(); inString += (char)inChar; if (inChar == ';') { //Serial.print("String: "); //Serial.println(inString); if (inString == "r1;") { digitalWrite(r, HIGH); enterscreen = 0; Serial.println("Red-ON"); } if (inString == "r0;") { digitalWrite(r, LOW); enterscreen = 0; Serial.println("Red-OFF"); } if (inString == "g1;") { digitalWrite(g, HIGH); enterscreen = 0; Serial.println("Green-ON"); } if (inString == "g0;") { digitalWrite(g, LOW); enterscreen = 0; Serial.println("Green-OFF"); } if (inString == "b1;") { digitalWrite(b, HIGH); enterscreen = 0; Serial.println("Blue-ON"); } if (inString == "b0;") { digitalWrite(b, LOW); enterscreen = 0; Serial.println("Blue-OFF"); } if (inString == "rel1;") { digitalWrite(Relay, LOW); enterscreen = 0; Serial.println("Rele_12v-ON"); } if (inString == "rel0;") { digitalWrite(Relay, HIGH); enterscreen = 0; Serial.println("Rele_12v-OFF"); } if (inString == "error1;") { error = 1; enterscreen = 0; digitalWrite(r, LOW); digitalWrite(g, LOW); digitalWrite(b, LOW); Serial.println("Error-ON"); } if (inString == "error0;") { error = 0; enterscreen = 0; digitalWrite(r, LOW); digitalWrite(b, LOW); digitalWrite(g, HIGH); Serial.println("Error-OFF"); } if (inString == "mos1;") { analogWrite(Mosfet, shimfreza); //Включаем фрезу freza = 1; digitalWrite(r, HIGH); digitalWrite(g, LOW); digitalWrite(b, LOW); Serial.println("Freza-ON"); } if (inString == "mos0;") { analogWrite(Mosfet, 0); //Выключаем фрезу freza = 0; digitalWrite(r, LOW); digitalWrite(g, HIGH); digitalWrite(b, LOW); Serial.println("Freza-OFF"); } if (inString == "uln11;") { digitalWrite(ULN1, HIGH); Serial.println("ULN_1-ON"); } if (inString == "uln10;") { digitalWrite(ULN1, LOW); Serial.println("ULN_1-OFF"); } if (inString == "uln21;") { digitalWrite(ULN2, HIGH); Serial.println("ULN_2-ON"); } if (inString == "uln20;") { digitalWrite(ULN2, LOW); Serial.println("ULN_2-OFF"); } if (inString == "uln31;") { digitalWrite(ULN3, HIGH); Serial.println("ULN_3-ON"); } if (inString == "uln30;") { digitalWrite(ULN3, LOW); Serial.println("ULN_3-OFF"); } if (inString == "uln41;") { digitalWrite(ULN4, HIGH); Serial.println("ULN_4-ON"); } if (inString == "uln40;") { digitalWrite(ULN4, LOW); Serial.println("ULN_4-OFF"); } if (inString == "enterprog;") { //Программа подключена digitalWrite(r, LOW); digitalWrite(g, LOW); digitalWrite(b, LOW); enterprog = 1; enterscreen = 1; Serial.println("SsPUSK A4-2 ENTER"); } if (inString == "exitprog;") { //Выход из программы digitalWrite(r, LOW); digitalWrite(g, LOW); digitalWrite(b, LOW); enterprog = 0; enterscreen = 0; Serial.println("SsPUSK A4-2 EXIT"); } inString.toCharArray(buffer,50); s1=atol(strtok(buffer," ")); s2=atol(strtok(NULL," ")); s3=atol(strtok(NULL," ")); s4=atol(strtok(NULL," ")); s5=atol(strtok(NULL," ")); //Serial.println(s1); //Serial.println(s2); //Serial.println(s3); //Serial.println(s4); //Serial.println(s5); if (s4 == 45) { //Установка ШИМ для фрезы shimfreza = map(s5, 0, 100, 0, 255); //На входе 0-100% на выходе от 0 до 255 Serial.print("Shim-"); Serial.println(s5); //shimfreza = s5; if (freza == 1) { analogWrite(Mosfet, shimfreza); //Если фреза включена, то меняем скорость } } if (s4 == 55) { // /*long c[4]={0,0,0,0}; c[0] = s1; c[1] = s2; c[2] = s3; MoveSM(c[0],c[1],c[2]); //Вращаем двигатели на заданное число шагов Serial.println("OK"); //Отправляем компьютеру сообщение "OK", значит можно высылать новую команду*/ positions[0] = s1; positions[1] = 50; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); // Move to a different coordinate positions[0] = s2; positions[1] = 100; stepper1.setSpeed(s3); stepper1.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position delay(1000); stepper1.setCurrentPosition(0); } if (s4 == 56) { // //startPosH = 200; //startPosV = 3000; //runtime = 60; //SpeedH = 0; //SpeedV = 0; //SpeedH = startPosH / runtime; //SpeedV = startPosV / runtime; //stepper1.moveTo(startPosH); //stepper1.setSpeed(SpeedH); //stepper2.moveTo(startPosV); //stepper2.setSpeed(SpeedV); //stepper1.run(); //stepper2.run(); } if (s4 == 57) { // //stepper1.setSpeed(200); //stepper1.move(100); //stepper1.runSpeed(); } if (s4 == 58) { // //stepper1.setSpeed(100); //stepper1.move(-1100); //stepper1.runSpeed(); } inString = ""; } } }Там в функции moveDir в switch по моему неправильная очерёдность дрыганья пинами.
Высокий уровень на пинах должен смещаться при каждом шаге, как бы волной, а там непонятно как.
Я уже вроде как на MultiStepper настроился. Осталось только скорость вращения сделать. На крайняк буду двигать по 0,1 мм. с задержками... Но как-то же должна скорость меняться...
Раньше был подключен только один двигатель. Сейчас подключил два и интересная картина получилась. Даю команду на перемещение 2000 шагов первый и 100 шагов второй одновременно. Всё нормально. Даю 100 шагов первый и 2000 шагов второй - второй отрабатывает, а перевый только дёргается и не крутится. Плохой контакт? Или что?
Вообще какая-то ерунда с первым двигателем. Отправляю несколько комманд на перемещение по 200 шагов на каждый двигатель - второй нормально отрабатывает, а первый крутится то по часовой, то против. При чём не через раз, а как когда...
Путём экспериментов понял, что скорее всего виноват драйвер. При первом подключении был слишком большой ток. Первый я вообще спалил, и этот видать подпалился. Второй двигатель (с нормальным драйвером) работает на ура. Путём эксперимента:
positions[0] = s1; positions[1] = s2 * -1; Serial.print(s1); Serial.print(" "); Serial.print(s2); Serial.print(" "); Serial.print(s3); Serial.println(" "); stepper2.setMaxSpeed(s3); stepper1.setCurrentPosition(0); stepper2.setCurrentPosition(0); steppers.moveTo(positions); steppers.runSpeedToPosition(); // Blocks until all are in position //delay(1000); stepper1.setCurrentPosition(0); stepper2.setCurrentPosition(0);получил вращение до 750 оборотов. При этом движок ооочень быстро крутит.
P.S. Пишу для того, чтоб - может кому надо и пригодится.
получил вращение до 750 оборотов. При этом движок ооочень быстро крутит.
это вы загнули))))
погуглите о высокой скорости шагового двигателя и как её доститчь.
с библиотекой аксельстепер больших скоростей вообще не получить.
Ну сам бы не увидел - не писал бы.
Вот видео где шаговик обрабатывает 5000 шагов с setMaxSpeed(750);
https://drive.google.com/open?id=0B0TPUtGNof7eVFNfTVVnY2FYcVE
А здесь с setMaxSpeed(200);
https://drive.google.com/open?id=0B0TPUtGNof7eaS1iVGRYOE12YUU
setMaxSpeed(200); это 200 шагов в сек, 1 оборот в секунду получается.
Ну раздницу видите. При 200 шагов и 750.
А крутящий момент в обоих случаях вас устраивает?
Пока не знаю. Всё только на макетке. Но судя по амперам - раздницы нет. Как соберу станок - видно будет.