работа шагового двигателя в циклах программы
- Войдите на сайт для отправки комментариев
Чт, 06/09/2018 - 18:07
Добрый день. Пытаюсь сделать на базе ардуино небольшую технологическую оснастку.
Есть монитор, матричная клавиатура, пару реле и шаговый двигатель с драйвером.
Никак не могу заставить нормально работать шаговый двигатель в данной программе. (самые нижние сточки в цикле void DVIGATEL). В результате запуска получается непонятное подергивание вала двигателя. Если делать пустой код и пробовать крутить вал, то все хорошо. По этому предполагаю, что проблемы именно в остальной части кода, но причина мне не ясна. Прошу помощи у опытных пользователей.
Так же готов выслушать любые другие советы по коду, так как опыта нет особо.
#include <AccelStepper.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <Keypad.h> // создаем объект-экран, передаём используемый адрес // и разрешение экрана: LiquidCrystal_I2C lcd(0x38, 16, 2); // Назначение клавиш клавиатуры const byte ROWS = 4; const byte COLS = 3; // char keys[ROWS][COLS] = { char keys[ROWS][COLS] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}, {'*', '0', '#'} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // пины 1-4 кнопок byte colPins[COLS] = {10, A0, 13}; // пины 5-7 кнопок Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); int n1 = 0; int n2 = 0; int Nst; int l1 = 0; int l2 = 0; int l3 = 0; int Lmm = 0; int NUMB = 0; int x = 0; int START = 0; int DEL_TIME = 50; //int RELE = 12; int STEP = 9; int DIR = 12; AccelStepper mystepper(1, STEP, DIR); void setup() { Serial.begin(9600); // инициализируем экран lcd.init(); // включаем подсветку lcd.backlight(); lcd.setCursor(0, 0); // печатаем первую строку lcd.print("KO"); lcd.setCursor(2, 0); lcd.write(0xA7); lcd.setCursor(3, 0); lcd.print("-BO"); delay (300); lcd.setCursor(7, 0); lcd.write(0xC9); delay (300); lcd.setCursor(13, 0); lcd.write(0xC1); lcd.setCursor(14, 0); lcd.write(0xBF); delay (300); // устанавливxаем курсор в колонку 0, строку 1 lcd.setCursor(0, 1); // печатаем вторую строку lcd.print("PA3MEP"); delay (300); lcd.setCursor(7, 1); lcd.write(0xC9); lcd.setCursor(13, 1); delay (300); lcd.print("mm"); delay (500); keypad.setHoldTime(2500); // задержка нажатия // механическое реле // pinMode (RELE, OUTPUT); } void loop() { // Отображение значений в СОМ порт char key = keypad.getKey(); Serial.print ("n1 = "); Serial.print (n1); Serial.print (" n2 = "); Serial.print (n2); Serial.print (" | "); Serial.print (" l1 = "); Serial.print (l1); Serial.print (" l2 = "); Serial.print (l2); Serial.print (" l3 = "); Serial.print (l3); Serial.print (" | "); Serial.print (" | "); Serial.print (" Nst:"); Serial.print (Nst); Serial.print (" Lmm:"); Serial.println (Lmm); // Serial.print (" NUMB:"); Serial.print (NUMB); // Serial.print (" START:"); Serial.println (START); // Отображение значений на экран LSD экрана lcd.setCursor(9, 0); lcd.print(n1); lcd.setCursor(10, 0); lcd.print(n2); lcd.setCursor(9, 1); lcd.print(l1); lcd.setCursor(10, 1); lcd.print(l2); lcd.setCursor(11, 1); lcd.print(l3); // Сброс значений для повторного ввода. if (key != NO_KEY) { switch (key) { case '*': n1 = 0; n2 = 0; l1 = 0; l2 = 0; l3 = 0; NUMB = -1; START = 0; break; } } // отработка нажатия ввода, назначение клавиш. if (key != NO_KEY && NUMB < 6) { NUMB++; switch (key) { case '1': x = 1; break; case '2': x = 2; break; case '3': x = 3; break; case '4': x = 4; break; case '5': x = 5; break; case '6': x = 6; break; case '7': x = 7; break; case '8': x = 8; break; case '9': x = 9; break; case '0': x = 0; break; } if (NUMB == 1) { n1 = x; } else if (NUMB == 2) { n2 = x; } else if (NUMB == 3) { l1 = x; } else if (NUMB == 4) { l2 = x; } else if (NUMB == 5) { l3 = x; } else { } } // Значение штук для отрезки Nst = (n1 * 10) + n2; // Значение размера для отрезки Lmm = l1 * 100 + l2 * 10 + l3; // Если значение введены и не равны "0", то при нажатии кнопки # происходит начало печати. if (Nst != 0 && Lmm != 0) { switch (key) { case '#': START = 1; break; } } if (START == 1) { DVIGATEL (); } } // --------------------------------------------------------------------------------------------------------- // Цикл отрезки заданных размеров // --------------------------------------------------------------------------------------------------------- void DVIGATEL () { mystepper.setMaxSpeed(300); mystepper.setSpeed(300); mystepper.moveTo(800); mystepper.run(); }
Непонятное - это как?
Вот у меня телефон, например, непонятное делает - сможете что-то посоветовать?
Непонятное - это как?
Вот у меня телефон, например, непонятное делает - сможете что-то посоветовать?
Как будто между управляющими сигналами появилось еще время. Толи что то ему мешает нормально работать, толи еще чего. Причем, частота вращения в этом коде в разы отличается от вращения в пустом коде, в котором я опысываю только работу двигателя.
Прошу помощи у опытных пользователей.
Вы это читали:
https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.h...
?
Попробуйте
while (!mystepper.run()) вместо mystepper.run()
в код не вникал, но сразу могу сказать - убрать Serial и дисплей обновлять только если изменился какой то отображаемый параметр.
в код не вникал, но сразу могу сказать - убрать Serial и дисплей обновлять только если изменился какой то отображаемый параметр.
А вывод данных как то влияет на работу системы? Тем более у меня же вывод данных отсутствует в цикле управления ШГ. В чем тут подвох? Поясните пожалуйста.
Прошу помощи у опытных пользователей.
Вы это читали:
https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.h...
?
Попробуйте
while (!mystepper.run()) вместо mystepper.run()
Если читать про run (), то там есть такая фраза "Вы должны называть это как можно чаще, но по крайней мере один раз за минимальный интервал времени, предпочтительно в вашем основном цикле. ".
Это трудности перевода, или что означает "Как можно чаще" ?
в код не вникал, но сразу могу сказать - убрать Serial и дисплей обновлять только если изменился какой то отображаемый параметр.
А вывод данных как то влияет на работу системы? Тем более у меня же вывод данных отсутствует в цикле управления ШГ. В чем тут подвох? Поясните пожалуйста.
выводить в каждом цикле loop информацию это просто бесполезная трата процессорной мощности.
поставьте переменную unsigned long в начале вывода и в конце посмотрите сколько микросекунд (или даже в вашем случае миллисекунд) тратиться на вывод, соотвественно даже реакция на клавиши будет не мгновенная.
в код не вникал, но сразу могу сказать - убрать Serial и дисплей обновлять только если изменился какой то отображаемый параметр.
А вывод данных как то влияет на работу системы? Тем более у меня же вывод данных отсутствует в цикле управления ШГ. В чем тут подвох? Поясните пожалуйста.
выводить в каждом цикле loop информацию это просто бесполезная трата процессорной мощности.
поставьте переменную unsigned long в начале вывода и в конце посмотрите сколько микросекунд (или даже в вашем случае миллисекунд) тратиться на вывод, соотвественно даже реакция на клавиши будет не мгновенная.
Пока опыта и знаний маловато, вот от этого такой и код)
Лучше сделать отдельную функцию для вывода данных и вызывать ее из цикла loop?
функцией однозначно
вывод нужно производить при изменении выводимых данных, т.е. изменили какое либо число кнопками - вывели информацию, поменяли другое число - опять вызвали функцию вывода данных в лог и на дисплей и т.д.
Если читать про run (), то там есть такая фраза "Вы должны называть это как можно чаще, но по крайней мере один раз за минимальный интервал времени, предпочтительно в вашем основном цикле. ".
Это трудности перевода, или что означает "Как можно чаще" ?
Вроде нормальный перевод, примерно это и написано.
А до фразы "Note that each call to run() will make at most one step, and then only when a step is due, based on the current speed and the time since the last step." Вы дочитали?
Суть там простая - либа дает step на драйвер каждые N ms после проверки в run() истек ли интервал задержки или еще нет. Если вы вызываете run реже, чем N, то STEP будет подаваться через промежутки, большие чем N ms.
Неравномерность хода определяется иными функциями, которые выполняются между вызовами run(). Поэтому - если вы вынесете свои рисования на дисплее в другую функцию или же они в любом случае (даже при однократном обновлении только с изменением выводимой информации) будут слишком долгие (более N ms) - той же равномерности, что и при пустом цикле добиться будет нельзя.
P.S. Я смотрю, что у вас еще и сам run() странно вызывается - в функции, которая при каждом запуске пересчитывает параметры хода. Это для чего вообще?
P.S. Я смотрю, что у вас еще и сам run() странно вызывается - в функции, которая при каждом запуске пересчитывает параметры хода. Это для чего вообще?
Может быть я конечно что то неправильно сделал, но идея была такая:
человек вводит на клавиатуре значения длины и количества, нажимает кнопку и двигатель отрабатывает их длину с введенным количеством повторений.
функцией однозначно
вывод нужно производить при изменении выводимых данных, т.е. изменили какое либо число кнопками - вывели информацию, поменяли другое число - опять вызвали функцию вывода данных в лог и на дисплей и т.д.
а как это описать условием?
примерно так?
n = 0;
x = вводимое число;
if (n != x) {
n=x;
Serial.println (n);
}
Что-то логаритм, который я увидел в вашем скетче от озвученной идеи... мягко говоря - отличается. Хотя, я и строке "
l3 = x;
" удивился, а потом только понял, что первый символ в переменной- "эль".строк 137..168 можно заменить на 1 строка. разделите 1 задача на функции