Устройства управления роботами, схемотехника и программирование (М. Предко, 2004). Устройства управления роботами, схемотехника и программирование. Устройствауправления роботамисхемотехника и микроконтроллеров picmicro
Скачать 6.79 Mb.
|
Рис. 4.S3. Схема для мыши Фоторезистор Инфракрасный светодиод Разъем Левый инфракрасный детектор Разъем для подключения левого двигателя резистор для балансировки фоторезисторов Светодиод- индикатор переключателя Правый инфракрасный детектор Разъем для подключения правого двигателя Микросхема L293D Микроконтроллер Разъем для подключения батареек Рис. Внешний вид печатной платы блока управления Таблица Список использованных элементов Обозначение Элемент Примечание Микроконтроллер Микросхема стабилизатора напряжения 294 Устройства управления роботами Таблица Список использованных элементов (окончание) U5 CR1 CR2 CR3 R4, R5 R2, R3, R8, R9 CDS1, CDS2 С7 Элемент Инфракрасный детектор Светодиод Светодиод 1N914 10 0,25 Вт 470 Ом; 0,25 Вт 100 Ом; 0,25 Вт Фоторезисторы, при освещении мкФ 0,01 мкФ Керамический резонатор на 4 МГц, со встроенными Р/С- или другой совместимый (три вывода) Любой видимого диапазона Любой инфракрасный Любой кремниевый рассчитанный на ток 200 мА При освещении должны уменьшать свое сопротивление Конденсаторы любого типа Оксидные конденсаторы Оксидный конденсатор Конденсаторы любого типа Для генератора тактовых импульсов микроконтроллера Модель мыши фирмы плата, монтажные провода, батарейка 9 В В скобках указаны отечественные аналоги, добавленные при переводе. - Во время работы двигателей потребляемый ток увеличивается; как следствие, на внутреннем сопротивлении батарейки падает достаточно большое напряжение. Чтобы свести эти потери к минимуму, надо использовать достаточно качественную щелочную батарейку с низким внутренним сопротивлением. Чтобы обеспечить микроконтроллер стабильным питанием, используем фильтрующий конденсатор большой емкости. Схема источника питания в данном случае далека от идеальной, но практика показала, что со своей задачей она вполне справляется. И контактные датчики, и дистанционное управление работают без заметных перебоев. Когда будете воспроизводить эту конструкцию, расположите панель для мик- роконтроллера в таком месте, откуда его можно было бы без труда извлечь, на- пример в левой задней части робота. Поверьте, нет ничего более обидного, когда прекрасно работающую схему приходится разбирать только из-за того, что иначе невозможно вытащить микроконтроллер для перепрограммирования! При монтаже клемм на двигатель необходимо следить за тем, чтобы клемма со знаком «плюс» располагалась со стороны передней части робота, а положитель- ный вывод двигателя соединялся с ней красным проводом. Отрицательный про- вод должен быть черным: в противном случае легко перепутать провода при на- ладке схемы, а это может привести самое малое к тому, что робот поедет назад (если вообще сможет куда-либо ездить). Также имеет смысл делать провода как Подключение к микроконтроллеру периферийных устройств 295 можно более чтобы уменьшить риск их наматывания на колеса и дру- гие движущиеся части. Если вы читали главу без пропусков, у вас не должен вызвать затруднений монтаж фоторезисторов, а также инфракрасного датчика системы дистанционно- го управления и На схеме с рис. 4.83 легко узнать проек- ты, описанные выше в этой главе. Текст управляющей программы вы найдете в файле // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 28 апреля 2002 - модификация модели мыши фирмы Tamiya. Инфракрасный обнаружитель объектов частотой 38 кГц). Дистанционное управление на основе инфракрасного детектора фирмы Sony. Для индикации используется светодиод. Формат пакета данных: Стартовый бит 1 О + + I I I I I I | мс | | мс | 1,76 мс | I 300 I 440 I Замечания по аппаратным средствам: Микроконтроллер PIC16F627 работает на частоте 4 МГц. Используется внешний тактовый генератор. Подключение выводов RAO - правый инфракрасный детектор для обнаружения объектов (опрашивается программно); RA4 - светодиод для индикации принятой команды дистанционного управления; RBO - левый инфракрасный детектор для приема команд дистанционного управления фирмы Sony и для обнаружения обьектов по положительному перепаду); RB1 - левый двигатель (вывод RB2 - левый двигатель (вывод R83 - светодиод инфракрасного обнаружителя объектов; RB4 - левый фоторезистор; RB5 - правый фоторезистор; RB6 - правый двигатель (вывод RB7 - правый двигатель (вывод 296 Устройства управления роботами // Глобальные переменные и константы: RTC = 0; // Счетчик реального времени. // Определения констант для команд // дистанционного управления. «define «define remote9 unsigned int unsigned int = unsigned char unsigned int Ox06EF OxOFEF Ox09EF OxOEEF Ox036F OxOF6F Ox076F Ox022F OxOD6F Ox056F 0; = 0; volatile char LeftCollision = 0; volatile char = 0; // Входные данные. // Количество входных символов. // Есть объект слева? // Есть справа? volatile char ADCState 0; volatile char ADCDlay 1; // Текущее состояние конечного // автомата опроса фоторезисторов. // Задержка 50 мс между срабатываниями // конечного volatile unsigned char LeftADC = OxOFF; // Состояние левого фоторезистора. volatile unsigned char RightADC = OxOFF; // Состояние правого фоторезистора. goStop 0x030 goForward 0x072 goReverse OxOB4 turnLeft 0x074 «define turnRight OxOB2 1 «define 0 LeftReverse -1 RightForward 1 RightStop 0 RightReverse -1 unsigned char = goStop; unsigned char PWMDuty = 15; unsigned char = 0; unsigned char 1; char = 0; // Стоп двигатели! // Вперед! // Реверс! // Левый двигатель, реверс! // (поворот налево). // Правый двигатель, реверс! // (поворот направо). // Замечание: на выводах // RB4/RB5 - высокий уровень. // Левый двигатель, вперед! // Левый двигатель, стоп! // Левый двигатель, реверс! // Правый двигатель, вперед! // Правый двигатель, стоп! // Правый двигатель, реверс! // Состояние двигателей. // Флаг для индикации состояния. Подключение к микроконтроллеру периферийных устройств 297 // Слово PIC16F627 CONFIG(Ox03F21); Unsupported flendif with external XT oscillator selected // Для PIC16F627: // внешний тактовый генератор XT, // RA6/RA7 используются для ввода-вывода, // внешний сигнал сброса, // таймер включен, // сторожевой таймер // защита кода отключена, // детектор включен. selected // Обработчик прерываний: void interrupt char temp; if { = 0; // Обработчик прерываний от таймера // Сбросить флаг прерываний от таймера TMRO. // Инкремент счетчика реального времени. // Здесь можно разместить дополнительный код // для обработки прерываний от таймера TMRO. // Узнать состояние двигателей и выключить их: PORTB temp = (PORTB & 0x039) | 0x030; // Проверка на потерянный пакет данных и останов до конца // текущего пакета: if { // Есть входной пакет? = 13; = 0; // Ждем 12 информационных // импульсов и конец стартового. // Разрешение прерываний // по изменении сигнала. } else if (DatalnCount == 0) { // Обнаружение объектов. TRISB3 = 0; // Разрешение выхода while (TMRO < 64); // В течение 64 мс. if (!RBO) // Если низкий - обнаружен // объект if (LeftCollision < 3) // Ждать троекратного // срабатывания. LeftCollision++; else; else LeftCollision = 0; if // Если уровень низкий - обнаружен // справа. if(RightCollision < 3) // Ждать троекратного // 298 Устройства управления роботами . else; else = 0; = 1; // Программная генерация для управления // скоростью вращения if == 0) // Нулевая ширина импульсов? else if (PWMDuty == 29) // Ширина импульса равна периоду? PORTB = temp | else // Нечто среднее? if <= PWMDuty) PORTB = temp | else; if == 30) PWMCycle = 0; // Индикация: if (--OpnCount == { // Опрос фоторезисторов. OpnCount = 1; PORTB = (PORTB & 0x039) | (motorState = goStop); if (LeftADC < RA4 0; // Зажечь светодиод - // источник света else RA4 = 1; // Потушить светодиод - // источник света слева. // Прием команд дистанционного управления: if (OataTime) { if == 0) { // Есть команда. = 12; // Ждать 12 импульсов. = 0; } else { // Прием очередного бита. = Dataln 1; if ((DataTime > 225) (DataTime < { // Получена 1. if == 0) { OpnCount = 200; // if (Dataln == { motorState = } else if (Dataln == { motorState = turnLeft; } else if (Dataln == remote6) ( motorState = turnRight; } else if (Dataln == { motorState = goReverse; Подключение к микроконтроллеру периферийных устройств 299 } else if (Dataln == { if < 29) PWMDuty++; else; } else if (Dataln == { if (PWMDuty '!= 0) . else; } else if (Dataln == remotePower) { • ExecuteFlag = 1; = goStop; OpnCount // Стоп. } else { ExecuteFlag = 0; motorState = goStop; OpnCount = 1; // Стоп. } else if 375) < { // Получен 0. if == 0) { OpnCount = 200; // if (Dataln == { motorState = } else if (Dataln == { motorState = turnLeft; } else if (Dataln == { motorState = turnRight; } else if (Dataln == { motorState = goReverse; } else if (Dataln == remoteVolUp) { if (PWMDuty < 29) PWMDuty++; else; } else if (Dataln == remoteVolDown) { (PWMDuty != 0) else; • . } else if (Dataln == remotePower) ExecuteFlag = 1; motorState = goStop; OpnCount = 1; // Стоп. } else ExecuteFlag = 0; motorState = goStop; OpnCount 1; // Стоп. } else if 12) // Ошибка. DatalnCount = 0; 300 Устройства управления роботами DataTime = 0; // Все сначала. // Задержка: += 0x0100; // Проверка на потерянный импульс: if (CurrentRTC > DatalnCount = 0; // Сброс. Ждать следующей команды. // Конечный автомат для работы с if { // Если не принимается if (ADCState == 0) { // Начальная if (--ADCDlay == 0) ADCState++; } else if (ADCState == 1) { // Подать импульс на обе (1 мс). = TRISB4 0; TRISB5 = 0; 0x030; // Разрешение прерываний // по изменении сигнала. // Переход к следующему // состоянию через 1 мс. } else if (ADCState == 2) { TRISB4 = 1; // Прекратить левый импульс. temp = RBIF = 0; RBIE = 1; } else if (ADCState == 3) { LeftADC = OxOFF; temp = PORTB; RBIF = 0; // Запрещение прерываний RBIE = 0; // по изменении сигнала. ADCState++; } else if (ADCState == 4) { TRISB5 = 1; // Прекратить правый импульс. temp = PORTB; RBIF = 0; // Разрешение прерываний RBIE = 1; изменении сигнала. ADCState++; } else if (ADCState == 5) { RightADC = OxOFF; temp = PORTB; RBIF = 0; // Запрещение прерываний RBIE = 0; // по изменении сигнала. ADCDlay = 50; ADCState = 0; } // Конец обработчика от таймера. // Здесь можно разместить другие обработчики прерываний. if (INTF) { // Обработка прерываний по изменении // сигнала на входе RBO/INT. DataTime = CurrentRTC + Время для текущего бита. Подключение к микроконтроллеру периферийных устройств 301 CurrentRTC = - // Время для следующего бита. INTF = 0; // Сброс флага прерываний. } // Конец обработчика прерываний по изменении сигнала на RBO/INT. if (RBIF) { // Обработка прерываний по изменении // сигнала на входных линиях порта PORTB. if (ADCState == 3) { LeftADC = TMRO; ADCState++; } else { TMRO; ADCDlay 50; ADCState 0; // Для левого // Для правого фоторезистора. // Повторять каждые 50 мс. } temp PORTB; RBIF = 0; // Запретить прерывания по изменении RBIE = 0; // сигнала на входах PORTB. // Конец обработки прерываний по изменении // сигнала на входных линиях порта PORTB. } // Конец обработчика прерываний. // Задержка на миллисекунд. // void msecs) int valueDlay; = RTC + msecs + 1; // Время окончания while (valueDlay != RTC); // Ждать. } // Конец функции void state ) // Установка состояния светодиода. if (state) RA4 0; else RA4 = 1; // Включить светодиод. // Выключить светодиод. } // Конец функции LEDOutput. int // Опрос состояния левого фоторезистора. { return LeftADC; > int // Опрос состояния правого фоторезистора. { return RightADC; } int // Опрос состояния левого контактора. if (LeftCollision 3) return 1; // Есть else 302 Устройства управления роботами return 0; // Нет касания. } int // Опрос состояния правого контактора. < if == 3) return 1; // Есть else return 0; // Нет касания. } void LeftMotor(int Movement, int Speed) // Управление левым двигателем. { switch (Movement) { case 1: // Вперед. (motorState & OxOF9) + 2; break; case 0: // Стоп. motorState = motorState & break; case -1: // Назад. motorState = (motorState & OxOF9) + 4; break; Speed; } void RightMotor(int Movement, int Управление правым двигателем. { switch (Movement) { case // Вперед. motorState = (motorState & Ox03F) + 0x040; break; case 0: // Стоп. motorState = motorState & break; case -1: // Назад. motorState = (motorState & Ox03F) + 0x080; break; > PWMDuty = Speed; } // Главная программа: void main(void) OPTION = // работает с таймером TMRO, // коэффициент деления 1:4. TMRO = 0; // Начальный сброс таймера TOIE = 1; // прерываний от таймера TMRO. GIE = 1; // Разрешение обработки прерываний. Подключение к микроконтроллеру периферийных устройств 303 // Здесь можно разместить код верхнего уровня. INTEDG = 1; CCPR1L = 13; PR2 26; = 0; T2CON = CHCON = 0x007; PORTA = 0x010; TRISA = OxOEF; PORTB = 0x000; = 0x039; while (1 == 1) { if // Прерывания вырабатываются по положительному // перепаду сигнала на выходе RBO/INT. // Ширина равна 50% периода. // Разрешить работу модуля // При частоте 38 кГц длительность // периода равна 26 // Сброс таймера TMR2. // Включить таймер TMR2, // коэффициент 1:1. // Выключить компараторы порта PORTA. // RA4 - выход // (светодиод пока не горит). // RB7/RB6 и RB2/RB1 - выходы. // Бесконечный цикл. // Здесь можно разместить код для управления // действиями робота. } else { // Здесь можно разместить код для сброса // робота в начальное состояние. } // Конец цикла } // Конец главной программы. Используя эту программу в качестве основы, можно поэкспериментировать со следующим набором функций: int // Опрос состояния левого // детектора столкновений. // Опрос состояния правого // детектора // Детекторы могут быть контактными или int // Опрос состояния левого int // Опрос состояния правого фоторезистора. // Фоторезисторы могут быть включены по схеме делителя напряжения // или в виде RC-цепочки. void Movement [ , int Speed ] ); void Movement [ , int Speed ] ); // Управление // левым двигателем. // Управление // правым двигателем. // Второй параметр (Speed) доступен при использовании инфракрасного // пульта дистанционного управления, но недоступен для радиоуправления. void State); // Включить/выключить светодиод. 304 Устройства управления роботами void * Message); // Вывод сообщения на void Dlaydnt // Функция задержки. При использовании инфракрасного пульта дистанционного управления я обыч- но назначаю для кнопки 2 команду «Вперед», 4 и 6 соответствуют поворотам вле- во и вправо, 8 - «Назад» (реверс обоих двигателей), 5 - «Стоп» (остановка обоих двигателей). С помощью кнопки, которая в обычных применениях управляет громкостью звучания телевизора, можно изменять скорость движения робота. Ширина им- пульса генерируемого в нашей программе для управления обоими двигателями, по умолчанию установлена равной половине периода (50%). Если довести это значение до 100%, то робот начнет довольно быстро носиться по ком- нате. К сожалению, в таком режиме батарейки хватит ненадолго. В программе предполагается, что для начала выполнения кода биологического уровня надо нажать кнопку включения питания на пульте дистанционного управ- ления. Для отключения кода следует подать сигнал «Стоп» (кнопка 5) или какую- либо другую прямую команду. Обеспечение или отключение в произвольное вре- мя «самостоятельности» робота может потребоваться для того, чтобы сначала с помощью дистанционного управления подвести его к какому-либо месту, затем запустить для проверки биологический код, а если робот попадет в трудную ситу- ацию, снова взять управление на себя. Следует заметить, что функция, выполнение которой наиболее трудно обеспе- чить, - это именно дистанционное управление. Если вы достаточно придирчиво испытаете робота в действии, то обнаружите, что при нажатии на кнопки пульта он может начать двигаться рывками и вести себя так, будто вместо одной коман- ды вы подали сразу несколько. Дело в том, что при работе двигателей присутствует большое число помех, оказывающих влияние на функционирование всех остальных подсистем, в том числе и приемника команд дистанционного управления. В следующей главе мы обсудим некоторые возможные пути решения подобных проблем. Для проверки работы механических и световых датчиков, а также инфракрас- ного обнаружителя объектов надо сначала остановить оба двигателя, после чего подождать как минимум 60 мс, чтобы дать возможность управляющей программе опросить состояние всех датчиков. Это время необходимо для наиболее медли- тельных входных устройств - с фоторезисторами. Для проверки дат- чиков обнаружителя объектов достаточно и 10 мс. А еще лучше выключать двигатели на 6 мс каждый раз, пока продолжается очередной цикл работы с фоторезисторами и датчиком обнаружителя объектов. Электродвигатели, входящие в комплект рассматриваемой модели, рассчита- ны на напряжение 1,5 В, поэтому для работы с нашей 9-вольтовой батарейкой они имеют слишком маленькое сопротивление и в результате потребляют слишком большой ток. Вы можете убедиться в том, насколько велики потери напряжения на электронных ключах микросхемы L293D и как сильно она греется при работе. Если использовать электродвигатели, рассчитанные на более высокое напря- жение, то батарейка прослужит намного дольше, а нагрев микросхемы L293D рез- ко уменьшится. |