Параллельный процессы при нажатие кнопки
- Войдите на сайт для отправки комментариев
Добрый день,
Суть необходимо сделать, чтобы при нажатие кнопки крутился шаговый двигатель в ту или иную сторону и пока он крутится с помощью сервопривода совершать движение. Реализовал это на параллельных процессах.
Первый код не работает, когда запускаю двигатель, то не могу его остановить. Должно быть: нажал на кнопку один раз он запустился, второй раз он остановился. Если не сложно, то помогите понять в чем проблема.
#include <StaticThreadController.h> #include <Thread.h> #include <ThreadController.h> #include <Servo.h> #include <Keypad.h> #include <plcLib.h> int dirPin = 8; int stepperPin = 9; Servo servo; Thread runstep = Thread(); Thread runservo = Thread(); char keyMap[4][4] = { {'1','2','3', 'A'}, {'4','5','6', 'B'}, {'7','8','9', 'C'}, {'*','0','#', 'D'} }; byte rowsPins[4] = { 50, 48, 46, 44 }; byte colsPins[4] = { 42, 40, 38, 36 }; Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 ); int agle = 85; String message = ""; void setup() { pinMode(dirPin, OUTPUT); pinMode(stepperPin, OUTPUT); setupPLC(); servo.attach(7); servo.write(85); runstep.onRun(rotstep); runstep.setInterval(500); runservo.onRun(rotservo); runservo.setInterval(200); } void rotateDeg(float deg, float speed){ int dir = (deg > 0)? HIGH:LOW; digitalWrite(dirPin,dir); int steps = abs(deg)*(1/0.225); float usDelay = (1/speed) * 70; for(int i=0; i < steps; i++){ digitalWrite(stepperPin, HIGH); delayMicroseconds(usDelay); digitalWrite(stepperPin, LOW); delayMicroseconds(usDelay); } } bool rotright = false; bool rotleft = false; bool servoL = false; bool servoR = false; // Поток степпера: void rotstep() { while (rotright || rotleft) { if (rotright) { rotateDeg(-360, .1); delay(100); rotateDeg(-360, .1); rotright = false; } else { rotateDeg(360, .1); delay(100); rotateDeg(360, .1); } } } // поток сервопривода void rotservo() { if(servoL) { agle = agle - 2; servo.write(agle); servoL = false; } else if (servoR) { agle = agle + 2; servo.write(agle); servoL = false; } } void step(boolean dir,int steps){ digitalWrite(dirPin,dir); delay(50); for(int i=0;i<steps;i++){ digitalWrite(stepperPin, HIGH); delayMicroseconds(100); digitalWrite(stepperPin, LOW); delayMicroseconds(100); } } void loop() { char isKeyPress = key.getKey(); if(isKeyPress == '#'){ // # - поворот серво servoR = true; if (runservo.shouldRun()) runservo.run(); // запускаем поток } if(isKeyPress == '*'){ // * - поворот серво servoL = true; if (runservo.shouldRun()) runservo.run(); // запускаем поток } if(isKeyPress == '0'){ // * - поворот серво в первоначальное положение servo.write(agle=85); } if(isKeyPress == '1'){ // 1 - поворот двигателя право в первоначальное положение if (rotright) { delay(500); rotright = false; } else { rotright = true; } if (runstep.shouldRun()) runstep.run(); // запускаем поток } if(isKeyPress == '3'){ // 1 - поворот двигателя лево в первоначальное положение if (rotleft) { delay(500); rotleft = false; } else { rotleft = true; } if (runstep.shouldRun()) runstep.run(); // запускаем поток } }
Второй код основной. Я плюнул на запуск двигателя с кнопки и включил его постоянно работать, а другими кнопками изменял положение сервопривода, но он с первого раза не реагирует на нажатие, видимо когда только нажатие попадает между этапами вращения.
#include <StaticThreadController.h> #include <Thread.h> #include <ThreadController.h> #include <Servo.h> #include <Keypad.h> #include <plcLib.h> int dirPin = 8; int stepperPin = 9; Servo servo; Thread runstep = Thread(); Thread runservo = Thread(); char keyMap[4][4] = { {'1','2','3', 'A'}, {'4','5','6', 'B'}, {'7','8','9', 'C'}, {'*','0','#', 'D'} }; byte rowsPins[4] = { 50, 48, 46, 44 }; byte colsPins[4] = { 42, 40, 38, 36 }; Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 ); int agle = 85; String message = ""; void setup() { pinMode(dirPin, OUTPUT); pinMode(stepperPin, OUTPUT); setupPLC(); servo.attach(7); servo.write(85); runstep.onRun(rotstep); runstep.setInterval(500); runservo.onRun(rotservo); runservo.setInterval(200); } void rotateDeg(float deg, float speed){ int dir = (deg > 0)? HIGH:LOW; digitalWrite(dirPin,dir); int steps = abs(deg)*(1/0.225); float usDelay = (1/speed) * 70; for(int i=0; i < steps; i++){ digitalWrite(stepperPin, HIGH); delayMicroseconds(usDelay); digitalWrite(stepperPin, LOW); delayMicroseconds(usDelay); } } bool rotright = false; bool rotleft = false; bool servoL = false; bool servoR = false; // Поток степпера: void rotstep() { while (rotright || rotleft) { if (rotright) { rotateDeg(-360, .1); delay(100); rotateDeg(-360, .1); rotright = false; } else { rotateDeg(360, .1); delay(100); rotateDeg(360, .1); } } } // поток сервопривода void rotservo() { if(servoL) { agle = agle - 2; servo.write(agle); servoL = false; } else if (servoR) { agle = agle + 2; servo.write(agle); servoL = false; } } void step(boolean dir,int steps){ digitalWrite(dirPin,dir); delay(50); for(int i=0;i<steps;i++){ digitalWrite(stepperPin, HIGH); delayMicroseconds(100); digitalWrite(stepperPin, LOW); delayMicroseconds(100); } } void loop() { char isKeyPress = key.getKey(); rotateDeg(360, .71); delay(1); if(isKeyPress == '#'){ // # - поворот серво servoR = true; if (runservo.shouldRun()) runservo.run(); // запускаем поток } if(isKeyPress == '*'){ // * - поворот серво servoL = true; if (runservo.shouldRun()) runservo.run(); // запускаем поток } if(isKeyPress == '0'){ // * - поворот серво в первоначальное положение servo.write(agle=85); } if(isKeyPress == '1'){ // 1 - поворот двигателя право в первоначальное положение if (rotright) { delay(500); rotright = false; } else { rotright = true; } if (runstep.shouldRun()) runstep.run(); // запускаем поток } if(isKeyPress == '3'){ // 1 - поворот двигателя лево в первоначальное положение if (rotleft) { delay(500); rotleft = false; } else { rotleft = true; } if (runstep.shouldRun()) runstep.run(); // запускаем поток } }
Как можно сделать, чтобы серво сразу реагировал на нажатие. И как сделать запуск и стоп степпера по кнопке, при этом чтобы серво жил своей жизнью и тоже реагировал на кнопки.
СПАСИБО!!
Как можно сделать, чтобы серво сразу реагировал на нажатие. И как сделать запуск и стоп степпера по кнопке, при этом чтобы серво жил своей жизнью и тоже реагировал на кнопки.
убрать делеи... все. нафиг.
везде? просто до этого было без делэй, но тоже не работало, это уже код с экспериментами.
Сейчас убрал везде делэй и убрал постоянное вращение. Запустить вращение могу, остановить не могу. и серво не работает((
Сейчас убрал везде делэй и убрал постоянное вращение. Запустить вращение могу, остановить не могу. и серво не работает((
теперь убери циклы
если я уберу цикл, то тогда у меня степпер сделает оборот и остановится, а надо чтобы постоянно вращалось
убрал цикл. в итоге двигатель останавливается когда выполнит команду и серво параллельно не работает
если я уберу цикл, то тогда у меня степпер сделает оборот и остановится, а надо чтобы постоянно вращалось
постоянно вращаться - это находиться в вечном цикле?
067
while
(rotright || rotleft)
068
{
069
if
(rotright)
070
{
071
rotateDeg(-360, .1);
072
delay(100);
073
rotateDeg(-360, .1);
074
rotright =
false
;
075
}
076
else
077
{
078
rotateDeg(360, .1);
079
delay(100);
080
rotateDeg(360, .1);
081
}
082
}
без
rotleft =
false
;
ты отсюда не выйдешь никогдано, и не это важно - сам дизайн кода с циклами, форами и делеями в лупе исключает какую-либо параллельность процессов.
пока контроллер занят вышеперечисленным, ты не сможешь делать что-то ещё - нажимать кнопки, снимать показания датчиков, реагировать на другие события.
убрал цикл. в итоге двигатель останавливается когда выполнит команду и серво параллельно не работает
двигатель должен делать что-то без команды?
с чего бы серво не работать, что ему не даёт?
я этого не понимаю. Да, задумка была, что двигатель в вечном цикле, пока я не изменю лог.переменную на фолс, с помощью кнопки.
у меня получилось параллельно управлять сервой, только когда в основном цикле луп я сделал постоянным вращение двигателя и тогда после его отработки, нажимая и держа кнопку я мог пробиваться сервой, чтобы поменять положение.
я этого не понимаю. Да, задумка была, что двигатель в вечном цикле, пока я не изменю лог.переменную на фолс, с помощью кнопки.
я уже второй день думаю, что ты имел в виду. но видимо не дошло до меня. Сделал так:
в итоге все снова зациклилось и остановить двигатель не могу и серво не слушается.
можете написать подробнее?
можете написать подробнее?
не нужно ничего писать - медитируй на свой код и думай, какая такая неведомая сила не даёт тебе исполнить код кнопок.
)))
в цикле луп сделал if проверку на перезапуск двигателя, т.е. если не отменен запуск, то снова в параллельный поток уходить. в итоге можно останавливать двигатель, но двигатель работает не постоянно, т.к. есть лаг во времени на обработку кода. И теперь его можно останавливать (двигать серво) и это можно сделать, только в тот момент, когда двигатель остновился((
Добавил это в луп:
видимо я не доконца понимаю, как работает thread
Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();. Все проверки нужно делать в подпрограммах thread. Там внутри thread подпрограмм ни чего не заLOOPливать. После инициализации thread сам будет вызывать подпрограмму с заданной вами периодичностью. Делайте несколько thread в каждом отдельная задача. Одна включать - выключать двигатель в зависимости от флага. Вторая менять флаг в зависимости от состояния кнопки. Третья - что ещё хочешь. Главное нигде ничего не ждать.
Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();. Все проверки нужно делать в подпрограммах thread. Там внутри thread подпрограмм ни чего не заLOOPливать. После инициализации thread сам будет вызывать подпрограмму с заданной вами периодичностью. Делайте несколько thread в каждом отдельная задача. Одна включать - выключать двигатель в зависимости от флага. Вторая менять флаг в зависимости от состояния кнопки. Третья - что ещё хочешь. Главное нигде ничего не ждать.
Так у меня так и сделано сейчас. Но не работает. вот последний код. сейчас думаю, как еще извернуться.
А двигатель делает фикисрованное кол-во оборотов и останавливается, его надо постоянно перезапускать.
Robot_Chickn, ты бы начал с малого - запускать и останавливать двигатель одной тактовой кнопкой.
ок, начну с этого! но я так понял, что это надо обязательно сделать через параллельный процесс. иначе будущее не прикрутишь потом.
Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();.
Так у меня так и сделано сейчас. Но не работает.
У тебя в loop() целая куча кода. Зачем? Ты ж thread используешь. Все RUN надо сделать в setup().
ок, начну с этого! но я так понял, что это надо обязательно сделать через параллельный процесс. иначе будущее не прикрутишь потом.
признавайся, кто тебе насрал в голову этими параллельными процессами?
забудь о параллельных, перпендикулярных и других процессах - просто пиши код, который не будет превращать контроллер в кирпич.
Мда. Ну кто так пишет параллельные процессы.
Вариант может быть таким.
Но , даже в этом вариаете не все праллельные процессы не переносят совместную работу. Точне не все умеют их писать.
я просто раньше в дипломе использовал параллельные процессы и все работало шикарно, но это совсем из другой сферы (не ардуино, а другая плата). А вот эти миллисекунды я не могу понять. Откуда мне знать сколько времени занимает у меня каждый процесс. Но видимо придется в них разобраться и сделать так. Но все равно всем СПАСИБО!
ветка не заканчивается, мне еще нужна будет помощь))
Похоже вам диплом нашару зачли. Процесс не измеряют длиной и сколько он длится. Процесс измеряют как часто он должен повторяется. Вот опрос кнопок он 0,2 секунды (200 микросекунд) должен повторятся. Ну не может чаще по кнопке стучать. У вас шаговый двигатель. У него есть скорость поворота. То есть период времени одного шага двигателя. Конечно может где-то и есть системыы, где пользователю программисту не надо заморачиваться созданием механизма организации процессов. Это делает среда. То в среде ардуино такого нет.
Похоже вам диплом нашару зачли. Процесс не измеряют длиной и сколько он длится. Процесс измеряют как часто он должен повторяется. Вот опрос кнопок он 0,2 секунды (200 микросекунд) должен повторятся. Ну не может чаще по кнопке стучать. У вас шаговый двигатель. У него есть скорость поворота. То есть период времени одного шага двигателя. Конечно может где-то и есть системыы, где пользователю программисту не надо заморачиваться созданием механизма организации процессов. Это делает среда. То в среде ардуино такого нет.
Спасибо за помощь. дейстивтельно помогло. но когда я поместил кнопки внутрь условий времени, то они не работали. сделал кнопки внутри лупа. работает, но кнопки срабатывают не с первого раза и с запаздыванием (и только если нажать и держать).
У тебя в пп
void
step(boolean dir,
int
steps),
void
rotateDeg(
float
deg,
float
speed)
зависает выполнение. Вот кнопки и не жмуться. Избавлятся надо от for циклов. У тебя же loop() крутится. Его и используй. Иначе никакие параллельные процессы нормально не заработают. И ещё хорощо бы избавится от float. Очень много едят памяти и времени на расчёты. delayMicroseconds() это тоже зло. Отработку моторов лучше загнать в прерывание таймера. С тем что у тебя делает код на весь круг это единицы милисекунд. Если правильно организовать все программа будет летать, задержки реакции на клавиши не будет.все лишнее обрал, но цикл во вращение не знаю, как убрать. Когда сделал без него в лупе, то двигатель можно сказать не двигается, поэтому без понятия, как сделать. Переменные float заменил на double.
и на сколько в цикле delayMicroseconds нужны я тоже не знаю
и на сколько в цикле delayMicroseconds нужны я тоже не знаю
Вы сами же захотели организовать программу в виде процессов.
1 процесс обработка кнопок, анализ команд с них и выработка решения
2 процесс работа шагового двигателя.
Так что надо делать свой процесс.
А иначе зачем городить такой огород.
Eсли ардуина не DUE то разницы нет никакой. По хорошему, формулы лучше преобразовать так, что бы в расчетах применялись только int типы.
Попробуйте этот скетч. Вращение мотора на один оборот в одну или другую сторону. Скорость вращения можно менять в любой момент. Повторный шаг возможен по окончании текущего. 360 - это градусы, можно заменить на переменную и делать шаг на любой угол. С сервой у вас нормально было.
nik182. Код не работает. Вообще не реагирует степпер на кнопки. Если по умолчанию поставить step = 1, то при нажатие на запуск двигателя, он дергается на один степ (видимо) и больше не реагирует на кнопки.
Код не работает. Вообще не реагирует степпер на кнопки. Если по умолчанию поставить step = 1, то при нажатие на запуск двигателя, он дергается на один степ (видимо) и больше не реагирует на кнопки.
да, что за фигня? у всего мира двигатели кнопкой управляются, а у одного уникала-тебя - нет.
Ребят, по сути задача решена, но криво с моей стороны. Моя следующая задача поставить тахометр, либо ик диод и фоторезистор, чтобы я мог измерять скорость вращений выходного вала. Относительно его показаний, я буду изменять работу сервака.
Что лучше использовать? и смогу ли я при грамотном коде обрабатывать показания оборотов, подавать изменяющееся значения скорости вращения на степпер и менять положения ардуино внутри одного ардуино мега без существенных тормозов?
https://youtu.be/_IVT0AQ3TQQ
Что лучше использовать? и смогу ли я при грамотном коде обрабатывать показания оборотов, подавать изменяющееся значения скорости вращения на степпер и менять положения ардуино внутри одного ардуино мега без существенных тормозов?
Ну задачу такую можно засунуть в одну ардуину. Но не по вашим силам. Чем больше программа , тем больше косяков вы посадите в программу. Тем более тестировать и налаживать вы программы не умеете. Вот така х.. малята.
Вы сами же захотели организовать программу в виде процессов.
1 процесс обработка кнопок, анализ команд с них и выработка решения
2 процесс работа шагового двигателя.
Так что надо делать свой процесс.
А иначе зачем городить такой огород.
если честно, то я не понял, что вы имеете в виду. Мне нужно в одно условие миллис засунуть все нажатия кнопок с таймаутом 200, второе условие - это степпер, а третье - серво. Правильно? если usdelay сделать 20, то у нас будет всего 50 шагов в секунду, чтобы увеличить скорость, нам надо будет значение меньше 20, точно ардуино сможет это обрабатывать корректно? я правильно все понял или нет?
если честно, то я не понял, что вы имеете в виду. Мне нужно в одно условие миллис засунуть все нажатия кнопок с таймаутом 200, второе условие - это степпер, а третье - серво. Правильно? если usdelay сделать 20, то у нас будет всего 50 шагов в секунду, чтобы увеличить скорость, нам надо будет значение меньше 20, точно ардуино сможет это обрабатывать корректно? я правильно все понял или нет?
Ну это я бы так делал. Другие может похоже, но с другими приемами. Но как вы сможете я не знаю.
Сервы как вариант так были бы.
qwone, вы готовы за меня написать данную программу? мини тз я пришлю, готов заплатить за ваше потраченное время. какая примерно цена? и как с вами связаться напрямую?
Не я не рискну. Для себя можно, а для других я не справлюсь. Поищите других и на месте где живете.
Кто нибудь другой готов мне в этом помочь? я так быстрее разберусь и смогу проверить свою модель(идею)
Кто нибудь другой готов мне в этом помочь? я так быстрее разберусь и смогу проверить свою модель(идею)
в чём помочь? библиотека управления двигателем не обладает функционалом запуска/остановки двигателя?
эти функции сложно запускать кнопками?
написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно.
написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно.
прошу тебя ответить на простой вопрос - обладает ли библиотека управления двигателем функционалом "старт/стоп"?
написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно.
прошу тебя ответить на простой вопрос - обладает ли библиотека управления двигателем функционалом "старт/стоп"?
наверно нет, я деталей библиотеки не знаю, только то, что написал в коде.
наверно нет, я деталей библиотеки не знаю, только то, что написал в коде.
приехали... и, как ты собрался останавливать двигатель, если ты его и раскрутить не можешь?
Добавте в setup() последней строкой steps=0; Или измените один раз скорость, потом сделайте шаг.
У меня нет keypad и мотора, поэтому отлаживал на нане, сериал порте и 13 ноге - светодиоде вот этим кодом:
Всё моргает как задумано. На каждый градус угла около четырёх импульсов. Скорость терминала 115200. Изменять скорость можно в процессе вращения - ничего не тормозит обмен с клавишами. Во время отработки вращения крутятся сервы и с клавиатуры и резистором на А0.
В библиотеку добавил