- •Харківський національний університет радіоелектроніки
- •Дипломний проект пояснювальна записка
- •Допускається до захисту
- •Харківський національний університет радіоелектроніки
- •Завдання на дипломний проект (роботу)
- •Календарний план
- •1 Анализ состояния вопросов управления роботами и постановка задач проектирования
- •2 Разработка аппаратной части микроконтроллерной системы управления
- •3 Разработка программного обеспечения микроконтроллерной системы
- •4 Охрана труда и безопасность в чрезвычайных ситуациях
- •5 Экономическая часть
3 Разработка программного обеспечения микроконтроллерной системы
3.1 Выбор среды разработки программного обеспечения
Для работы с Arduino существует множество сред разработки. Они могут быть представлены, как самостоятельные программные пакеты, так и реализованные в виде объединения нескольких программных решений.
Выбор среды разработки производится исходя из требований к среде и ее особенностей: язык программирования, использование библиотек, функциональные возможности, интерфейс, удобство работы и т.д. Ниже рассмотрены несколько наиболее популярных сред разработки ПО для Arduino.
3.1.1 Среда разработки AVR Studio
Программировать Arduino можно с помощью программной среды AVR Studio (рисунок 3.1).
Рисунок 3.1– Среда разработки AVR Studio
AVR Studio – это интегрированная среда разработки для 8- и 32-битных AVR приложений от компании Atmel, работающая в операционных системах Windows. AWR Studio содержит компилятор C/C++ и симулятор, позволяющий отследить выполнение программы. Текущая версия поддерживает все выпускаемые на сегодняшний день контроллеры AVR и средства разработки. AVR Studio содержит в себе менеджер проектов, редактор исходного кода, инструменты виртуальной симуляции и внутрисхемной отладки, позволяет писать программы на ассемблере или на C/C++.
Ключевое окно в AVR Studio это окно исходного текста программы. Когда объектный файл открыт, автоматически создается окно исходного текста программ. В окне отображается код, который выполняется в отладочном окружении (эмуляторе или программном симуляторе) а текстовый маркер всегда находится на строке, которая будет выполнена в следующем цикле.
Пользователь может выполнять программу полностью в пошаговом режиме, трассируя блоки функций, или выполняя программу до места, где стоит курсор. В дополнение можно определять неограниченное число точек останова, каждая из которых может быть включена или выключена. Точки останова сохраняются между сессиями работы.
В окне исходного текста программы выводится информация о процессе выполнения программы. В дополнение, AVR Studio имеет много других окон, которые позволяют управлять и отображать информацию о любом элементе микроконтроллера:
Watch window: значения и адреса переменных;
Trace window: хронология выполнения программы;
Register window: содержимое регистров;
Memory windows: Окна показывают содержимое памяти программ, данных, портов ввода/вывода и энергонезависимого ПЗУ;
I/O window: содержимое регистров ввода/вывода;
Message window: сообщения от AVR Studio;
Processor window: информация о ресурсах микроконтроллера: программный счетчик, указатель стека, регистр статуса и счетчик цикла.
Основные характеристики AWR Studio:
Интегрированный компилятор C/C++;
Интегрированный симулятор;
При помощи плагина возможна поддержка компилятора GCC в виде сборки WinAVR;
Поддержка инструментов Atmel, совместимых с 8-разрядной AVR архитектурой, в том числе AVR ONE!, JTAGICE mkI, JTAGICE mkII, AVR Dragon, AVRISP, AVR ISPmkII, AVR Butterfly, STK500 и STK600;
Поддержка плагина AVR RTOS;
Поддержка AT90PWM1 и ATtiny40;
Интерфейс командной строки с поддержкой TPI.;
Для работы в AWR Studio с Arduino требуется так же установить официальное приложение Arduino IDE, которое будет играть роль загрузчика программы в микроконтроллер. Так же требуется установить расширение Arduino IDE for Atmel Studio 6.1 & 6.2. Затем, произвести настройку расширения, указав директорию, в которой расположена среда Arduino, выбрать плату и указать номер порта, к которому она подключена.
Таким образом, используя загрузчик Arduino IDE, можно писать программы в более функциональной среде AWR Studio.
3.1.2 Среда разработки Arduino IDE
Arduino IDE (Integrated development environment) (рисунок 3.2) – бесплатная программная оболочка, предназначенная для написания программ, их компиляции и программирования аппаратуры Arduino.
Рисунок 3.2– Программная оболочка Arduino IDE
В этой оболочке имеется текстовый редактор, менеджер проектов, препроцессор, компилятор и инструменты для загрузки программы в микроконтроллер. Кроссплатформенная оболочка написана на Java на основе проекта Processing, работает под Windows, Mac OS и Linux.
Язык программирования Arduino является стандартным С++ (используется компилятор AVR-GCC) с некоторыми особенностями, упрощающими написание программ.
Программы, написанные под Arduino, называются sketch и сохраняются в файлах с расширением ino. Эти файлы перед компиляцией обрабатываются препроцессором. Так же существует возможность создавать и подключать к проекту стандартные С++ файлы. Обязательную в С++ функцию main препроцессор Arduino создает сам, вставляя туда необходимые действия. Программист должен обеспечить две обязательные для Arduino функции: Setup и Loop. Первая вызывается только один раз, после подачи питания или сброса платы, когда стартует скетч. Используется для инициализации переменных, определения режимов работы выводов, запуска используемых библиотек и т.д. Вторая выполняется в бесконечном цикле все время работы микроконтроллера и содержит в себе основной алгоритм работы устройства.
В текст программы не обязательно вставлять заголовочные файлы используемых стандартных библиотек. Они добавляются препроцессором Arduino в соответствии с конфигурацией проекта. Однако, пользовательские библиотеки нужно указывать. Менеджер проекта Arduino IDE имеет нестандартный механизм добавления библиотек. Библиотеки в виде исходных текстов на стандартном C++ добавляются в специальную папку в рабочем каталоге IDE. При этом ее название добавляется в список библиотек в меню IDE. Программист отмечает нужные библиотеки, которые затем вносятся в список компиляции.
Arduino IDE не предлагает никаких настроек компилятора и минимизирует другие настройки, что упрощает начало работы для новичков и уменьшает риск проблем.
Закачка программы в микроконтроллер Arduino происходит через предварительно запрограммированный специальный загрузчик (все микроконтроллеры от Arduino продаются с этим загрузчиком). Загрузчик создан на основе Atmel AVR Application Note AN109. Он может работать через интерфейсы RS-232, USB или Ethernet в зависимости от состава периферии конкретной процессорной платы. На рисунке 3.3 схематично показана структура системы программирования Arduino.
Рисунок 3.3– Структура системы программирования Arduino
AVR GCC - это бесплатный компилятор с языка C/C++, в результате компиляции получается двоичный файл программы пользователя с расширением HEX.
AVRDUDE - это бесплатная утилита программатора, которая передает загрузчику микроконтроллера код программы пользователя в виде HEX-файла.
Загрузчик – это небольшая программа, которая всегда находится в старших адресах памяти микроконтроллера. Благодаря загрузчику максимально упрощен процесс записи программы в память микроконтроллера, а пользователю не требуется использовать программатор и разбираться в технологии прошивки микроконтроллера.
Таким образом, среду Arduino IDE можно охарактеризовать, как достаточно простой и удобный для пользователя инструмент работы с Arduino. Для большинства электронных устройств и микросхем написаны готовые библиотеки, а так же хорошо описан язык программирования и пользователю доступны множество примеров программ. Поэтому данная среда была выбрана для разработки программного обеспечения микроконтроллерной системы.
3.2 Разработка алгоритмов работы микроконтроллерной системы
Алгоритм функционирования системы можно условно разделить на два блока: режим следования линии и режим объезда препятствия.
Режим следования линии осуществляется за счет показаний датчиков линии и подразумевает, что на пути робота на определенном расстоянии нет препятствий. В этом случае, робот изначально устанавливается на поверхность таким образом, чтобы линия оказалась между датчиками. Затем, осуществляется поочередный опрос левого и правого датчиков линии. Используемые датчики выдают логический ноль, когда «видят» черное и единицу, когда «видят» белое. На прямой робот должен пропускать линию между сенсоров. Таким образом, если показания датчиков говорят об отсутствии линии под ними, то робот едет прямо. В случае, когда линия уходит в сторону, соответствующий датчик дает об этом знать. Так, при повороте траектории направо, правый сенсор наезжает на линию и начинает показывать ноль. При повороте налево, ноль показывает левый сенсор. В таких случаях происходит корректировка движения робота. Корректировка заключается в повороте робота в сторону соответствующую датчику наехавшему на линию и продолжается до тех пор, пока линия снова не окажется между датчиками. Поворот робота в стороны реализуется путем остановки соответствующего колеса при вращающемся противоположном колесе. Например, для поворота влево следует остановить левое колесо и пустить правое, в ином случае – наоборот. Таким образом, данный алгоритм упрощенно можно изобразить схемой (рисунок 3.4)
Рисунок 3.4– Алгоритм движения по линии
В режим объезда препятствия система входит в случае, если показания с дальномеров, направленных в сторону движения, указывают на наличие препятствия на определенном расстоянии от робота. Данное расстояние зависит от размеров робота и выбирается таким образом, чтобы при возникновении препятствия робот мог безопасно проехать мимо него. Так как в передней части робота установлены два дальномера так, что их общий сектор обзора равен 60°, то для робота диаметром L было выбрано такое же расстояние реагирования. Как видно по схеме (рисунок 3.5), полученный зазор K значительно больше L и удовлетворяет данным требованиям.
Рисунок 3.5– Выбор расстояния реагирования дальномеров
При входе в режим объезда препятствия система сравнивает показатели двух передних дальномеров и выбирает, в какую сторону следует выполнять объезд, исходя из того, где расстояние до препятствия больше. Затем, робот разворачивается на месте в соответствующую сторону, пока не «увидит» препятствие боковым датчиком (рисунок 3.6). После чего, контролируя боковым датчиком расстояние N до препятствия, робот движется вдоль него, выполняя объезд.
Рисунок 3.6– Алгоритм входа в режим объезда препятствий
Графически вход в режим объезда представлен на рисунке 3.7
|
|
а) |
б) |
Рисунок 3.7 – Вход в режим объезда препятствия: а) возникновение препятствия и выбор стороны объезда; б) разворот боковым датчиком к препятствию
Во время движения робота вдоль препятствия робот постоянно удерживается от него на некотором заданном расстоянии N. Происходит это благодаря постоянному опросу бокового датчика, направленного к препятствию. На основании показаний датчика происходит корректировка траектории робота. В случае, когда расстояние меньше заданного – он отъезжает от препятствия, если больше – приближается.
Корректировка движения основана на регулировании соотношений скорости моторов методом широтно-импульсной модуляции (ШИМ), который дает возможность регулировать радиус, следовательно, и крутизну дуги траектории (рисунок 3.8).
Рисунок 3.8 – Траектории движения робота и их радиусы
Во время движения колеса описывают окружности радиусами R и R+M, где М – расстояние между колесами. Тогда длины окружностей, которые описывают колеса:
|
|
Обозначим: t - время проезда окружностей
V1, V2 – скорости вращения колес
Тогда время проезда окружностей можно выразить через скорости вращения колес:
|
|
Поскольку время проезда окружностей одинаково, то приравнивая полученные формулы, можно вывести пропорцию:
|
|
Таким образом, чем выше скорость V2 по отношению к V1, тем меньше радиус описываемой дуги и наоборот.
Так как скорость вращения двигателей зависит от приложенного к обмотке якоря напряжения, то для ее регулирования удобно использовать широтно-импульсную модуляцию, меняя скважность импульсов (рисунок 3.9).
Рисунок 3.9 – Зависимость среднего напряжения от скважности
Зависимость среднего напряжения от величины скважности является линейной:
|
|
где Т – период импульсов, τ – длительность импульса, S – скважность.
Таким образом, во время движения вдоль препятствия, робот может контролировать траекторию, регулируя скорости двигателей, в зависимости от расстояния до препятствия (рисунок 3.10). Так, при нормальном расстоянии Snorm, скорости обоих двигателей равны и робот едет прямо параллельно препятствию. При сближении с препятствием, скорость Vk двигателя расположенного на стороне датчика повышается, а противоположного Vs – снижается. Тем самым робот начинает отдаляться от препятствия, возвращаясь к нормальному расстоянию. При отдалении от препятствия скорости двигателей регулируются наоборот.
Рисунок 3.10 – Зависимость скорости вращения двигателей от расстояния до препятствия
В данном режиме, помимо контроля расстояния боковым датчиком, так же происходит считывание данных с передних датчиков для того, чтобы в процессе объезда робот контролировал пространство впереди себя. Этот процесс реализован подобно тому, как робот входит в режим объезда: при приближении к препятствию впереди, робот разворачивается в ту же сторону, что и при входе в режим объезда и продолжает двигаться вдоль препятствия.
В процессе объезда происходит опрос датчиков линии, для определения момента возвращения робота на линию и его дальнейшего движения вдоль нее. Алгоритм объезда препятствия представлен на рисунке 3.11.
Рисунок 3.11 – Алгоритм объезда препятствия
Процесс возвращения робота на линию зависит от двух факторов: стороны, в которую робот ушел с линии перед объездом и стороны, с которой робот обнаружил линию после объезда.
По возвращении на линию, важной задачей является направить робота в нужном направлении, чтобы он продолжал движение по траектории. После объезда робот может обнаружить линию как датчиком, расположенным на стороне объезда, так и противоположным датчиком (рисунок 3.12).
|
|
а) |
б) |
Рисунок 3.12 – Обнаружение линии при объезде с левой стороны: а) правым датчиком; б) левым датчиком
В случае, когда робот наезжает на линию датчиком, противоположным стороне объезда, он начинает двигаться вперед, пока линию не «увидит» датчик, расположенный на стороне объезда, после чего робот переходит в режим следования линии.
В ином случае, когда робот наезжает на линию датчиком, соответствующим стороне объезда, он движется вперед, пока противоположный датчик не окажется над линией. Затем робот выполняет разворот на месте в сторону соответствующую стороне объезда, пока датчик на этой же стороне не «увидит» линию и затем осуществляется переход в режим следования линии. Данный алгоритм представлен на рисунке 3.13.
Р
исунок
3.13 – Алгоритм возврата на линию
3.3 Программная реализация алгоритмов
3.3.1 Инициализация портов и настройка их режима работы
Так как к выводам микроконтроллера подключены различные датчики и исполнительные механизмы, то их следует должным образом настроить.
Каждый датчик линии подключен к одному выводу микроконтроллера, который следует настроить на ввод информации с датчиков. Ультразвуковые сенсоры используют по два вывода микроконтроллера: один для запуска процесса измерения (настраивается на выход), другой для считывания информации с датчика (настраивается на вход). Для управления двигателями требуется по два вывода, настраиваемых на выход, отвечающих за направление и скорость вращения двигателей.
Процедура инициализации и настройка режима работы портов производится с помощью стандартной команды pinMode:
pinMode(41, INPUT); //правый датчик линии
pinMode(43, INPUT); //левый датчик линии
pinMode(4, OUTPUT); //направление левого колеса
pinMode(5, OUTPUT); //enable левого колеса
pinMode(6, OUTPUT); //enable правого колеса
pinMode(7, OUTPUT); //направление правого колеса
pinMode(30, OUTPUT); //trig переднего левого датчика
pinMode(31, INPUT); //echo переднего левого датчика
pinMode(32, OUTPUT); //trig переднего правого датчика
pinMode(33, INPUT); //echo переднего правого датчика
pinMode(34, OUTPUT); //trig бокового левого датчика
pinMode(35, INPUT); //echo бокового левого датчика
pinMode(36, OUTPUT); //trig бокового правого датчика
pinMode(37, INPUT); //echo бокового правого датчика
Пример 3.1 – Процедура инициализации портов
3.3.2 Функция опроса датчиков линии
Опрос датчиков линии осуществляется с помощью команды digitalRead. Это стандартная функция Arduino, возвращающая значение логического уровня сигнала на выводе. Аргументом функции является номер опрашиваемого вывода:
digitalRead(41); //опрос правого датчика линии
digitalRead(43); //опрос левого датчика линии
Пример 3.2 – Команды опроса датчиков линии
3.3.3 Функция опроса ультразвуковых дальномеров
Опрос ультразвуковых дальномеров реализуется путем удержания высокого уровня на выходе Trig в течении 10 мкс, после чего с выхода Echo считывается импульс длительностью, пропорциональной расстоянию до препятствия. Ниже показана функция, реализующая опрос:
int GetDistance(int TrigPin){
int duration;
int cm;
digitalWrite(TrigPin, HIGH); //сигнал на Trig
delay(10); //в течении 10 мкс
digitalWrite(TrigPin, LOW); //убираем сигнал
duration=pulseIn(TrigPin+1, HIGH); //длительность импульса на trig+1 выходе (echo)
cm=duration/58; //перевод в сантиметры
return cm; //возвращаемое значение
}
Пример 3.3 – Функция опроса дальномеров
3.3.4 Процедуры управления колесами
Для каждого колеса была написана своя функция управления, которая в качестве аргументов принимает два значения: направление вращения и скорость вращения. Синтаксис данных функций показан ниже:
void LeftMotor(int dir, int speed){ //левый мотор
if (dir>0)
digitalWrite(4, HIGH); //вращение прямо
else
digitalWrite(4, LOW); //вращение обратно
analogWrite(5, speed); //выставляем скорость
}
void RightMotor(int dir, int speed){ //правый мотор
if (dir>0)
digitalWrite(7, HIGH); //вращение прямо
else
digitalWrite(7, LOW); //вращение обратно
analogWrite(6, speed); //выставляем скорость
}
Пример 3.4 – Процедуры управления колесами
3.3.5 Процедура выбора стороны объезда
Показателем стороны объезда является флаг DSFlag, который принимает три значения: 0 – при отсутствии впереди робота каких либо препятствий и необходимости совершения объезда, -1 – при объезде слева и 1 – при объезде справа. Значение флага определяют показания передних дальномеров робота. Ниже приведен программный код данной процедуры:
void GetFlag(){
int left = GetDistance(30);//чтение левого датчика
int right = GetDistance(32);//чтение правого датчика
if(left<FDist) DSFlag=1;//сравнение показателя левого дальномера с расстоянием реагирования и установка флага
else if(right<Fdist) DSFlag=-1; ;//сравнение показателя левого дальномера с расстоянием реагирования и установка флага
else DSFlag=0;
return;}
Пример 3.5 – Процедура выбора стороны объезда
3.3.6 Процедура движения вдоль линии
Движение вдоль линии реализуется с помощью функций опроса датчиков линии и процедуры управления колесами. Данная функция будет выполняться, до тех пор, пока впереди робота нет препятствий. Ниже приведен программный код данной процедуры:
void LineTrace(){
while(DSFlag==0){ //выполнять пока нет препятствия
GetFlag();//установить флаг
boolean left = digitalRead(43);//чтение левого датчика
boolean right = digitalRead(41);//чтение правого датчика
if(left==right){//если значения равны (оба на белом)
LeftMotor(1, 128);//движение прямо
RightMotor(1, 128);
}
else if(left){//если левый датчик на линии
LeftMotor(1, 0);//поворот влево
RightMotor(1, 128);
}
else{//в другом случае (на линии правый датчик)
LeftMotor(1, 128);//поворот вправо
RightMotor(1, 0);
}
}
}
Пример 3.6 – Процедура движения вдоль линии
3.3.7 Процедура схода с линии перед объездом
Данная процедура выполняется при встрече робота с препятствием и производит разворот робота боковым дальномером к препятствию. Для выбора стороны разворота, в качестве аргумента функция принимает значение DSFlag.
void Rotation(int DSFlag, int SNDist){
int LMDir; //направление левого мотора
int RMDir; //направление правого мотора
int USPin; //пин опрашиваемого датчика
int SideDist; //значение с опрашиваемого датчика
if (DSFlag<0){ //если DSFlag = -1 (разворот влево)
LMDir=0; //левый мотор вращаем назад
RMDir=1; //правый вперед
USPin=36; //опрашиваем правый боковой дальномер
}else{ //иначе (DSFlag = 1, разворот вправо)
LMDir=1; //левый мотор вращаем вперед
RMDir=0; //правый мотор вращаем назад
USPin=34; //опрашиваем левый боковой дальномер
}do{ //выполнять
LeftMotor(LMDir, 64); //пуск левого мотора со скоростью 64
RightMotor(RMDir, 64); //пуск правого мотора со скоростью 64
SideDist=GetDistance(USPin); //получение расстояния
} while (Side dist>SNDist); //пока полученное расстояние больше нужного
}
Пример 3.7 – Процедура схода с линии перед объездом
3.3.8 Процедура возвращения на линию
Данная процедура выполняется при встрече робота с линией в процессе объезда препятствия и производит разворот робота в нужном направлении для дальнейшего движения по траектории. В качестве аргумента функция принимает значение DSFlag.
void BackToLine(int DSFlag){
int LMDir; //направление левого мотора
int RMDir; //направление правого мотора
int FLinePin;//пин датчика наехавшего на линию
int SLinePin;//пин другого датчика
if(DSFlag==-1){//если объезд совершался слева
FLinePin=41;//пин правого датчика
SLinePin=43;//пин левого датчика
LMDir=0;//левый мотор назад
RMDir=1;//правый вперед
}else{//если объезд совершался справа
FLinePin=43;//пин левого датчика
SLinePin=41;//пин правого датчика
LMDir=1;//левый мотор вперед
RMDir=0;//правый назад
}
if(digitalRead(FLinePin)==HIGH){//если над линией датчик с пином FLinePin
do{//движение вперед
LeftMotor(1, 64);
RightMotor(1, 64);
}while(digitalRead(SLinePin)==LOW);//пока над линией не окажется второй датчик
}else{//если над линией датчик с пином SLinePin
do{//движемся вперед
LeftMotor(1, 64);
RightMotor(1, 64);
}while(digitalRead(FLinePin)==LOW);//пока над линией не окажется второй датчик
do{//затем вращаемся в сторону
LeftMotor(LMDir, 64);
RightMotor(RMDir, 64);
}while(digitalRead(SLinePin)==LOW);//пока над линией не окажется первый датчик
}
DSFlag=0;//возвращение на линию
}
Пример 3.8 – Процедура возвращения на линию
3.3.9 Процедура движения вдоль препятствия
В данной процедуре робот движется вдоль препятствия, удерживая расстояние от него в пределах SNDist. Кроме того, происходит контроль дальномеров впереди робота и датчиков линии. В качестве аргумента процедура принимает значение DSFlag, для выбора опрашиваемого датчика.
void AlongMove(DSFlag){
int USPin;//пин опрашиваемого датчика
int SideDist;//расстояние сбоку
int FrontDist; //расстояние впереди
int LMSpeed;//скорость левого мотора
int RMSpeed;//скорость правого мотора
int LMDir;//направление левого мотора
int RMDir;//направление правого мотора
while ((digitalRead(41)*digitalRead(43))==0){//пока не видим линию, выполняем
if(DSFlag==-1){//если объезд слева
USPin=36;//опрашиваем правый боковой дальномер
LMDir=1; //направление маневра в случае препятствия
RMDir=0;
}else{//если объезд справа
USPin=34;//опрашиваем левый боковой датчик
LMDir=0; //направление маневра в случае препятствия
RMDir=1;
}
if(GetDistance(30)<GetDistance(32)){//присвоение меньшего значения с передних дальномеров
FrontDist=GetDistance(30);
}else{
FrontDist=GetDistance(32);
}
if(Frontdist<10){//если в пределах 10 см препятствие
while(GetDistance(USPin)>10){//разворачиваемся к нему боком на месте
LeftMotor(RMDir, 32);
RightMotor(LMDir, 32);
}
}else{//если впереди препятствия нет
SideDist=GetDistance(USPin);//считываем показания бокового датчика
if(Side dist>(SNDist+SRange)) {если расстояние превышает максимальное (выезд за препятствие)
while(GetDistance(USPin)>(SNDist+SRange)){//то поворачиваемся к препятствию
LeftMotor(LMDir, 32);
RightMotor(RMDir, 32);
}
}else if (SideDist<(SNDist-SRange)){//если расстояние меньше минимального
while(GetDistance(USPin)<(SNDist-SRange)){//разворачиваемся от препятствия
LeftMotor(RMDir, 32);
RightMotor(LMDir, 32);
}
}else{//если расстояние в пределах нормы
LMSpeed=64-(6.4*(SideDist-SNDist)*DSFlag);//расчет скоростей для моторов
RMSPeed=64+(6.4*(SideDist-SNDist)*DSFlag);
LeftMotor(1, LMSpeed);//вращение моторов с заданными скоростями
RightMotor(1, RMSPeed);
}
}
}
Пример 3.9 – Процедура движения вдоль препятствия
Используя разработанные процедуры и функции, была разработана управляющая программа для микроконтроллерной системы. Листинг программы представлен в Приложении А.
