Раздельное управление двумя устройствами с одной платы
- Войдите на сайт для отправки комментариев
Пнд, 18/04/2016 - 23:43
Пока что на светодиодах тренируюсь, нужно заствить их работать каждый по независящему от другому циклу.
Вот написал такое:
//2 светодиода плавно зажигаются и затухают const int RED=9; const int GR=10; void setup() { pinMode (RED, OUTPUT); pinMode (GR, OUTPUT); } void loop() { for (int i=0; i<256; i=i+1) { analogWrite(RED, i); delay(5); } for (int i=255; i>=0; i=i-1) { analogWrite(RED, i); delay(20); } for (int j=0; j<256; j=j+1) { analogWrite(GR, j); delay(15); } for (int j=255; j>=0; j=j-1) { analogWrite(GR, j); delay(5); } }
Но светодиоды работают по очереди, не могу придумать, как запустить циклы на одновременное прохождение.
И да, я чайник.
Ну, понятное дело, они ждут друг друга в Ваших delay'ах. Избавьтесь от delay и всё будет.
http://robotosha.ru/arduino/multi-tasking-arduino.html
А ещё лучше, вместо организации классов с сохранением номера пина использовать макрокоманды для обозначения ножек и everyMillis() для повышения прозрачности. :)
А ещё лучше, вместо организации классов с сохранением номера пина использовать макрокоманды для обозначения ножек и everyMillis() для повышения прозрачности. :)
А еще лучше сразу arhat.h?:)))
Пока что на светодиодах тренируюсь, нужно заствить их работать каждый по независящему от другому циклу.
Вот написал такое:
Но светодиоды работают по очереди, не могу придумать, как запустить циклы на одновременное прохождение.
И да, я чайник.
Все были чайниками - не расстраивайтесь :)
Процессор не многозадачный, это не виндовс, где можно запустить одновременно много задачь и они будут работать параллельно почти не влияя друг на друга. Процессор исполняет команды последовательно.
Вы сделали очередь корорая движется по кругу и эта очередь замирает на время из-за команды delay(). Пока выступает эта команда, все ждут. Необходимо убрать эту команду, тогда очередь понесётся по кругу без остановок с бешеной скоростью. Чтобы в этом быстром круговороте происходили требуемые действия, необходимо опираться на текущее время. Алгоритм такой:
1. Запоминаем текущее время в переменной в начале цикла.
2. Внутри цикла проверяем прирост текущего времени, вычитая из самого текущего времени значение, запомненное в п.1. Если это изменение уже дошло до нужного значения, выполняем некоторое быстрое действие, не останавливающее выполнение цикла (включаем светодиод или выключаем), далее запоминаем в переменной п.1 новое время. Если же ещё не натикало сколько надо, ничего не делам. И такую проверку условия ставим на все светодиоды.
Есть готовые решение для этого, но несложно и самостоятельно реализовать. :)
Кстати, объявлять ноги переменными вовсе не обязательно и даже не желательно, ибо для доступа к этим переменным требуются ресурсы процессора. Вместо "const int red=9;" намного более эффективно написать "#define red 9" тогда компилятор при использовании red не обращение к переменной будет писать процессору, а подставит числовую константу, что будет эффективнее.
Вместо "const int red=9;" намного более эффективно написать "#define red 9"
А теперь скомпилируйте оба варианта с попутным выводом кода в ассемблере, посмотрите ... и впредь не говорите то, чего не знаете.
вы удивитесь, но "const int red=9;" и "#define red 9" на выходе компилятора дадут абсолютно одинаковый результат: "9". Они поумнели за последнее время :)
А вот если написать "int red=9;", то тогда да, разница будет существенной.
как то так
в конце задержка в 5 потому что у нас все кратное 5, можно убрать)
вы удивитесь, но "const int red=9;" и "#define red 9" на выходе компилятора дадут абсолютно одинаковый результат: "9". Они поумнели за последнее время :)
А вот если написать "int red=9;", то тогда да, разница будет существенной.
Согласен. :)
Спасибо за подробные разъяснения, у меня тоже были сомнения в многозадачности процессора ардуино, но я почему-то считал, что эта проблема как-то аппаратно в ардуино обходится. Теперь понял, что решать надо программно.
Сейчас экспериментирую на светодиодах, но в "программе-максимум" у меня изготовление копировального станочка с ЧПУ.
Спасибо за подробные разъяснения, у меня тоже были сомнения в многозадачности процессора ардуино, но я почему-то считал, что эта проблема как-то аппаратно в ардуино обходится. Теперь понял, что решать надо программно.
Сейчас экспериментирую на светодиодах, но в "программе-максимум" у меня изготовление копировального станочка с ЧПУ.
У процессоров нет многозадачности, есть лишь средства её реализации. :) А в копировальном станке, я думаю, не потребуется многозадачность - линейная "черепашья графика". :) Одновременное движение по нескольким осям не требует многозадачности и даже наоброт - требует последовательного исполнения, обеспечивающего синхронноть.
У процессоров нет многозадачности, есть лишь средства её реализации.
Точно, вспомнил, процессор все обрабатывает последовательно, а многозадачность поддерживает (или не поддерживает) ОС.
Да, ваша правда, иначе согласовать движение по осям будет проблемой. Где бы про это можно посмотреть, хотя бы по каким словам искать информацию?
Пока что сделал вот так:
Это уже ближе, но все равно не то, один светодиод влияет на другой, по отдельности они мигают по другому, чем вместе. То есть если на кусок кода, отвечающий за один светодиод, поставить теги комментария, то другой мигает так, как задумано. Вместе же они мигают отсебятину.
в посте #2 было приведено решение. Надо только вникнуть ;)
Я бы написал примерно так:
В этом случае, у вас и зажигание и тухление светодиода идет неблокирующим действием и начальный код будет исполняться И в процессе изменения яркости тоже. А у вас, пока он не загорится waitAll = 256*15 мсек = 3.84 секунды а потом пока не погаснет ещё 255*5 = 1.28сек, итого 3,84+1,28=5,12сек .. весь код "стоит колом" и МК всё это время основные команды в loop() не отрабатывает.
Скомпилял. Скетч 882 байта. Но, номера пинов надо всеж таки определять через #define
Заодно нашел ошибку в пересчетах, поправил и даже упростилось. :)
Кстати, объявлять ноги переменными вовсе не обязательно и даже не желательно, ибо для доступа к этим переменным требуются ресурсы процессора. Вместо "const int red=9;" намного более эффективно написать "#define red 9" тогда компилятор при использовании red не обращение к переменной будет писать процессору, а подставит числовую константу, что будет эффективнее.
Немного уточнить хочу, ибо мои знания о программировании идут из глубины веков.))) И это так, потому как программировал последний раз на языке PL-1 в восьмидесятых годах последнего столетия прошлого тысячелетия. Поэтому для понимания некоторых вещей мне требуется отдельное объяснение, хотя всем кажется, что это само собой разумеющиеся.
Поэтому скажите, правильно ли я понимаю, что функция "const int red=9; выполняет такие действия"
- объявляет тип данных как константу,
- константу целочисленную,
- задает ее имя,
- имя текстовое,
- выделяет под ее размещение 2 байта в регистрах памяти,
- ставит ее значение равным 9.
Не пойму только, как компилятор понимает, что это не просто число 9 под именем red, а именно девятый вывод на плате?
А "define red 9" говорит компилятору, что когда в тексте встретится "red", то нужно просто вместо текста вставить число 9, выделив при этом необходимые регистры памяти под его размещение. И, кстати, тот же вопрос, почему эта 9 определяется именно как вывод?
Не пойму только, как компилятор понимает, что это не просто число 9 под именем red, а именно девятый вывод на плате?
А "define red 9" говорит компилятору, что когда в тексте встретится "red", то нужно просто вместо текста вставить число 9, выделив при этом необходимые регистры памяти под его размещение. И, кстати, тот же вопрос, почему эта 9 определяется именно как вывод?
ответ на оба вопроса задаем пин RED тобишь 9 как выходной и делаем запись переменной ledState в пин RED.
Объявление const int red = 9;
В С/С++ читается примерно так (и это НЕ функция!): имя "red" является знаковой целочисленной константой (нормально 2 байта, но бывают "экзотические системы") с начальным значением "9".
Компилятор помечает в таблице имен это имя как неизменяемое и везде вместо него подставляет константу 9.
К какому пину платы относится эта конктанта - компилятору "по-барабану". Он чисто С-ишный. А вот во включаемых файлах (их список указан в комментариях к arhat.h - доступно на гитхабе), есть специальные макросы, которые связывают некоторые операции с таким числом с соответствующим АДРЕСОМ памяти (регистром), который .. соответствует требуемому действию с заданным пином.
Все операции с пинами платы преобразуются в конечном счете в операции И/ИЛИ логики над соответствующими битами нужного адреса.
Все пины отображены на "регистры" микроконтроллера, которые сами "отображены" на адреса памяти. Их список есть в каждом даташите на каждый микроконтроллер Атмела. .. и у каждого - по своему.
digitalWrite() делает такое преобразование через вызов спец. функции, которая перекодирует по таблице номер пина в конкретный адрес и бит в нем. Можно, если задано константно через #define эту перекодировку возложить на препроцессор "С" и в код встыкать только одну команду И/ИЛИ логики по управлению пином. Что и сделано в arhat.h. Несколько вычурно, но работает исправно.
Дополню, некоторые адреса памяти, отведенной под регистры МК имеют "короткие команды" ввода-вывода, но они байтовые. То есть ими можно изменять сразу 8 пинов или устанавливать некое значение в неком регистре управления .. типа analogWrite().
Не пойму только, как компилятор понимает, что это не просто число 9 под именем red, а именно девятый вывод на плате?
Никак не понимает. Для него это просто число 9. Для кого-то, может быть, это количество дырок в кармане, а для другого - миллиардов в банке, а для компилятора - просто число 9. Как и для чего это число использовать - это Ваше дело, компилятору это А) неизвестно и Б) безразлично.
Здравствуйте народ, Помогите мне пожалуйста написать скетч сам никак не понимаю как это сделать нужен для ик управления и для управления реле в одном скетче как-то объединил 2 скетча но работает некорректно пожалуйста помогите.
думаю, ошибка в строке 13.
думаю, ошибка в строке 13.
Если Вы это про программу уважаемого Arhat109-2 , то там же написано
нет, я про скетч, написанный Maik
Чтобы синхронно двигаться по нескольким осям одновременно мотором, который требует давать ему N шагов, необходимо либо создать таблицу шагов по осям равной размерности для всех осей и в неё записать все шаги, учитывая что по одной оси на 3 шага у другой оси будет 2 шага разных и один стоять на месте и т.п. Либо задавать перемещение функцией и на кадую единицу времени выдавать шаги. Но в этом случае всё равно моторы будет каждый шаг делать отдельно по осям. Иногда и чаще всего это неприемлемо - будет дрейф. Для этого необходимо делать буффер по каждой оси, сначала его заполнять значениями каждого шала, а потом давать уже синхронно команду на вывод сразу всег регистров осей. Возможно, скороть записи в 3 порта процессора настолько высока, что с этим не стоит заморачиваться, т.е. процессор записал в один порт шаг на перемещение по одной оси и мотор ещё не успел поехать, как он уже и для второй оси порт записал, но мне приходилось давно-давно через LPT-порт управлять осями и там пришлось городить регистры.
А ещё у дуньки есть ШИМ управляемые приводы - ему дал, грубо говоря, положение 26 и он сам туда поедет, да ещё и держать это положение будет, если враги отодвинут. :)