Помогите! Управление шаговым двигателем и использование millis()
- Войдите на сайт для отправки комментариев
Втр, 24/10/2017 - 12:00
Привет товарищи. Столкнулся со следующей проблеммой. Написал прогу для насоса жидкости на шаговом двигателе. Сначала написал все с использованием delay, так как небыло необходимости что то получать от контроллера во время выполнения. Работает по прерыванию.
Выставили колво жидкости, нажали кнопку и шаговик делает нужное количество шагов.
Все это прекрасно работает с использование delay для управления step dir, но с millis заставить работать не могу никак. Шаговик пищит и все. Ничего не понимаю. Помогите пожалуйста советами.
код с дилей
void stepp() //Функция одного шага вперед
{
digitalWrite(dir, Rotate);
digitalWrite(stp, HIGH);
delayMicroseconds(speedd);
digitalWrite(stp, LOW);
delayMicroseconds(speedd);
}
код с милис
void stepp() //Функция одного шага вперед
{
if(mil - time >= speedd);
{
time = mil;
}
stpvalue=!stpvalue;
digitalWrite(dir, Rotate);
digitalWrite(stp, stpvalue);
}
Код надо приводить поностью. Вот, чему у Вас равна переменна speedd в первом коде и чему во втором? Хрустального шара у меня нет.
Если они в обоих кода одинаковые, то ... Вас не смущает, что в первом коде задержка измеряется в микросекундах, а во втором в миллисекундах?
Принцип:
typedef enum {wait, start, stop, done} machineState; // состояния двигателя machineState state = wait; unsigned long timer; // таймер отсчёта времени void stepp() { switch(state) // смотрим состояния { case wait: // ждём начала работы { digitalWrite(dir, Rotate); // начинаем digitalWrite(stp, HIGH); timer = micros(); // запоминаем время начала state = start; // и статус - мы стартовали } break; case start: // двигатель крутится { if(micros() - timer > speedd) // если время вышло, то { digitalWrite(stp, LOW); // останавливаем двигатель state = stop; // запоминаем статус, что мы останавливаемся timer = micros(); // и время начала остановки } } break; case stop: // двигатель останавливается { if(micros() - timer > speedd) // если время вышло { state = done; // заканчиваем цикл } } break; case done: // ничего не делаем, двигатель ждёт нового вызова, когда нужно, например, по нажатию на кнопку { } break; } } void loop() { void stepp(); // обновляем состояние двигателя if(wantToStep) // надо шагать двигателем по-новой (например, нажата кнопка)? { if(state == done) // двигатель закончил цикл и сейчас стоит { stepp(); // можно шагать } } }Код надо приводить поностью. Вот, чему у Вас равна переменна speedd в первом коде и чему во втором? Хрустального шара у меня нет.
Если они в обоих кода одинаковые, то ... Вас не смущает, что в первом коде задержка измеряется в микросекундах, а во втором в миллисекундах?
Спасибо, я никогда не использовал switch case и не сталкивался с этим, но выглядит отлично, должно работать.
Есть одно но, в коде сделаны плавное ускорение и торможение двигателем. Вопрос тут именно по функции milis. Почему она не заменяет delay?
Есть одно но, в коде сделаны плавное ускорение и торможение двигателем.
Рад за вас :)
Вопрос тут именно по функции milis. Почему она не заменяет delay?
Потому что это разные функции, с разным предназначением: одна возвращает время в миллисекундах, прошедшее после подачи питания на дуню, вторая - реализует задержку выполнения программы на нужное время.
Спасибо, буду разбираться с конструкцией switch case.
Спасибо, буду разбираться с конструкцией switch case.
При чём тут конструкция switch/case? Можно написать, и не используя её - важен алгоритм, а не конструкции языка.
Сделал все тоже самое, но с micros(). Да и ставил скорость постоянную при использовании millis. Все тоже самое. Никаких изменений. Дело видимо не в этом. Читал у Америкосов они сделали у них вроде работает.
void singleStep() { if (curMillis - prevStepMillis >= millisBetweenSteps) { prevStepMillis += millisBetweenSteps; digitalWrite(stepPin, HIGH); digitalWrite(stepPin, LOW); } }Что не так происходит логически?
Функция Vipolnit выполняется по прерыванию, простой цикл n-шагов.
n-раз должна выполнится функция stepp? Проверяем, если время вышло выполняем. и так n-раз
void Vipolnit() for (int a = 0; a <= b; a++) stepp(); void stepp() { if(micros() - previosMicros >=200); { digitalWrite(dir, HIGH); digitalWrite(stp, HIGH); digitalWrite(stp, LOW); } }А вот так все пучком.
void Vipolnit() for (int a = 0; a <= b; a++) stepp(); void stepp() { digitalWrite(dir, HIGH); digitalWrite(stp, HIGH); digitalWrite(stp, LOW); delayMicroseconds(200); }Romanoff,
Вы не обижайтесь, но сейчас я буду сильно ругаться и обзываться! (впрочем, захотите обидеться - мне пофигу).
Вам, идиоту, уже писали
Код надо приводить полностью.
ну, и где??????????????????????????
Нет, выложить код нам в лом - мы лучше будем мозги засирать себе и людям, а после нескольких часов бесполезной писанины и потери времени, вдруг выясняется, что
Функция Vipolnit выполняется по прерыванию
Если бы Ваше ленивое величество соизволило бы выложить код полностью, как Вас просили, Вам бы ещё утром сказали бы, что не работает ни хрена millis в прерываниях от слова совсем. Она всегда возвращает одно и тоже значение! А delayMicroseconds - работает.
Понятно в чём проблема?
Теперь про решение. Вообще-то в прерывании такие вещи не делаются, но в качестве костыля попробуйте вставить
sei();
между строками 1 и 2.
И, да, пока не будет полного кода, я вообще больше не буду читать Ваши вопросы - это просто потеря времени, как было с прерыванием.
Мне не в лом. Просто мне стыдно там черт ногу сломит. Извините за то что туплю. Но был бы опытен, то не обращался бы за помощью.
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //Настройки насоса unsigned long time;//переменная времени boolean stpvalue = HIGH; int stp = 13; //13 пин к step int dir = 12; //12 пин к dir int a; //переменная для отсчета int b; //количество шагов int ml = 30; //количество жидкости int speedy = 200; //выставляемое значение скорости int speedd; int spd; int s = 600; //Начальная скорость при разгоне int startspd; int c = 400; //За сколько шагов до конца цикла сбрасывать скорость int PreStop; int j = 20; //защита от капель, шакгов назад int Rotate; int r; int RotateBack; //Меню int m = 6; //переменная для меню int p1 = LOW; //выбираем объем жидкости int p2 = LOW;//скорость насоса int p3 = LOW;//время разгона int p4 = LOW;//время торможения int p5 = LOW;//защита от капли int p6 = LOW;//направление вращения //Энкодер int pinA = 3; int pinAold = LOW; int pinNOW; int pinB = 4; int sw = 5; int swold = HIGH; boolean t = LOW; void setup() { Serial.begin(9600); lcd.begin(); lcd.clear(); pinMode(stp, OUTPUT); pinMode(dir, OUTPUT); pinMode(pinA, INPUT); pinMode(pinB, INPUT); pinMode(sw, INPUT); digitalWrite(11, HIGH); attachInterrupt(0, Nalit , LOW); digitalWrite(2, HIGH); } void loop() { //Энкодер и выбор меню if (p1 == 0 && p2 == 0 && p3 == 0 && p4 == 0 && p5 == 0 && p6 == 0) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { m--; lcd.clear(); } else { m++; lcd.clear(); } if (m > 6) { m = 0; } if (m < 0) { m = 6; } Serial.println(m); } pinAold = pinNOW; } //Главное меню и выбор настроек if (m == 0) { lcd.setCursor(0, 0); lcd.print("Vol"); lcd.setCursor(0, 1); lcd.print("Rot"); if (r == 1) { lcd.setCursor(4,1); lcd.print("Forward"); } if (r==0) { lcd.setCursor(4,1); lcd.print("Backward"); } lcd.setCursor(4, 0); lcd.print(ml); Serial.println("Main menu"); Serial.println(b); Serial.println(ml); } if (m == 1) { if(p1 == 0) { lcd.setCursor(1, 0); lcd.print("Volume liquid"); lcd.setCursor(1, 1); lcd.print(" "); Serial.println("Volume liquid"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p1++; lcd.clear(); } if (p1 > 1) { p1 = 0; } swold = digitalRead(sw); Serial.println(p1); if (p1 == 1)//подменю 1 (выбор объема тары) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { ml--; lcd.clear(); } else { ml++; lcd.clear(); } if (ml > 100) { ml = 100; } if (ml < 5) { ml = 5; } } Serial.println(ml); lcd.setCursor(7,1); lcd.print(ml); lcd.setCursor(7,0); lcd.print("ml"); pinAold = pinNOW; } } if (m==2)//меню выбора скорости { if (p2==0) { lcd.setCursor(5,0); lcd.print("Speed"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p2++; lcd.clear(); } if (p2 > 1) { p2 = 0; } swold = digitalRead(sw); Serial.println(p2); if (p2 == 1)//подменю 2 (выбор скорости) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { lcd.clear(); speedy=speedy +200; } else { lcd.clear(); speedy=speedy -200; } if (speedy > 2000) { speedy = 2000; } if (speedy < 200) { speedy = 200; } } Serial.println(spd); lcd.setCursor(5,0); lcd.print("Speed"); lcd.setCursor(5,1); lcd.print(spd); pinAold = pinNOW; } } if(m==3) { if (p3==0) { lcd.setCursor(2,0); lcd.print("Acceleration"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p3++; lcd.clear(); } if (p3 > 1) { p3 = 0; } swold = digitalRead(sw); Serial.println(p2); if (p3 == 1)//подменю 3 (выбор ускорения) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { s=s+200; lcd.clear(); } else { s=s -200; lcd.clear(); } if (s > 2000) { s = 2000; } if (s < 200) { s = 200; } } Serial.println(s); lcd.setCursor(2,0); lcd.print("Start speed"); lcd.setCursor(7,1); lcd.print(startspd); pinAold = pinNOW; } } if(m==4) { if (p4==0) { lcd.setCursor(4,0); lcd.print("Braking"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p4++; lcd.clear(); } if (p4 > 1) { p4 = 0; } swold = digitalRead(sw); Serial.println(p4); if (p4 == 1)//подменю 4 (торможение) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { c=c-100; lcd.clear(); } else { c=c +100; lcd.clear(); } if (c > 1000) { c = 1000; } if (c < 200) { c = 200; } } Serial.println(s); lcd.setCursor(5,0); lcd.print("PreStop"); lcd.setCursor(7,1); lcd.print(PreStop); pinAold = pinNOW; } } if(m==5)//защита капли { if (p5==0) { lcd.setCursor(4,0); lcd.print("DripBack"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p5++; lcd.clear(); } if (p5 > 1) { p5 = 0; } swold = digitalRead(sw); Serial.println(p4); if (p5 == 1)//подменю 5 (всасывание капли) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { j--; lcd.clear(); } else { j++; lcd.clear(); } if (j > 50) { j = 50; } if (j < 0) { j = 0; } } Serial.println(j); lcd.setCursor(4,0); lcd.print("DripBack"); lcd.setCursor(7,1); lcd.print(j); pinAold = pinNOW; } } if(m==6) { if (p6==0) { lcd.setCursor(5,0); lcd.print("Rotate"); } if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { p6++; lcd.clear(); } if (p6 > 1) { p6 = 0; } swold = digitalRead(sw); Serial.println(p6); if (p6 == 1) //подменю 6 (направление вращения) { pinNOW = digitalRead(pinA); delay(2); if ((pinAold == LOW) && (pinNOW) == HIGH) { if (digitalRead(pinB) == LOW) { r++; lcd.clear(); } else { r--; lcd.clear(); } if (r>1) { r=0; } if (r<0) { r=1; } } if (r == 1) { Rotate = HIGH; RotateBack = LOW; lcd.setCursor(4,1); lcd.print("Forward"); } if (r==0) { Rotate = LOW; RotateBack = HIGH; lcd.setCursor(4,1); lcd.print("Backward"); } Serial.println(r); lcd.setCursor(5,0); lcd.print("Rotate"); pinAold = pinNOW; } } speedd = s; spd = map(speedy,200,2000,10,1); //для вывода на экран скорости от 1 до 10 startspd = map(s,200,2000,10,1);//для вывода начальной скорости PreStop = map(c,200,1000,1,10);//торможение b = ml * 150; } void stepp() //Функция одного шага вперед { if(micros() - time>=speedd); { time = micros(); digitalWrite(dir, Rotate); digitalWrite(stp, HIGH); if(micros() - time>= speedd); { time = micros(); digitalWrite(dir, Rotate); digitalWrite(stp, LOW); } } } void steppback() //Функция одного шага назад { if(micros() - time > speedd); { if (stpvalue == HIGH) { stpvalue = LOW; } else { stpvalue = HIGH; } digitalWrite(dir, RotateBack); digitalWrite(stp, stpvalue); } } void Nalit() //функция прерывания { digitalWrite(11, LOW); for (int a = 0; a <= b; a++)// { if (speedd > speedy && b - a > c)//плавный разгон и торможение { speedd--; } if (speedd < speedy) { speedd = speedy; } if (b - a < c) { speedd++; } stepp(); } if (a = b)//контроль капли { speedd = s; for (int k = 0; k < j; k++) { steppback(); } } digitalWrite(11, HIGH); }ну, вот - попроси дурня молиться, он стеклянный хер разобъёт...
нет, что бы самостоятельно локализовать глючный код и выложить 10 строк, он запостил 500.
ну, вот - попроси дурня молиться, он стеклянный хер разобъёт...
нет, что бы самостоятельно локализовать глючный код и выложить 10 строк, он запостил 500.
Romanoff,
Вы не обижайтесь, но сейчас я буду сильно ругаться и обзываться! (впрочем, захотите обидеться - мне пофигу).
Вам, идиоту, уже писали
Код надо приводить полностью.
ну, и где??????????????????????????
Нет, выложить код нам в лом - мы лучше будем мозги засирать себе и людям, а после нескольких часов бесполезной писанины и потери времени, вдруг выясняется, что
Функция Vipolnit выполняется по прерыванию
Если бы Ваше ленивое величество соизволило бы выложить код полностью, как Вас просили, Вам бы ещё утром сказали бы, что не работает ни хрена millis в прерываниях от слова совсем. Она всегда возвращает одно и тоже значение! А delayMicroseconds - работает.
Понятно в чём проблема?
Теперь про решение. Вообще-то в прерывании такие вещи не делаются, но в качестве костыля попробуйте вставить
sei();
между строками 1 и 2.
И, да, пока не будет полного кода, я вообще больше не буду читать Ваши вопросы - это просто потеря времени, как было с прерыванием.
я так делал, мне сказали код целиком. Читайте тему целиком, а потом пожалуйста обзывайтесь. Вы что все такие нервные?
если я тебе скажу убиться нахер - ты хоть тогда начнёшь думать, зачем я тебе это сказал?
я так делал, мне сказали код целиком. Читайте тему целиком, а потом пожалуйста обзывайтесь. Вы что все такие нервные?
если я тебе скажу убиться нахер - ты хоть тогда начнёшь думать, зачем я тебе это сказал?
Что тебе нужно? отвали
ну, вот и поговорили - зачем было нужно постить 500 строк кода задним числом, когда уже выяснили, почему так, а не иначе?
*когда голова начнёт думать прежде, чем руки делать?
Я Вам советовал поставить sei(); - помогло?
Для delay() используется одна функция. При millis() надо две функции 1- запускающая , 2 -размещеная в цикле loop(). Прерывание тоже , но 2 это фунция висит не в loop(), а в фунции прерывания. Это и есть тупизна новичков при переходе на millis(). Они буквально этот нюанс не догоняют.
Для delay() используется одна функция. При millis() надо две функции 1- запускающая , 2 -размещеная в цикле loop(). Прерывание тоже , но 2 это фунция висит не в loop(), а в фунции прерывания. Это и есть тупизна новичков при переходе на millis(). Они буквально этот нюанс не догоняют.
походу тут собрание сошедших с ума до и после изучения С++ - вторые учат первых программировать. О_О
Я Вам советовал поставить sei(); - помогло?
Попробовал. Ничего не изменилось..
походу тут собрание сошедших с ума до и после изучения С++ - вторые учат первых программировать. О_О
Может просто подскажешь, если знаешь как это сделать? Я пока не понял ничего из всех советов.
Попробовал. Ничего не изменилось..
А чего вчера не сказали? У меня было время вечером посмотреть что там с кодом.
По поводу того, что Вы ничего не поняли, для начала почитайте http://arduino.ru/Reference/AttachInterrupt и забудьте об идее использовать millis внутри прерывания. И подумайте как делать.
А код Ваш я посмотрю сегодня попозже.
Хорошо. Спасибо. Про прерывани я читал) Я не совсем нуб. Код же я как то написал. Там пишут дилей не работает, но он то работает) а милис да, видимо не подойдет для меня. Надо делать милис не через прерывания, а по цифровому порту и не париться.
Там пишут дилей не работает, но он то работает)
Не работает. У Вас работает не delay, а delayMicroseconds - это две большине разницы.
милис да, видимо не подойдет для меня.
Почему не подойдёт? Надо просто правильно сделать. Меня вот удивило, что Вам костыль не помог, значит ошибка в чём-то ещё. Сегодня я найду время посмотреть код.
А какая разница? Цепляете на любые цифровые пины и прописываете их номера в программе. Только не перепутайте ничего.
Так прошу прощения, костыль помог пару раз из 20 попыток выполнить функцию, потом контроллер замер. Если я не буду использовать прерывания, а сделаю выполнение функции при условии лог.единицы на цифровом порту, то это может помочь ситуации? Или разницы не будет?
Знаете, я краем глаза посмотрел на код.... Пока Вы серьёзно за него не возьмётесь, не поможет ничего. У Вас проблема не в прерывании, а либо в крайней невнимательности, либо в полном незнании языка.
Я не совсем нуб.
Это заметно.
if (digitalRead(sw) == LOW) { delay(10); } if ((swold == HIGH) && (digitalRead(sw) == LOW) ) //Проверяем состояние кнопки { Nalit(); } swold = digitalRead(sw);Сделал не через attach, разницы никакой нет. пищит.
Знчит, последнее китайское предупреждение (для особо понятливых)
Код нужен полностью! Делайте его сворачиваемым, но публикуйте полнстоью.
Сделал не через attach
Что сделал? Как сделал? ХЗ! Не через какой attach, когда было прямо сказано - оставьте с прерываниями, только исправьте ошибки добавьте sei()? ХЗ!
Господи хватит обвинений)) Что с вами? У вас на форуме какая то мания принизить достоинство другого человека, в чем то обвинить, сказать что ничего ты не знаешь ты тупой и прочее. Ну да ладно.
Я к коду вернулся спустя год. Второпях напутал, нет, даже возможно даже тупанул, ведь год вообще не кодил. Действительно if напутал, когда переделывал с delay на micros.
603 вы правы я это давно уже написал. Естественно там сравнение, что самое странное что это условие работало, даже с присвоением, но исправил, спасибо.
Удалил точки с запятой - не работает. Вставил костыль - не работает.
Цикл Nalit выполняется но в функци step не работают micros. Т.е. одно действие выполняется сразу после другого без задержки.
Ну, как знаете. Дело Ваше.