Здравствуйте уважаемые форумчане.
Сразу скажу, что в программировании контроллеров я не силён, но очень хочу освоить это не лёгкое дело .
Опишу задачу, которую пока не могу решить без вашего совета:
1.Вводные данные.
Есть каретка, которая перемещается на линейных направляющих при помощи ШД и швп. Присутствует 5 кнопок управления и 1 концевой выключатель. Также есть ещё 2 аварийных концевика, которые физически отключают питание от ШД, но в скетче не участвуют.
Логика работы должна быть такая:
1.1При включении системы каретка едет в направлении концевого выключателя до тех пор, пока в него не упрётся.
1.2 Срабатывание концевика определяет нулевую координату и отводит каретку от концевика до его размыкания.
1.3 С этого момента каретка ориентирована и кнопками управления её можно отправить в различные координаты либо вручную двигать вперед-назад.
Контроллер arduino UNO
Драйвер ШД - dm860h (промышленный).
Концевик нормально разомкнутый.
-
Суть проблемы.
Программу переписывал множество раз. Уверен, что присутствуют какие то нелепые куски от старых кодов и комментарии для удобства, которые можно исключить.
Во время написания каждый раз проверяю скетч на эмуляторе с сайта https://wokwi.com/
На нём всё прекрасно работает. В реале получается следующее:
2.1 Каретка упирается в концевик и возвращается назад на 10000 шагов.
(иногда она почему то мгновенно зависает при срабатывании концевика и залипает в таком положении, не начав возврат. На сколько я понимаю т.к. работает аппаратное прерывание - никакие кнопки не работают и снимать каретку с концевика приходится вручную отключив питание).
2.2. Когда каретка производит возврат то происходит мгновенная пауза после размыкания концевика и ещё один возврат на 10000 шагов…
(иногда этого не происходит при размыкании концевика. Т.е. концевик сработал - каретка вернулась на 10000 шагов разомкнув концевик и всё ОК и повторного возврата нет).
3.3 Также есть проблема “перебегания” концевика, если каретка успевает разогнаться, находясь далеко при подачи питания. Поэтому из 2000 шагов откат назад после замыкания концевика превратился в 10тыс шагов, чтобы каретка гарантированно отъехала и разомкнула концевик. Это влияет на точность установки нуля. -
Вопрос
Для моих задач такого скетча в целом достаточно и точность нуля в ±3мм и не частые залипания на концевике, но хочу сделать так как я ХОЧУ, а не как получилось .
Хотелось бы реализовать плавное касание концевика.
Т.е. включаем питание:
-каретка летит в концевик
-он срабатывает,
-каретка отъезжает обратно на определенное число шагов (чуть дальше гарантированного размыкания концевика)
-устанавливается низкая скорость вращения мотора и он опять едет к концевику но уже медленно (исключить перебег)
-концевик срабатывает
-мотор отъезжает чуть чуть дальше “размыания концевика”
- активно управление кнопками.
Просьба бить сильно, чтобы лучше дошло =) .
Заранее спасибо.
#include <AccelStepper.h>
AccelStepper stepper(1, 13, 12); //DRIVER, step, direction
boolean initZero;
void setup(){
Serial.begin(9600);
initZero = true; // установили флаг
attachInterrupt(0, setZero, !LOW); //(0 - номер прерывания (int) для UNO это D2, setZero - функция обработчик прерывания, !LOW - режим работы "прерывание будет срабатывать всякий раз, когда на выводе присутствует низкий уровень сигнала" )
pinMode(A0, INPUT_PULLUP); //против часовой
pinMode(A1, INPUT_PULLUP); //по часовой
pinMode(A2, INPUT_PULLUP); //координата 1 (ПМ)
pinMode(A3, INPUT_PULLUP); //координата 2 (ТС)
pinMode(A4, INPUT_PULLUP); //вернуться в 0 (не налажено)
pinMode(2, INPUT_PULLUP); //Концевик
}
long pastTime = 0;
volatile uint32_t debounce;
void setZero(){
if (millis() - debounce >= 100 && !digitalRead(2)) { // D2 сигнал концевика
debounce = millis();
initZero = false; //Отменить возвращение домой при включении контроллера
stepper.setAcceleration(5000);
stepper.setCurrentPosition(0);
stepper.moveTo(-10000);
stepper.run();
// ваш код по прерыванию по высокому сигналу
}
}
void loop(){
bool push = !digitalRead(A0); //назначаем кнопку(по часовой) на выход A0
bool push1 = !digitalRead(A1); //назначаем кнопку(против часовой) на выход A1
bool goToCoordinatePM = !digitalRead(A2); //назначаем кнопку(ехать в ПМ) на выход A2
bool goToCoordinateTC = !digitalRead(A3); //назначаем кнопку(ехать в ТС) на выход A3
bool goToZero = !digitalRead(A4); //назначаем кнопку(найти 0) на выход A4
if (initZero == 1){ //Возвращение домой при включении контроллера
stepper.setMaxSpeed(3000);
stepper.setAcceleration(400);
stepper.setSpeed(510);
stepper.runToNewPosition(999000);
stepper.run();
}
for(bool x=!digitalRead(A0); x == 1; x=!digitalRead(A0)){
for (float s=1; s > -1; s=s+0.01){
stepper.setMaxSpeed(-7000);
stepper.setSpeed(-1000-s);
stepper.runSpeed();
if (!digitalRead(A0) == 0) break;
}
}
for(bool x=!digitalRead(A1); x == 1; x=!digitalRead(A1)){
for (float v=1; v > -1; v=v+0.01){
stepper.setMaxSpeed(7000);
stepper.setSpeed(1000+v);
stepper.runSpeed();
if (!digitalRead(A1) == 0) break;
}
}
if (goToCoordinatePM == 1){
stepper.setMaxSpeed(7000);
stepper.setAcceleration(500);
stepper.setSpeed(510);
stepper.runToNewPosition(-74000); //координата для ПМ
stepper.run();
}
if (goToCoordinateTC == 1){ // 665 формат
stepper.setMaxSpeed(7000);
stepper.setAcceleration(500);
stepper.setSpeed(510);
stepper.runToNewPosition(-630000); //координата для ТС
stepper.run();
}
if (goToZero == 1){
stepper.setMaxSpeed(5000);
stepper.setSpeed(510);
stepper.runToNewPosition(990000);
stepper.run();
}
Serial.println("Sensors value is: ");
Serial.print("ПМ\t\t");
Serial.println(analogRead(A2), DEC);
Serial.print("TC\t\t");
Serial.println(analogRead(A3));
Serial.print("KOHCEBUK\t\0");
Serial.println(digitalRead(2));
Serial.println("--------");
}