Модераторы
174 сообщений
Мужчина
|
Сразу хочу отметить, все мои материалы в этой теме предназначены исключительно для публикации на ресурсах сайта www.servodroid.ru. Любое цитирование, копирование и т.п. на сторонних ресурсах рассматривается как нарушение интеллектуальной собственности. Ссылки же на данную тему допускаются.
|
|
|
|
|
Модераторы
174 сообщений
Мужчина
|
Фрагмент кода, позволяющий реализовать программпую генерацию ШИМ-сигналов для управления сервоприводами (писался для AtTiny2313, но подвергается переделке под другие микроконтроллеры):
Описание: Это уже вторая версия данного кода, которая реализует программную генерацию ШИМ-сигналов с частотой 50 Гц. Длительностью импульсов составляет от 500 мкс до 2500 мкс с шагом 10 мкс, что соответствует 200 возможным положениям качалки сервопривода. Задание необходимого положения происходит через регистры r0, r1 и так далее - по числу сервоприводов, каждый регистр отвечает за положение качалки одного из сервоприводов.
Как это работает: В генерации задействован таймер 0, работающий в CTC-режиме, это значит, что обработчик таймера будет вызываться через равные промежутки времени, указанные при инициализации и равные 10 мкс. С каждым вызовом обработчика происходит увеличение переменной-счетчика, принимающей значения от 0 до 2000 по кругу (естественно, реализовать эту задачу в одном регистре не представляется возможным, поэтому отвечают за счет регистры r17 и r18). Передние фронта импульсов формируется при переполнении переменной-счетчика, длинна импульсов задается в регистрах r0, r1, ... и равна значению регистра умноженному на 10 мкс. Исходя из этого получаем, что минимальное значение в любом регистре - 50 (500 мкс), максимальное - 250 (2500 мкс). Очевидно, что удобнее использовать диапазон от 0 до 200, для чего введено понятие смещения, в командах для микроконтроллера передаются числа от 0 до 200, микроконтроллер же сам к ним добавляет смещение 50.
Особенности: Исправил: 1) Данный вариант генерации ШИМ-сигналов, несмотря на некоторую неоптимальность, пожалуй, будет более понятен тем, кто знаком с микроконтроллерами недавно именно благодаря своему прямому решению задачи "в лоб". Возможно, через какое то время я попробую оптимизировать данный код. Задействованны регистры r0, r1 и т.д. для хранения положения качалки каждого сервопривода, r16 для хранения величины смещения, r17 и r18 для переменной-счетчика, r19, r20 и т.д. для вывода сигналов в выбранные порты, по одному на порт. 2) Важно, микроконтроллер должен запускаться с кварцевым резонатором 8 МГц и НЕзапрограммированном флаге CKDIV8 (деление тактовой частоты на 8). В противном случае, код инициализации таймера придется изменить. Добавил: 3) Эмпирически выяснилось, что для каждого отдельно взятого сервопривода соответствия между длинной импульсов и границами положения качалки различаются, для одного это может быть длительность 500-2500 мкс, для другого 400-2400 мкс, для третьего 600-2400 мкс. Поэтому рекомендую не передавать микроконтроллеру команду выведения сервоприводов в крайние положения, а использовать диапазон чисел от 15 до 185. После обработки такой команды длительность импульса составит 650-2350 мкс.
Листинг: Листинг программы состоит из нескольких частей. Code ; инициализация таймера 0 ldi r16, 10 ; загружаем константу для сравнения out OCR0A, r16 ldi r16, 0b00000010 ; выбираем Normal Output A Mode, Normal Output B Mode, CTC Mode out TCCR0A, r16 ldi r16, 0b00000010 ; выбираем CTC Mode, деление тактовой частоты равным восьми out TCCR0B, r16 in r16, TIMSK ; разрешаем Compare Match A прерывание таймера 0, для этого меняем 3-0 биты регистра MCUCR не затрагивая остальные биты cbr r16, 0b00000111 ; обнуляем 2-0 биты sbr r16, 0b00000001 ; устанавливаем 0 бит out TIMSK, r16
; инициализация портов ; в этом месте необходимо сконфигурировать выбранные ножки микроконтроллера на вывод
Загружаем начальные значения регистров. Если этого не сделать, при старте микроконтроллера все сервоприводы могут попытаться уйти в недопустимые конструкцией положения, а это чревато выводом сервоприводов из строя. Code ; загрузка начальных констант в регистры ldi r17, 0 ; обнуление регистров переменной-счетчика на случай, если они были использованны ранее ldi r18, 0 ldi r16, 50 ; загружаем смещение mov r0, r16 ; начальная длительность импульса равна смещению ; mov r1, r16 ; и так далее по числу сервоприводов
И, собственно, обработчик прерывания таймера 0: Code tim0_compA: inc r17 ; это событие происходит каждые 10 мкс
; для первого сервопривода cp r17, r0 ; если значения регистров равны - формируем задний фронт импульса brne tim0_compA_control_mark1 cbr r19, 0b00000001 ; очищаем бит 0 (сервопривод подключен к ножке PB0) tim0_compA_control_mark1:
; и так далее по числу сервоприводов ; cp r17, r1 ; если значения регистров равны - формируем задний фронт импульса ; brne tim0_compA_control_mark2 ; cbr r20, 0b01000000 ; очищаем бит 6 (сервопривод подключен к ножке PD6) ; tim0_compA_control_mark2:
cpi r17, 250 ; возможно, регистр r17 близок к переполнению brne tim0_compA_control_mark inc r18 ; тогда задействуем вспомогательный регистр, это событие происходит каждые 2.5 мс ldi r17, 0 ; а регистр r17 обнуляем
cpi r18, 8 ; появление этого числа в регистре означает, что переменная-счетчик достигла значения 250*8=2000 brne tim0_compA_control_mark ldi r18, 0 ; тогда ее надо обнулить (r17 уже обнулен к этому моменту), это событие происходить каждые 20 мс sbr r19, 0b00000001 ; в этом случае устанавливаем бит в единицу (формируется передний фронт импульсов) tim0_compA_control_mark:
out PORTB, r19 ; выводим в порт ; out PORTD, r20 ; и так далее по числу использованных портов reti
Вопросы в ЛС или онлайн чат http://www.servodroid.ru/index/online_chat_po_robototekhnike/0-77
|
|
|
|
|