Программирование
Позаимствовав некоторые из плат робота «Скутер», «Андроид» выполнять те же самые программы: «Hello World», поиск света и обход препятствия. Распределение сигналов ввода-вывода для робота «Андроид» отличается от распределения в «Скутере», поэтому листинги должны быть отредактированы следующим образом
• зуммер перемещен с RB6 (вывод 11) на RC6 (вывод 8);
• фары D1 и D2 перенесены с RC4 (вывод 6) на RB4 (вывод 11);
• боковой светодиод D3 на RC5 (вывод 5) в роботе «Андроид» не устанавливался, однако присутствует резервный канал RC7 (вывод 9) который можно для этого использовать;
• двигатель Ml перенесен с RC6/7 (выводы 8/9) на RB6/7 (выводы 10/11).
Основное различие заключается в том, что робот «Андроид» оснащен двигателем М2 для управления движением вместо эксцентрикового шкива.
В тех местах листинга, где указывается, что робот изменяет направление движения путем небольшого отъезда назад, команда включения двигателя Ml в обратном направлении опускается. Вместо этого двигатель М2 программируется так, чтобы изменить направление движения.
Прямолинейное движение
Первое, что необходимо сделать почти в любой программе, — повернуть управляющее колесо таким образом, чтобы робот двигался прямо вперед.
Это колесо может остаться в угловой позиции после предыдущего этапа управления, поэтому, фактически, к началу нового этапа робот не знает, куда он ориентирован. Эта проблема отсутствует в роботах с управлением танкового типа.
Программа поворачивает управляющее колесо в одном направлении до тех пор, пока не сработает концевой выключатель.
Теперь программа знает, куда повернуто колесо, и поворачивает его в обратном направлении на фиксированный угол, выводя в центральную позицию. Существует две версии этой программы: одна — для двигателя постоянного тока, а другая — для шагового двигателя.
Программа для двигателя постоянного тока при выводе управляющего колеса в центральную позицию полагается на тактирование, поэтому требует точной настройки и даже в этом случае может оказаться неточной. Программа для шагового двигателя очень точна при условии, что концевой выключатель точно позиционирован.
Невзирая на наличие концевого выключателя, управление двигателя постоянного тока в общем случае менее точное, чем правление с помощью шагового двигателя. Использование двигателя к накоплению погрешности и необходимо пользовать два конечных выключателя (левый и правый), чтобы предотвратить слишком большой угол поворота рулевого колеса в любом направлении.
При использовании шагового двигателя достаточно только одного концевого выключателя для первичного центрирования колеса.
После этого всякий раз при повороте колеса считаются шаги. Позиция колеса сохраняется как значение переменной, и робот всегда знает, куда он ориентирован.
Непосредственно перед меткой программы start расположена справочная таблица codes. Она содержит коды, которые выдаются на двигатель, чтобы он отработал один шаг влево или вправо. Переменная pointer указывает на текущий код, полученный двигателем.
Следующий код, считываемый из таблицы, будет корректным кодом для продолжения поворота в данном направлении.
Кодов — всего четыре, поэтому указатель должен вернуться к коду О после указания кода 3 (или к коду 3 после кода 0 в случае обратного отсчета).
Это легко обеспечивается с помощью маски, представляющей .собой двоичное значение 00000011.
Оно подвергается логической операции «И» с указателем для получения двух младших разрядов.
Фактическое значение указателя достигает 255 перед сбросом, однако это игнорируется за счет выполнения операции логического «И» с маской и младшими двумя разрядами указателя. Обратите внимание, что при использовании управляющего шагового двигателя зуммер переносится с вывода RC6 на RA2.
Песни и танцы
Начнем с «песни». Подпрограмма для формирования прямоугольных тоновых сигналов была описана в главе 5.
Она создает звуки заданной частоты и длительности, однако для этого ей необходимо дать три значения на обработку.
Кроме того, данную подпрограмму необходимо отредактировать, чтобы звуковой сигнал поступал на заданный вывод.
В роботе «Андроид» динамик управляется по каналу RB5 порта В. Отредактируйте листинг для считывания portb вместо portc, trisb вместо trisc и portb 5 вместо portc 0. Так, для получения звука «си» введите следующий список значений:
Это часть листинга основной программы, поэтому введите после нее call playit. При желании выполнить этот фрагмент автономно в качестве демонстрации заблокируйте переход микроконтроллера PIC на подпрограммы, введя следующий цикл ожидания:
Если необходимо, чтобы один и тот же тон звучал в программе несколько раз, то весь соответствующий код можно оформить в виде подпрограммы.
Для получения последовательности, состоящей из двух-четырех нот, повторите листинг соответствующее количество раз, вызывая после каждого playit. Например, данная подпрограмма играет С, С, G’:
При указанных настройках тоновые сигналы длятся в течении одной или большего числа секунд.
Самый простой способ сделать их короче заключается в снижении значения в счетчике внешнего цикла с 5 до 3 или 2.
Для правильной настройки более практично использовать» справочную таблицу. Каждая позиция такой таблицы содержит три значения: datal, datafinal и lendata.
Таблица для трехнотной «настройки» показана ниже. В ней одно за другим указаны три значения для каждой ноты.
Подпрограмма считывания таблицы выбирает три значения с помощью переменной pointer, помещает их в три переменные, а затем вызывает подпрограмму playit. Для следующей ноты pointer опять трижды инкрементируется, считывая и перенося данные всякий раз перед вызовом подпрограммы playit.
Этот процесс продолжается до тех пор, пока не будут воспроизведены все ноты.
Листинг для трехнотной последовательности:
Подобную подпрограмму можно расширить количество нот, вплоть до формирования завершенной мелодии Вначале необходимо определить требуемые значения, используя метод, а затем — сформировать таблицу.
Теперь переходим к танцам Управление двигателями реализуется передачи последовательности кодов на приводной двигатель управления М2.
Для управления предпочтительнее шаговый двигатель, поскольку он может программироваться (однако не слишком быстрое, иначе он может несколько шагов). Коды могут быть помещены в справочную табуну в каждую четвертую (вперед/назад/стоп) и пятую (влево/вправо) позицию.
Коды «танца» запускают или останавливают приводной или управляющий двигатель, которые продолжают работать во время воспроизведения очередной ноты. Когда воспроизведение ноты завершено, микроконтроллер PIC переходит к справочной таблице, чтобы выяснить, что делать дальше.
Двигатели могут быть реверсированы, остановлены или же режим их работы может быть оставлен без изменений.
Робот может продолжать свое движение в течение воспроизведения нескольких нот. Хореография роботов — весьма увлекательное занятие.
Ножницы, бумага, камень
Эта известная во всем мире стратегическая игра — одна из любимых у робота «Андроид».
При умелом программировании его можно даже научить выигрывать.
«Ножницы, бумага, камень» — игра для двух игроков, которые стоят лицом друг к другу с правой рукой, спрятанной за спину.
Состояние ладоней правых рук символизирует ножницы, бумагу или камень. Ножницам соответствуют вытянутые указательный и средний пальцы при поджатых остальных. Бумагу символизирует раскрытая ладонь, а камень — кулак.
По сигналу игроки резко вытягивают руки вперед, чтобы показать свой выбор: ножницы, бумагу или камень.
Если оба выбрали один и тот же вариант, то результат ничейный, однако при выборе разных вариантов победитель определяется по следующим правилам:
• ножницы побеждают бумагу, потому что режут ее;
• бумага побеждает камень, потому может обернуть его;
• камень побеждает ножницы, потому что тупит их.
Такая простая игра может показаться тривиальной, однако некоторые люди воспринимают ее всерьез. Так, недавно (а именно, в мае 2005 года) в программе новостей ВВС было сообщено, что известная компания по проведению аукционов Christie выиграла контракт на 10,5 фунтов стерлингов в результате победы в одном раунде этой игры против фирмы Sotheby.
Для того чтобы робот «Андроид» мог играть в эту игру, его правая рука должна управляться шаговым двигателем.
Требуются два датчика переключатель выбора программы и кнопка. Состояние игры индицируй «глазами» робота (светодиоды D1 и D2) и зуммером.
В данном случае переключатель выбора программы служит, по сути, для выбора одной из двух стратегий игры.
Ход игры с роботом «Андроид» выглядит следующим образом:
1. Установите переключатель выбора программы в положение «Вкл.» или «Выкл.». Положению «Выкл.» соответствует хаотическая игра робота, победа в которой определяется волей случая. Для положения «Вкл.» выполняется программа, в соответствии с которой робот учится играть на своем опыте.
2. Запустите программу. «Глаза» робота начнут светиться с половинной яркостью.
3. Когда будете готовы начать игру, нажмите и отпустите кнопку. «Глаза» робота потухнут, а затем мигнут один раз, когда кнопка будет отпущена.
4. Рука робота, вероятно, уже будет поднята. Нажмите и удерживайте кнопку. Рука повернется по часовой стрелке. Эта стадия привязана ко времени. Если кнопка не будет нажата сразу после этапа 3, то программа перейдет к шагу 5, однако рука при этом окажется в неверной позиции.
5. Когда рука будет направлена вертикально вниз, отпустите кнопку.
6. Робот делает свой выбор и включает зуммер. Когда зуммер выключится, робот поднимает руку, чтобы указать свой выбор.
Вы делаете то же самое.
7. Выбор робота может быть прочитан в прорези на его плече или же определен визуально по углу порота руки: 45° означает ножницы, 90° — бумагу, а 135° — камень.
8. Робот не может распознать ваш выбор, поэтому ему необходимо сообщить, если он выиграл. В случае выигрыша «Андроида» нажмите кнопку один раз, если же результат ничейный, то не предпринимайте никаких действий. По истечении приблизительно одной минуты робот опустит свою руку, перейдя в состояние готовности к следующему раунду.
Для того чтобы сыграть еще раз при той же стратегии, нажмите кнопку для возврата к шагу 6. Стратегия может быть изменена, если предварительно изменить положение переключателя режима.
Программа — довольно длинная, однако примечательно то, что основная ее часть уделена подпрограмм управления вводом-выводом.
Собственно игра, заложенная в подпрограмме strategy, — относительно короткая.
Программу можно как угодно расширять. Например, робот мог бы использовать динамик и генерировать различные звуковые сигналы на различных стадиях игры. Или же его можно запрограммировать на исполнение короткой песни и танца после каждой его победы, а также — на испускание какого-либо мрачного звука после поражения.
Следует отметить, что существует множество стратегий обучения, которые робот может принять на вооружение.
Рассматриваемая программа структурирована таким образом, чтобы обеспечить возможность включения новых подпрограмм с заменой уже существующих. Попробуйте запрограммировать другую стратегию, которая, на ваш взгляд, может привести к победе.
В программе используются такие регистры общего назначения:
• delayO, delayl и delayn — для подпрограмм delay и longde-lay;
• ranval, bitn и bitm — для генератора случайных чисел;
• count — содержит 01, 10 или 11, которые позже умножаются на восемь для получения количества шагов, на которые должен повернуться вал двигателя;
• pointer — указывает на коды в справочной таблице code;
• mask — служит для маскирования разрядов регистра rand-val, выделяя разряды ;
• waitime — служит для установки таймаута в подпрограмме ready;
• countcopy — содержит копию первичного значения переменной .count для использования в дальнейшем;
• newcount — содержит 01, 10 или 11, которые определяют дальнейшую реакцию робота. Если робот выигрывает, то значение newcount остается неизменным, если же проигрывает, то содержимое newcount изменяется с 01 на 10, случайно выбранное число.
Она начинайся с запуска подпрограммы генерирования случайных чисел, которая будет выполняться до тех пор, пока вы не решите начать игру нажатием кнопки. Поскольку временная привязка никогда не повторяется в точности, игра почти наверняка каждый раз будет начинаться с другого случайного числа.
Программа продолжается двойной проверкой состояния кнопки, чтобы микроконтроллер не начал работать с большой скоростью сразу после нажатия кнопки. Затем следует последовательность из четырех обращений к подпрограммам. «Глаза» робота мигают один раз, после чего выполняются подпрограммы ready и movent, блок-схемы которых. Они ориентируют руку робота вертикально вниз, если она еще не в этом положении.
До тех пор пока кнопка удерживается нажатой игроком, вызывается подпрограмма move-it, в которой подпрограмма продвигает шаговый двигатель на один шаг. Если кнопка отпущена, то подпрограмма ready обходит подпрограмму move-it. В любом случае ведется обратный отсчет значения переменной waittime, после которого позиция руки робота не может быть откорректирована.
При возврате в главную программу глаза робота мигнут три раза, чтобы показать, что «Андроид» готов к игре.
Для того чтобы определиться с реакцией робота, вызывается подпрограмма strategy, блок-схема которой.
После повторного мигания глазами, подпрограмма считывает состояние ключа выбора программы.
Если ключ разомкнут, то Микроконтроллер PIC переходит к подпрограмме strategy. В ней выбирается случайное число, и используется маска для выделения двух младших разрядов.
Для преобразования результата в перемещение руки, значение (теперь в переменной count) умножается на восемь, чтобы дать 8, 16 или 24.
Это достигается в результате трехкратного циклического сдвига влево переменной count. Восемь шагов двигателя поворачивают вал на 45°, поэтому значение в count приводит к повороту на 45°, 90° или 135°. Эхо значение сохраняется в переменной countcopy для использования в дальнейшем, когда рука робота возвращается в вертикальную позицию. Подпрограмма возвращает управление главной программе с разрядами (умноженными на восемь), сохраненными в переменной count, что определяет высоту поднятия руки.
В альтернативном режиме игры (strategy2) робот повторяет свою успешную игру до тех пор, пока она остается успешной.
Цель данного алгоритма — дать роботу чуть больше, чем средняя вероятность победы. При входе в подпрограмму strategy2 проверяется значение new-count. В первом раунде оно будет нулевым, в силу чего микроконтроллер PIC возвращается в подпрограмму strategyl для выбора случайного значения, которое заносится в count. Если это — не первая игра сеанса, то значение в newcount будет отличным от нуля.
Оно присваивается переменной count и умножается на восемь перед возвратом в главную программу.
Значение в newcount может быть тем, которое привело робота к победе и повторяет его успешную игру.
Однако, если в предыдущей игре робот проиграл, то переменной newccount обычно (однако не всегда) присваивается другое значение в подпрограмме tryagain. В результате в текущей игре робот попробует действовать иначе.
После возврата из подпрограммы strategy микроконтроллер PIC вызывает подпрограмму cycler, которая поворачивает руку робота на число шагов, содержащееся в count. На каждом шаге она обращается к справочной таблице codes и выдает код на шаговый двигатель.
В подпрограмме cycler указатель декрементируется на каждом шаге с тем, чтобы коды считывались из таблицы в направлении снизу вверх.
В подпрограмме cyclel, используемой позже для автоматического опускания руки, указатель инкрементируется на каждом шаге, что дает считывание таблицы сверху вниз.
На этом игра завершается, и робот либо выиграл, либо проиграл. При использовании стратегии strategyl (ключ не замкнут), робот выдает звуковой сигнал и мигает глазами, после чего ожидает от игрока нажатия кнопки для запуска нового раунда.
В случае стратегии strategy2 (ключ замкнут) робот переходит к подпрограмме winlose, в которой ожидает (метка scoring) нажатия Игроком кнопки в случае победы робота. Длительность ожидания устанавливается значением в переменной waittime. Во время ожидания включен зуммер.
Как только кнопка отпущена, countcopy копируется в newcount. Однако это значение в восемь раз превосходит исходное, не станет 01, 10 или 11 (1, 2 или 3 в десятичном виде). Это соответствует выбору ножниц, бумаги или камня в игре, так что результат хода робота в этом случае носит случайный характер.
поэтому разряды 3 и 4 переменной countcopy копируются в разряды о и 1 переменной newcount.
Это восстанавливает корректное значение newcount, приводя программу в состояние готовности к следующему раунду.
Затем микроконтроллер PIC ожидает (метка waiting) нажатия кнопки в течение обратного отсчета значения waittime до достижения им нуля.
Если кнопка нажата, то PIC возвращается в главную программу со счетом побед, сохраненным в newcount.
Если кнопка нажата не будет, то программа переходит к метке result, где newcount инкрементируется, что дает роботу новый вид реакции.
Однако, если предыдущее значение newcount было равно 11, то его инкрементирование приведет к выходу за рамки диапазона.
В этом случае, подпрограмма tryagain выбирает случайное значение. Оно может быть тем же, что и предыдущее, однако есть шанс, что оно будет другим.
В любом режиме программа ожидает нажатия кнопки до того, как опустить руку робота, используя подпрограмму cyclel и декрементируя count.
Программа переходит к nextgame, после чего робот трижды мигает «глазами», а зуммер сигнализирует о начале следующей игры.
Программа, реализующая рассмотренные выше алгоритмы, а соответствующий ей НЕХ-файл.
Источник: qwedr.com