delay()-millis() как оптимизировать код
- Войдите на сайт для отправки комментариев
Втр, 25/01/2022 - 18:26
В последние дни много тем о данном переходе. Ковыряюсь в направлении "объединить-переписать два скетча" примерно так:
// 1 поток void setup() { pinMode(13, OUTPUT); } void loop() { delay(500);// кадр 1 digitalWrite(13,HIGH); delay(100);// кадр 2 digitalWrite(13,LOW); }
// 2 поток void setup() { pinMode(12, OUTPUT); } void loop() { delay(666);// кадр 1 digitalWrite(12,HIGH); delay(222);// кадр 2 digitalWrite(12,LOW); }
// слитые 1 и 2 поток long Y1=0; long Y2=0; int K1=1;//счётчик кадров в псевдопотоке 1 int K2=1;//счётчик кадров в псевдопотоке 2 void setup() { pinMode(13, OUTPUT); pinMode(12, OUTPUT); } void loop() { loop_1();// loop_2();// } ////////////////////////////// void loop_1(){ if(K1==1&&millis()-Y1>=100){Y1=millis();K1=2;digitalWrite(13,LOW);} if(K1==2&&millis()-Y1>=500){Y1=millis();K1=1;digitalWrite(13,HIGH);} } void loop_2(){ if(K2==1&&millis()-Y2>=222){Y2=millis();K2=2;digitalWrite(12,LOW);} if(K2==2&&millis()-Y2>=666){Y2=millis();K2=1;digitalWrite(12,HIGH);} }
Сводится всё примерно к наборам типа:
Но каждый раз проверять на истинность весь список нет смысла, достаточно лишь одну строку, содержащую номер текущего кадра.
Как это можно сделать?
Сводится всё примерно к наборам типа:
Но каждый раз проверять на истинность весь список нет смысла, достаточно лишь одну строку, содержащую номер текущего кадра.
Как это можно сделать?
Это не будут проверяться условия с номером кадра больше текущего?, а до текущего будут?
Это не будут проверяться условия с номером кадра больше текущего?, а до текущего будут?
Странный вопрос. Оператор switch
Ну именно как в вопросе я и понял после 4 прочтения :-). Тогда это частичное сокращение проверок.
Будет выполняться только кейс с совпадающим номером кадра. Главное, не забывать операторы break; в конце каждого кейса.
Ясно, при последнем кадре будут проведены все проверки до него.
Русский язык не родной?
Будет выполняться только кейс с совпадающим номером кадра. Главное, не забывать операторы break; в конце каждого кейса.
Родной, - Родной ! :-)
Не выполняться, а проверяться. Вот фраза из ссылки:
Когда найден оператор case, значение которого равно значению переменной, выполняется программный код в этом операторе.
НАЙДЕН...
Именно так. Оператор switch берет значение К и пробегает по списку кейсов, сравнивая К с их значениями. Если находит совпадающий, то выполняет его код. По другому никак не получится. Человек - и тот сначала ищет совпадающий кейс, а потом уже смотрит, что в нем. Так у человека глаза есть. И обработка информации где-то в глубинах мозга. А МК как сможет узнать, куда прыгать? ;)
По другому никак не получится. А МК как сможет узнать, куда прыгать? ;)
Печаль... видно бейсик из детства навеял со своими goto между строками-частями кода.
В детстве и деревья были повыше, и трава зеленее. А если сейчас сядешь за бейсик и попробуешь сделать на нем, окажется, что все равно нужно сравнивать и выбирать нужную метку по условию сравнения ;)
lilik и v258
не нужен тут switch() и куча if-ов
Сделайте массив интервалов с индексом по переменной K - и все проверки выродятся в одну строчку
В последние дни много тем о данном переходе. Ковыряюсь в направлении "объединить-переписать два скетча" примерно так:
Мне кажется, сам подход дидактически неверен: Вы показываете пример исходного кода и пример финального кода, причем финальный очень существенно отличается от исходного. И где здесь ответ на вопрос "о переходе". Т.е. о том, как его осуществить.
Совершенно непонятно, как из первого кода получить второй.
Нужно указать, что объединение кодов должно происходить в два этапа:
1. В каждом из фрагментов перейти от использования delay() к использованию millis(). (обязательно проверив их работоспособность после переделки)
2. Физически объединить полученные на 1 этапе скетчи в один.
Вы опустили результат первого этапа, чем сделали свой пример совершенно непонятным.
Вы опустили результат первого этапа, чем сделали свой пример совершенно непонятным.
Да, упустил.
После объединяем в общий скетч:
Пока эксперименты выглядят по такому плану:
1. Делим скетчи на фрагменты-кадры по входящим в них delay();
2. Меняем фрагменты на эквиваленты с использованием millis();
3. Собираем каждый скетч в отдельности и проверяем эквивалентность в работе.
4. Собираем скетчи в общий и перепроверяем в работе.
lilik и v258
не нужен тут switch() и куча if-ов
Сделайте массив интервалов с индексом по переменной K - и все проверки выродятся в одну строчку
Это да, но их не станет меньше. И проверки скорее всего будут несводимые к массивам (разные наборы условий и реализаций по ним).
Я извиняюсь, вопрос новичка: а разве не надо в разных условиях применять разные переменные?
Имею ввиду Y1
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия. Вот что первоначальной инициализации нормальной нет, это вопрос. Я бы сделал так:
lilik, Нужно писать как положено. Членораздельно, прежде всего! На кой хрен мне (и всем остальным) нужно раскодировать все эти записи! Вы кто? Радистка Кэт, чтоле? Ужос!
Это просто неуважение к читающим! И я вам об этом уже говорил. Но, видать, "не в коня корм", к сожалению.(
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия.
Я к тому, что в #17 возможно надо не long Y1 = 0; long Y2 = 0; , a long Y1 = 0;...longY4 = 0;?
Иначе будет сбой по интервалам. Или нет?
Вы кто? Радистка Кэт, чтоле? Ужос!
Трудно перестроиться на программирование. Привычка (сильна) ужимать до отдельных букв и действий между ними. А писать Kadr и Yschedschee тоже не хочется. Просто идею саму хотел донести.
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия. Вот что первоначальной инициализации нормальной нет, это вопрос. Я бы сделал так:
Согласен, обычно пишу long Y1=0;// тут чего то ступил.
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия.
Я к тому, что в #17 возможно надо не long Y1 = 0; long Y2 = 0; , a long Y1 = 0;...longY4 = 0;?
Иначе будет сбой по интервалам. Или нет?
Нет. Y1 это образно говоря течение 1 потока, Y2 - 2 потока. А значения K1, K2 показывают как далеко от начала соответствующего loop() дошло исполнение соответствующего скетча.
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия. Вот что первоначальной инициализации нормальной нет, это вопрос. Я бы сделал так:
Согласен, обычно пишу long Y1=0;// тут чего то ступил.
Да так и было у тебя изначально (равно нулю), но это не правильно. Миллис уже могло отсчитать не мало (или запоминает значение при ребуте или ещё что (миллион вариантов), поэтому первые интервалы будут не верными. Правильно сразу миллис инициализировать и как можно ближе к loop() или даже в самом loop(). Это пофиг со светодиодами, а там где 1 миллисекунда важна - не прокатит.
Интервалы заданы константами (500 и 100, соответственно), а переменная K1/K2 как раз разделяет условия.
Я к тому, что в #17 возможно надо не long Y1 = 0; long Y2 = 0; , a long Y1 = 0;...longY4 = 0;?
Иначе будет сбой по интервалам. Или нет?
В #26 все доходчевее чем я пояснили.)
lilik и v258
не нужен тут switch() и куча if-ов
Сделайте массив интервалов с индексом по переменной K - и все проверки выродятся в одну строчку
Это да, но их не станет меньше. И проверки скорее всего будут несводимые к массивам (разные наборы условий и реализаций по ним).
Еще как сводимые.
Если сильно надо чтоб проверок действительно стало меньше - есть способ.
1. Для всех "задач" определяем через сколько времени им выполняться и выбираем минимальное из них.
2. Формируем через обычную работу с миллис это интервал из п.1 и по завершении - выполняем "задачу" для которой он был.
3. Переходим к п.1
На словах не сложно но на практике - не для новичка. Но проверок меньше.
В #26 все доходчевее чем я пояснили.)
lilik, BOOM, спасибо за разъяснения
Я согласен, ошибка будет небольшая, равная времени исполнения кода за фигурными скобками.
В большинстве случаев она не критична. Возможно я и здесь не прав, отвечать не надо, я лучше "тихо сам
с собой" ещё подумаю))
Вы кто? Радистка Кэт, чтоле? Ужос!
Трудно перестроиться на программирование. Привычка (сильна) ужимать до отдельных букв и действий между ними. А писать Kadr и Yschedschee тоже не хочется. Просто идею саму хотел донести.
Вот именно форма записи и затрудняет восприятие Вашей идеи.
IMHO если что-то делать, то делать как следует. А иначе - вообще не имеет смысла.
IMHO если что-то делать, то делать как следует. А иначе - вообще не имеет смысла.
Истина в том, что всё что можно измерить, всегда можно улучшить. И смысл всегда есть, потому что нет предела совершенства.
Если сильно надо чтоб проверок действительно стало меньше - есть способ.
1. Для всех "задач" определяем через сколько времени им выполняться и выбираем минимальное из них.
2. Формируем через обычную работу с миллис это интервал из п.1 и по завершении - выполняем "задачу" для которой он был.
3. Переходим к п.1
На словах не сложно но на практике - не для новичка. Но проверок меньше.
Это называется с использованием системного тика. Так обычно делают где нет миллис. Вместо тика иногда даже delay(T_SYS).
В некоторых случаях, когда просят что нибудь добавить в монстроподобный скетч, заряжаю свободный таймер на прерывание и в нём, в фоне, уже делаю свою работу.
ошибка будет небольшая, равная времени исполнения кода за фигурными скобками.
В большинстве случаев она не критична. Возможно я и здесь не прав
Таки да, я и здесь не прав. Разобрался, всё работает корректно, без ошибок. Код за фиг. скобками, если он меньше периода конечно, не влияет.
Спасибо, полезный пример.
Вот именно форма записи и затрудняет восприятие Вашей идеи.
:-(
Согласен, ещё заметил, что запись типа if(){....;....;if(){}....;....;if(){if(){}}...;} с "однобуквенными переменными" легче понимается мной чем "лесенки со словами - shot ,gone "
Если сильно надо чтоб проверок действительно стало меньше - есть способ.
1. Для всех "задач" определяем через сколько времени им выполняться и выбираем минимальное из них.
2. Формируем через обычную работу с миллис это интервал из п.1 и по завершении - выполняем "задачу" для которой он был.
3. Переходим к п.1
На словах не сложно но на практике - не для новичка. Но проверок меньше.
Это называется с использованием системного тика. Так обычно делают где нет миллис. Вместо тика иногда даже delay(T_SYS).
В некоторых случаях, когда просят что нибудь добавить в монстроподобный скетч, заряжаю свободный таймер на прерывание и в нём, в фоне, уже делаю свою работу.
Так тут интервал как формировать - не существенно. Существенно и сложно п.1. По сути нужно держать список порядка вызова задач сортированный по нарастанию времени, уметь добавлять в него новую задачу и т.д.
Я реализовал такое для разделения одного аппаратного таймера для нескольких задач. Работает нормально для серв, 1ware и прочего с длительностями процессов от десятков мкс до нескольких мс. Для других интервалов можно и проще писать.
Но, повторюсь, это точно не для новичков.
Спасибо, полезный пример.
Он безграничен для тренировок. Как воткнуть в 1 кадр "делей из цикла" и т.д. :-)
Он безграничен для тренировок. Как воткнуть в 1 кадр "делей из цикла" и т.д. :-)
Когда-то Alexey_Rem показал мне простой и доходчивый пример
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/popytka-odolet-delay#comment-606475
чем помог разобраться(ещё раз ему спасибо).
С тех пор использую в разных вариациях. По сути это то же самое, просто не разобрался сразу ,
опыта видимо маловато ещё...
Но чем больше разберу примеров - тем лучше))
По сути это то же самое,...
Но чем больше разберу примеров - тем лучше))
Ну, да, строка if(millis()>T){T=millis();...} эквивалент в "мгновенном loop()" для delay(T); из "долгого loop()". Остальные "добавки лишь для указания местоположения" в долгом.