sanyaav | Дата: Среда, 20.02.2013, 21:11 | Сообщение # 1 |
Репутация:
Группа:Журналист
Сообщений: 134
Награды: 8
Статус:Offline
Для чего нужен ШИМ? (точнее употребить "нужна", так как это модуляция-она). Так вот эта неприступная для некоторых особа очень помогает, когда необходимо плавно регулировать скорость вращения различных сверлилок, вентиляторов и более крупных "вращалок", также можно с помощью ШИМ регулировать яркость светодиодов или ламп, ещё одно применение: регулятор температуры для различных нагревателей...на этом список не заканчивается, область применения ограничена только фантазией разработчика. По своей природе ШИМ - это обычные импульсы, с неизменным периодом, но с изменяемыми длительностями импульса и паузы. Допустим общее питание схемы 12 вольт, а нам нужно на выходе получить 1,2 вольта, при этом длительность периода примем равной 10 мс, в итоге длительность импульса будет 1 мс, а длительность паузы 9 мс. Можно встретить термин "скважность", что это такое? допустим вы увидели такую запись: скважность 40% это значит, что длительность импульса составляет 40% от времени периода. Если применить к примеру выше, то скважность 40% даст на выходе 4,8 вольт, при этом длительность импульса будет равна 4 мс, а длительность паузы 6 мс.
Теперь разберёмся с программой, я её уже написал и проверил в протеусе, выкладываю ТУТ Реализация самая простейшая, недостатки есть, но для понятия принципа организации ШИМ этого будет достаточно. Начнём по-порядку: Здесь первые две строчки оставляем такими же как и в прошлой программе Ниже объявляем несколько регистров специального назначения, регистр OPTION_REG в этой программе нам нужен для включения подтягивающих резисторов (для того, чтобы не использовать внешние), а также для настройки делителя перед сторожевым таймером, в регистре WPU можно выбрать к каким выводам будут подключены подтягивающие резисторы, регистр ANSEL будет нужен для того, чтобы указать режим работы входов, регистр CMCON служит для включения-выключения компаратора. Ниже идут три регистра общаего назначения, два нижних просто переименуем.
Теперь рассмотрим тело программы, начнём с настроек:
директива org указывает с какого адреса начинается выполнение программы, в данном случае с 0000h, как и в прошлый раз. Теперь нужно открыть страницу 26 даташита. Там приведена таблица регистров, которые влияют на порт ввода-вывода, эти регистры мы и будем изменять Сначала отключим компаратор, для этого изменим регистр CMCON, смотрим в таблицу: на работу порта влияют 3 первых бита, открываем страницу 35 даташита и смотрим что же это за биты, производитель любезно отсылает нас на просмотр рисунка 6-2, что мы и делаем, во второй ячейке видим заветные слова: СМ2-СМ0: 111 - компаратор выключен, вот это значение и записываем в регистр СМСОN, для этого используем команды movlw-запись числа в аккумулятор, и movwf-пересылка числа из аккумулятора в регистр. Для изменения остальных регистров нужно перейти в 1 банк (почему-рассказано в прошлых уроках, если кто не помнит даю наводку: стр 10 даташита.) С регистром TRISIO всё понятно, только теперь в отличие от прошлой программы нужно настроить 2 ножки на вход, чтобы принимать сигнал с кнопок, для этого в 1 и во 2 бит записываем 1, также я записал 1 в третий бит, так как он всегда используется только как вход. Теперь снова открываем стр.26 смотрим на регистр ANSEL, там выделены биты 0-3, переходим на страницу 45 смотрим, какое значение нужно поставить: модуль АЦП не используется, значит просто запишем нули в регистр. Можно сделать это как с регистром СМСОN, но проще будет обнулить регистр командой clrf. Разбираемся с регистром OPTION_REG: в этой программе для настройки порта нам нужен только 7 бит, чтобы включить подтягивающие резисторы, дополнительно изменим биты 3-0 для настройки максимального времени до сброса сторожевого таймера, в итоге получаем число 00001111 для записи в регистр. Записываем его как и в первом случае двумя командами. Включени резисторов разрешено, теперь нужно указать какие именно ножки будут подтянуты к "+", для этого изменим регистр WPU, открываем страницу 22, изменение по аналогии с портом TRISIO, нужен резистор-значит ставим 1, не нужен-0 (исключение 3 бит). записываем число 00000110 в WPU и переходим обратно в нулевой банк.
Теперь нужно задать начальные значения нашего сигнала: 2 вопроса: зачем задавать начальное значение и почему именно 1 и 254 ответ 1: оба регистра при включении питания будут обнулены и если кнопки не нажаты, то длительность импульса будет ноль и длительность паузы будет ноль, то есть при включении сигнал не пойдёт до нажатия какой-либо кнопки. ответ 2: в прошлой программе я рассказал, как организовать цикл временной задержки при помощи команды decfsz, каждый раз при помощи этой команды содержимое регистра уменьшается на единицу, пока не станет равным нулю, если изначально в регистре будет записан ноль, то следующим числом за нулём при вычитании будет 255, поэтому изначально записываем 1, при этом примем значение периода равным 255 (опять же для упрощения), длительность паузы при этом будет 255-1=254 - это число и записываем в регистр T_L.
После того как всё настроено, нужно опросить кнопки: Для начала поясню алгоритм: на входах GPIO 2 и GPIO 1 всегда присутствует высокий уровень сигнала, так как они подтянуты к "+", при нажатии кнопок входы замыкаются на массу, что даёт низкий уровень сигнала в порт, вот этот низкий уровень и нужно проверять, если кнопка нажата, то увеличить (уменьшить счётчик времени импульса), если не нажата, то проследовать далее по программе без изменений. увеличение (уменьшение) я сделал с шагом 32, можно применить и другой шаг, но учитывайте то, что скважность при этом будет "плавать", чтобы этого не было в данной программе можно использовать шаги по степени числа 2: 2,4,8,16,32,64.....и даже 127, но тогда будет всего 2 уровня сигнала: ~0% и ~50% после увеличения(уменьшения) счётчика длительности импульса, нужно рассчитать константу для счётчика длительности паузы, затем перейти к установке сигналов.
По командам даный алгоритм выглядит так: btfsc GPIO,1 - проверка бита номер 1 в регистре GPIO (описание на странице 77) если этот бит равен 1 (высокий уровень сигнала) то выполняем следующую команду: goto PROV2 - переход по метке PROV2, то есть переход к проверке нажатия второй кнопки. если бит 1 равен нулю (что свидетельствует нажатию на кнопку), то ждём когда пользователь отпустит кнопку, для чего применяем команду btfss (описание на странице 77), если бит всё ещё равен нулю, то выполняем команду перехода goto OTKL1, то есть зацикливаем, пока нажата кнопка. (P.S. стоит помнить о сторожевом таймере, он у нас сработает через 2,3 с., и контроллер сбросится в начало, чтобы этого избежать перед командой btfss GPIO,1 нужно поставить clrwdt) когда кнопка отожмётся, выполняем увеличение регистра T_H на шаг равный 32, для этого сначала записываем значение 32 в аккумулятор командой movlw .32 , затем складываем эту константу со значением, которое уже хранится в T_H, для этого используем команду addwf T_H,1 (1 здесь указывает на то, что результат нужно сохранить в регистре T_H, если здесь поставить 0, то результат сохраниться в аккумуляторе) Теперь нужно рассчитать значение регистра T_L, для этого перешлём рассчитаную ранее коснстанту в аккумулятор командой movf T_H,0 (ноль как раз и свидетельствует о сохранении в аккумулятор, если нужно сохранить в этом же регистре используем 1, как и в предыдущем случае, вопрос: зачем сохранять "сам в себя"? для того, чтобы проверить на равенство нулю, если в этом регистре будет ноль, то будет "поднят" флаг равенства нулю)
далее нужно вычесть это значение из константы общего времени 255, делается это командой sublw .255 - вычесть W(аккумулятор) из константы, результат при этом сохранится в аккумуляторе, и нужно его перенести в регистр T_L, делается это с помощью команды movwf T_L Теперь все константы посчитаны можно переходить к установке сигналов (команда goto START) (P.S. нажатие второй кнопки не описываю, там всё аналогично, разница только в команде subwf T_H,1 - в этом случае мы вычитаем знначение шага, а в предыдущем увеличивали)
теперь перейдём к описанию установки синалов:
Для реализации временной задержки воспользуемся подпрограммой, как и в прошлом уроке, будем уменьшать на 1 регистр IMP, значения для регистра IMP будем брать из рассчитаных ранее при нажатии кнопок. Нельзя напрямую работать с рассчитанными значениями, так как после одного периода эти значения будут утеряны, и храниться в регистрах будет ноль. Чтобы передать константу в регистр IMP воспользуемся 2 командами:
movf T_H,0 - пересылка T_H в аккумулятор (ноль в команде) movwf IMP - пересылка их аккумулятора вIMP
затем нужно установить высокий уровень сигнала (аналогично программе из прошлого урока) bsf GPIO,0 и перейти на выполнение подпрограммы временной задержки: call PPZ после того, как выполнится временная задержка для импульса, нужно произвести анологичные операции для паузы, для чего используем значение регистра T_L и выполняем следующие команды
movf T_L,0 movwf IMP bcf GPIO,0 call PPZ
после полного периода нужно перейти на опрос кнопок, для чего пользуемся командой
goto PROV1 - переход по метке PROV1
далее цикл повторяется.
Ну вот и всё, осталось только прошить и попробовать как это работает.
Схема дополнена транзисторным ключом ВНИМАНИЕ!!! питание микроконтроллера отдельное +5 вольт, питание мотора в данном случае 42-45 вольт, масса общая
Сообщение отредактировал sanyaav - Пятница, 22.02.2013, 17:48 | |
|
I'll be back
|
|
| |
YurAlex | Дата: Суббота, 23.02.2013, 10:17 | Сообщение # 3 |
Репутация:
Группа:Новичок
Сообщений: 2
Награды: 0
Статус:Offline
"Допустим общее питание схемы 12 вольт, а нам нужно на выходе получить 1,2 вольта, при этом длительность периода примем равной 10 мс, в итоге длительность импульса будет 1 мс, а длительность паузы 9 мс." Насколько корректно это к разным нагрузкам? Ведь, как я понимаю, от скважности изменяется падение напряжения на нагрузке из-за изменения среднего тока через нагрузку за период. Или что-то я упустил?
| |
|
|
|
| |
sanyaav | Дата: Воскресенье, 24.02.2013, 10:56 | Сообщение # 4 |
Репутация:
Группа:Журналист
Сообщений: 134
Награды: 8
Статус:Offline
А я уж думал никто и спрашивать не будет, YurAlex, если использовать в качестве нагрузки резисторы, то напряжение будет очень близко к расчётному, если нагрузка индуктивная или емкостная, то будет разброс, из-за сглаживания импульсов, и при расчётных 6 вольтах в нагрузку пойдут все 10 из 12, и это напряжение будет разным на разных частотах ШИМ.
| |
|
I'll be back
|
|
| |
sanyaav | Дата: Воскресенье, 09.03.2014, 13:06 | Сообщение # 7 |
Репутация:
Группа:Журналист
Сообщений: 134
Награды: 8
Статус:Offline
Penta_Tonic, будешь смеяться, но начал я с Корабельникова)))) при этом сам не дочитал до конца, понимание пришло как-то само по себе на практике. Кстати, на счет ничего лишнего: некоторым наоборот надо всё разжевать, как раз у Корабельникова всё разжевано и даже переварено. Здесь же я стараюсь выкладывать свои наработки в этой области: интерфейсы, алгоритмы и тд. я не претендую на самое лучшее объяснение, кто-то понимает, кто-то нет. Рад, что тебе мои статьи пришлись по душе)
| |
|
I'll be back
|
|
| |
makarius | Дата: Воскресенье, 09.03.2014, 16:56 | Сообщение # 8 |
Репутация:
Группа:Проверенный паятель
Сообщений: 362
Награды: 12
Статус:Offline
А зачем смеяться, разницы нет с чего начинать!;) Главное, осилить (понять логику работы), потом уже трудно остановиться, когда поймешь, что контроллеры наши помощники и задуманые идеи постепенно входят в нашу жизнь, делая её более яркой и насыщенной!;)
Хорошие статьи!
| |
|
Каждый выбирает для себя женщину, религию, дорогу. Дьяволу служить или пророку -...
|
|
| |