Аппаратная шим на микроконтроллере

Урок 13. Аппаратная ШИМ на микроконтроллере

В этом уроке мы научимся реализовывать ШИМ сигнал на микроконтроллере AVR с помощью BASCOM-AVR. В микроконтроллерах AVR, ШИМ можно реализовать посредством таймеров, для этой цели в микроконтроллере есть ШИМ выходы на порты вводавывода.

Например, в микроконтроллере Attiny13 есть один таймер (Timer0) и два канала вывода ШИМ Pwm0a и Pwm0b,которые находиться на портах PB.0 и PB.1.

В документации на микроконтроллер ШИМ каналы подписываются так: OC0A – ШИМ канал A на таймере 0, OC0B – ШИМ канал B на таймере 0, OC1A – ШИМ канал A на таймере 1, OC1B – ШИМ канал B на таймере 1 и т.д.

Работа с ШИМ в микроконтроллере Для начала работы нужно сконфигурировать таймер на работу ШИМ для этого есть команда:

Config Timer1 = Pwm, Pwm = Разрядность, Compare A Pwm = Состояние канала A, Compare B Pwm = Состояние канала B, Prescale = Частота ШИМ

Разрядность можно задать 8, тогда будет скважность ШИМ от 0 до 255. Для Timer1 разрядность можно задать 9 или 10. Состояние канала A или B можно задать Clear Up – скважность при 0 = логической 1 и Clear Down – скважность при 0 = логической 0. Частоту ШИМ можно задать: 1, 8, 64, 256 и 1024.
Пример команды конфигурирования: Config Timer0 = Pwm , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 8
После конфигурирования таймера нужно сконфигурировать порты ШИМ на вывод командой Config порт = Output, например: Config Portb.0 = Output
Потом нужно запустить таймер командой Start таймер, например: Start Timer0.
Теперь можно записать скважность в ШИМ канал для канала A таймера 0 это можно сделать так: Pwm0a = скважность, например: Pwm0a = 150

Практический пример

Теперь давайте попробуем поработать с ШИМ на практике, сделаем простую моргалку которая будет плавно зажигать и тушить светодиоды. За основу возьмём микроконтроллер Attiny13 и два светодиода, соберём простую схему:

Теперь напишем простую программку на BASCOM-AVR, применяя полученные знания:

$regfile = “attiny13.dat”
$crystal = 9600000
Config Timer0 = Pwm , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 8
Config Portb.0 = Output
Config Portb.1 = Output
Start Timer0
Do
Incr Pwm0a
Decr Pwm0b
Waitms 5
Loop
End

Откомпилируем её, прошьём микроконтроллер и установим фьюз биты микроконтроллера на тактирование от внутреннего тактового генератора на 9.6 МГц без делителя на 8. Пример установки фьюз битов в программе SinaProg:

Я использовал свою отладочную плату и вот что получилось:

Скачать файлы для урока (проект в Proteus, исходник, прошивка) вы можете ниже

Урок 14. Программный UART в BASCOM-AVR

Скачать список элементов (PDF)

Прикрепленные файлы:

Яковлев Александр ВячеславовичОпубликована: 2012 г.0Вознаградить Я собрал 0 0

x

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография

Источник: http://cxem.net/mc/mc177.php

Генерация аналоговых сигналов микроконтроллером. Ч1

Введение

   В устройствах на микроконтроллерах иногда требуется генерировать аналоговый сигнал. В зависимости от частоты аналогового сигнала, требуемого разрешения и типа используемого микроконтроллера, выполнить это можно несколькими способами.

А именно: с помощью широтно-импульсной модуляции, используя функционал аппаратных таймеров или программную реализацию, с помощью встроенного цифроаналогового преобразователя (ЦАП`а), с помощью внешних схем цифроаналоговых преобразователей на дискретных элементах или с помощью внешних микросхем цифроаналоговых преобразователей.

1. Принцип генерации аналогового сигнала с помощью ШИМ (PWM)

   ШИМ сигнал представляет собой цифровой сигнал, у которого период повторения постоянный, а длительность меняется. Отношение длительности ШИМ сигнала к его периоду называется коэффициентом заполнения.

Пропустив такой сигнал через низкочастотный фильтр, что по сути равносильно интегрированию, мы получим на выходе фильтра уровень напряжения пропорциональный коэффициенту заполнения. 

   Таким образом, меня этот коэффициент, можно генерировать аналоговые сигналы произвольной формы.

Причем как переменные, например, синусоида, пила или человеческая речь, так и постоянные (произвольный уровень напряжения). 

1.1 Характеристики сигнала

   Максимальная амплитуда выходного аналогового сигнала будет определяться амплитудой логической единицы цифрового ШИМ сигнала. Если микроконтроллер питается от +5 В, то грубо говоря, амплитуда выходного аналогового сигнала будет от 0 до 5 В.    Минимальный шаг изменения аналогового сигнала (разрешение) будет определяться выражением:

dUa = Umax/2^n,

где Umax максимальная амплитуда аналогового сигнала (В), а n – разрядность счетчика реализующего ШИМ.    Например, ШИМ сигнал формируется с помощью программного 8-ми разрядного счетчика. Количество градаций ШИМ сигнала, которые можно получить с помощью этого счетчика, равно 2^8 = 256. Тогда разрешение аналогового сигнала при Umax = 5 В будет равно 

dUa = 5/256 = 0,0195 В. 

   Частота ШИМ сигнала будет определять так:

Fpwm = Fcpu/(K*2^n),

где Fcpu – тактовая частота микроконтроллера (Гц), K – коэффициент предделителя счетчика, n – разрядность счетчика.    Например, тактовая частота микроконтроллера 8 МГц, коэффициент предделителя равен 8, разрядность счетчика 8 бит. Тогда частота выходного ШИМ сигнала будет равна:

Fpwm = 8000000/(8*256) = ~3906 Гц

   Частота выходного аналогового сигнала будет определяться выражением:

Fa = Fpwm/Ns = Fcpu/(K*2^n*Ns),

где Fpwm – частота ЩИМ сигнала, а Ns – количество отсчетов аналогового сигнала. 

      Например, ШИМ сигнал реализуется на 8-ми разрядном счетчике с коэффициентом предделителя равным 8 и тактовой частотой микроконтроллера 8 МГц. В памяти микроконтроллера записано 32 отсчета синусоидального сигнала, которые представляют собой один его период. Тогда частота выходной синусоиды будет равна:Fa = 8000000/(8*2^8 * 32) = ~122 Гц

   Разрядность ЦАП`a сделанного на основе ШИМ эквивалентна разрядности используемого счетчика. 

1.2 Аппаратная реализация ШИМ

   Все современные микроконтроллеры имеют в своем составе таймеры/счетчики. Один или несколько режимов этих таймеров предназначены для генерации ШИМ сигнала. Как правило этот сигнал генерируется на специальных выводах.

Например, у микроконтроллера mega16 фирмы Atmel 8-ми разрядный таймер/счетчик Т0 имеет два режима генерации ШИМ сигнала (быстрый ШИМ и ШИМ с точной фазой), а для вывода сигнала используется пин порта B – OC0 (PINB3).

   Достоинство аппаратной реализации ШИМ сигнала – это низкая загрузка микроконтроллера (прерывание вызывается один раз в период ШИМ сигнала), простота использования и точность (если в системе мало прерываний).

Из недостатков можно отметить – ограниченное разрешение счетчиков, невысокая частота, ограниченное число каналов, на которых можно генерировать ШИМ сигналы. Хотя существуют специальные микроконтроллеры специально “заточенные” для генерации большого количества ШИМ сигналов.

1.3 Программная реализация ШИМ

   Также можно генерировать ШИМ сигнал программно. Для этого нужно просто создать программный счетчик и по сигналу аппаратного таймера инкрементировать его значение и отслеживать достижение крайних значений счетчика, в которых ШИМ сигнал меняет состояние.    Преимущество программной реализации – простота, неограниченное количество каналов, неограниченное разрешение. Конечно, условно неограниченное, с учетом доступной памяти. Недостатки программной реализации – высокая загрузка микроконтроллера. Прерывания должны вызываться на каждый инкремент счетчика и каждый раз нужно проверять не достиг ли он одного из крайних значений. Также программная реализация имеет меньшую точность (большее дрожание фронтов сигнала) и еще меньшую частоту (из-за первого недостатка).   Однако, несмотря на это, программная реализация ШИМ`а тоже имеет место быть, если требуется генерировать постоянный аналоговый сигнал или переменный, но с невысокой частотой.    Ниже приведен пример кода, который выполняет функцию генерацию аналогового сигнала с помощью аппаратной и программной широтно-импульсной модуляции. Код написан для микроконтроллера atmega16, тактовая частота 8 МГц, компилятор IAR. На выходах PB2 и PB3 генерируются две синусоиды (разной частоты) из 32 двух отсчетов. #include #include #include #define SPWM_PIN 2//таблица синуса__flash uint8_t tableSin[] = {   152,176,198,218,234,245,253,255,   253,245,234,218,198,176,152,128,   103, 79, 57, 37, 21, 10, 2, 0,   2, 10, 21, 37, 57, 79,103,128};uint8_t softCount = 0;uint8_t softComp = 0;int main( void ){ //настройка портов PORTB = 0; DDRB = 0xff; //разрешение прерывания по совпадению Т0TIMSK = (1

Источник: http://chipenable.ru/index.php/item/167

Широтно-импульсная модуляция (ШИМ)

Широтно-импульсная модуляция (ШИМ) – это метод преобразования сигнала, при котором изменяется длительность импульса (скважность), а частота остаётся константой. В английской терминологии обозначается как PWM (pulse-width modulation). В данной статье подробно разберемся, что такое ШИМ, где она применяется и как работает.

Область применения

С развитием микроконтроллерной техники перед ШИМ открылись новые возможности.

Этот принцип стал основой для электронных устройств, требующих, как регулировки выходных параметров, так и поддержания их на заданном уровне.

Метод широтно-импульсной модуляции применяется для изменения яркости света, скорости вращения двигателей, а также в управлении силовым транзистором блоков питания (БП) импульсного типа.

Широтно-импульсная (ШИ) модуляция активно используется в построении систем управления яркостью светодиодов. Благодаря низкой инерционности, светодиод успевает переключаться (вспыхивать и гаснуть) на частоте в несколько десятков кГц.

Его работа в импульсном режиме воспринимается человеческим глазом как постоянное свечение. В свою очередь яркость зависит от длительности импульса (открытого состояния светодиода) в течение одного периода.

Если время импульса равно времени паузы, то есть коэффициент заполнения – 50%, то яркость светодиода будет составлять половину от номинальной величины. С популяризацией светодиодных ламп на 220В стал вопрос о повышении надёжности их работы при нестабильном входном напряжении.

Решение было найдено в виде универсальной микросхемы – драйвера питания, работающего по принципу широтно-импульсной или частотно-импульсной модуляции. Схема на базе одного из таких драйверов детально описана здесь.

Подаваемое на вход микросхемы драйвера сетевое напряжение постоянно сравнивается с внутрисхемным опорным напряжением, формируя на выходе сигнал ШИМ (ЧИМ), параметры которого задаются внешними резисторами.

Некоторые микросхемы имеют вывод для подачи аналогового или цифрового сигнала управления. Таким образом, работой импульсного драйвера можно управлять с помощью другого ШИ-преобразователя.

Интересно, что на светодиод поступают не высокочастотные импульсы, а сглаженный дросселем ток, который является обязательным элементом подобных схем.

Микроконтроллер Ардуино тоже может функционировать в режиме ШИМ контроллера. Для этого следует вызвать функцию AnalogWrite() с указанием в скобках значения от 0 до 255. Ноль соответствует 0В, а 255 – 5В. Промежуточные значения рассчитываются пропорционально.

Повсеместное распространение устройств, работающих по принципу ШИМ, позволило человечеству уйти от трансформаторных блоков питания линейного типа. Как результат – повышение КПД и снижение в несколько раз массы и размеров источников питания.

ШИМ-контроллер является неотъемлемой частью современного импульсного блока питания. Он управляет работой силового транзистора, расположенного в первичной цепи импульсного трансформатора. За счёт наличия цепи обратной связи напряжение на выходе БП всегда остаётся стабильным.

Малейшее отклонение выходного напряжения через обратную связь фиксируется микросхемой, которая мгновенно корректирует скважность управляющих импульсов.

Кроме этого современный ШИМ-контроллер решает ряд дополнительных задач, способствующих повышению надёжности источника питания:

  • обеспечивает режим плавного пуска преобразователя;
  • ограничивает амплитуду и скважность управляющих импульсов;
  • контролирует уровень входного напряжения;
  • защищает от короткого замыкания и превышения температуры силового ключа;
  • при необходимости переводит устройство в дежурный режим.

Принцип работы ШИМ контроллера

Задача ШИМ контроллера состоит в управлении силовым ключом за счёт изменения управляющих импульсов. Работая в ключевом режиме, транзистор находится в одном из двух состояний (полностью открыт, полностью закрыт). В закрытом состоянии ток через p-n-переход не превышает несколько мкА, а значит, мощность рассеивания стремится к нулю.

В открытом состоянии, несмотря на большой ток, сопротивление p-n-перехода чрезмерно мало, что также приводит к незначительным тепловым потерям. Наибольшее количество тепла выделяется в момент перехода из одного состояния в другое.

Но за счёт малого времени переходного процесса по сравнению с частотой модуляции, мощность потерь при переключении незначительна.

Широтно-импульсная модуляция разделяется на два вида: аналоговая и цифровая. Каждый из видов имеет свои преимущества и схемотехнически может реализовываться разными способами.

Аналоговая ШИМ

Принцип действия аналогового ШИ-модулятора основан на сравнении двух сигналов, частота которых отличается на несколько порядков. Элементом сравнения выступает операционный усилитель (компаратор).

На один из его входов подают пилообразное напряжение высокой постоянной частоты, а на другой – низкочастотное модулирующее напряжение с переменной амплитудой.

Компаратор сравнивает оба значения и на выходе формирует прямоугольные импульсы, длительность которых определяется текущим значением модулирующего сигнала. При этом частота ШИМ равна частоте сигнала пилообразной формы.

Цифровая ШИМ

Широтно-импульсная модуляция в цифровой интерпретации является одной из многочисленных функций микроконтроллера (МК). Оперируя исключительно цифровыми данными, МК может формировать на своих выходах либо высокий (100%), либо низкий (0%) уровень напряжения.

Однако в большинстве случаев для эффективного управления нагрузкой напряжение на выходе МК необходимо изменять. Например, регулировка скорости вращения двигателя, изменение яркости светодиода.

Что делать, чтобы получить на выходе микроконтроллера любое значение напряжения в диапазоне от 0 до 100%?

Вопрос решается применением метода широтно-импульсной модуляции и, используя явление передискретизации, когда заданная частота переключения в несколько раз превышает реакцию управляемого устройства. Изменяя скважность импульсов, меняется среднее значение выходного напряжения.

Как правило, весь процесс происходит на частоте в десятки-сотни кГц, что позволяет добиться плавной регулировки. Технически это реализуется с помощью ШИМ-контроллера – специализированной микросхемы, которая является «сердцем» любой цифровой системы управления.

Активное использование контроллеров на основе ШИМ обусловлено их неоспоримыми преимуществами:

  • высокой эффективности преобразования сигнала;
  • стабильность работы;
  • экономии энергии, потребляемой нагрузкой;
  • низкой стоимости;
  • высокой надёжности всего устройства.

Получить на выводах микроконтроллера ШИМ сигнал можно двумя способами: аппаратно и программно. В каждом МК имеется встроенный таймер, который способен генерировать ШИМ импульсы на определённых выводах. Так достигается аппаратная реализация.

Получение ШИМ сигнала с помощью программных команд имеет больше возможностей в плане разрешающей способности и позволяет задействовать большее количество выводов. Однако программный способ ведёт к высокой загрузке МК и занимает много памяти.

Примечательно, что в цифровой ШИМ количество импульсов за период может быть различным, а сами импульсы могут быть расположены в любой части периода.

Уровень выходного сигнала определяется суммарной длительностью всех импульсов за период.

При этом следует понимать, что каждый дополнительный импульс – это переход силового транзистора из открытого состояния в закрытое, что ведёт к росту потерь во время переключений.

Пример использования ШИМ регулятора

Один из вариантов реализации ШИМ простого регулятора уже описывался ранее в этой статье. Он построен на базе микросхемы NE555 и имеет небольшую обвязку. Но, несмотря на простату схемы, регулятор имеет довольно широкую область применения: схемы управления яркости светодиодов, светодиодных лент, регулировка скорость вращения двигателей постоянного тока.

Источник: https://ledjournal.info/spravochnik/shirotno-impulsnaya-modulyaciya.html

Урок 37. Широтно-импульсная модуляция в Ардуино

В уроке узнаем о широтно-импульсной модуляции, о реализации этого способа управления в контроллерах Ардуино, о режимах и функциях работы с ШИМ в Ардуино.

https://www.youtube.com/watch?v=Xki0CD3uy0Y

Предыдущий урок     Список уроков     Следующий урок

Прервемся на урок от разработки контроллера холодильника, для того чтобы научиться работать с широтно-импульсным модулятором Ардуино.

В нашей разработке используется именно такой способ регулирования мощности на элементе Пельтье.

Широтно-импульсная модуляция.

Широтно-импульсная модуляция (ШИМ) это способ управления мощностью на нагрузке с помощью изменения скважности импульсов при постоянной амплитуде и частоте импульсов.

Можно выделить две основные области применения широтно-импульсной модуляции:

  • Во вторичных источниках питания, различных регуляторах мощности, регуляторах яркости источников света, скорости вращения коллекторных двигателей и т.п. В этих случаях применение ШИМ позволяет значительно увеличить КПД системы и упростить ее реализацию.
  • Для получения аналогового сигнала с помощью цифрового выхода микроконтроллера. Своеобразный цифро-аналоговый преобразователь (ЦАП). Очень простой в реализации, требует минимума внешних компонентов. Часто достаточно одной RC цепочки.

Принцип регулирования с помощью ШИМ – изменение ширины импульсов при постоянной амплитуде и частоте сигнала.

На диаграмме можно увидеть основные параметры ШИМ сигнала:

  • Ui – амплитуда импульсов ;
  • Ton – время активного (включенного) состояния сигнала;
  • Toff – время отключенного состояния сигнала;
  • Tpwm – время периода ШИМ.

Даже интуитивно понятно, что мощность на нагрузке пропорциональна соотношению времени включенного и отключенного состояния сигнала.

Это соотношение определяет коэффициент заполнения ШИМ:

Kw = Ton / Tpwm.

Он показывает, какую часть периода сигнал находится во включенном состоянии.  Может меняться:

  •  от 0 – сигнал всегда выключен;
  •  до 1 – сигнал все время находится во включенном состоянии.

Чаще используют процентный коэффициент заполнения. В этом случае он находится в пределах от 0 до 100%.

Среднее значение электрической мощности на нагрузке строго пропорционально коэффициенту заполнения. Когда говорят, что ШИМ равен, например, 20%, то имеют в виду именно коэффициент заполнения.

Формирование аналогового сигнала.

Если сигнал ШИМ пропустить через фильтр низких частот (ФНЧ), то на выходе фильтра мы получим аналоговый сигнал, напряжение которого пропорционально коэффициенту заполнения ШИМ.

U = Kw * Ui

В качестве ФНЧ можно использовать простейшую RC цепочку.

Из-за неидеальной характеристики такого фильтра частота среза должна быть минимум на порядок меньше частоты ШИМ. Для простого RC фильтра частота среза вычисляется по формуле:

F = 1 / (2 π R C).

  • При повышении частоты среза ФНЧ на выходе фильтра увеличиваются пульсации с частотой ШИМ.
  • При уменьшении частоты среза фильтра снижается время реакции выходного аналогового сигнала на изменения ширины импульсов.

Из этого вытекает главный недостаток широтно-импульсной модуляции. Метод способен синтезировать только достаточно медленные аналоговые сигналы или требует применения фильтров низких частот с высокой добротностью, сложных в реализации.

Я бы рекомендовал:

  • В случае, когда к быстродействию аналогового сигнала жестких требований нет выбирать заведомо заниженную частоту среза фильтра.
  • Если необходимо оптимизировать быстродействие аналогового преобразователя, то лучше промоделировать схему.

Даже простейшие моделирующие программы вычисляют уровень пульсаций достаточно точно. Вот результаты моделирования на SwCAD для ШИМ частотой 500 Гц и RC фильтрами с частотами среза 500 Гц, 50 Гц и 5 Гц. Зеленым цветом показана диаграмма ШИМ, синим – напряжение на выходе RC фильтра.

Частота среза 500 Гц (10 кОм, 32 нФ).

Частота среза 50 Гц (10 кОм, 320 нФ).

Частота среза 5 Гц (10 кОм, 3,2 мкФ).

Точность преобразования широтно-импульсных модуляторов определяется погрешностью амплитуды импульсов (т.е.

стабильностью питания микроконтроллера) и значением падения напряжения на ключах цифровых выходов микроконтроллера. Как правило, точность ШИМ микроконтроллеров невысока.

Добиться высокой точности ШИМ преобразования можно с помощью дополнительной схемы с аналоговыми ключами и источником опорного напряжения.

К недостаткам использования широтно-импульсных модуляторов в качестве ЦАП также следует отнести высокое выходное сопротивление. Оно определяется сопротивлением резистора RC фильтра и не может быть низким из-за малой нагрузочной способности выходов микроконтроллера.

Широтно-импульсные модуляторы в Ардуино.

Платы Ардуино на базе микроконтроллеров ATmega168/328 имеют 6 аппаратных широтно-импульсных модуляторов. Сигналы ШИМ могут быть сгенерированы на выводах 3, 5, 6, 9, 10, 11.

Управление аппаратными ШИМ осуществляется с помощью системной функции analogWrite().

void analogWrite(pin, val)

Функция переводит вывод в режим ШИМ и задает для него коэффициент заполнения. Перед использованием analogWrite() функцию pinMode() для установки вывода в режим “выход” вызывать необязательно.

Аргументы:

  • pin – номер вывода для генерации ШИМ сигнала.
  • val – коэффициент заполнения ШИМ. Без дополнительных установок  диапазон val от 0 до 255 и соответствует коэффициенту заполнения от 0 до 100 %. Т.е. разрядность системных ШИМ в Ардуино 8 разрядов.

analogWrite(9, 25);  // на выводе 9 ШИМ = 10%

Частота ШИМ Ардуино 488,28 Гц.

Для генерации ШИМ используются все три таймера Ардуино.

Таймер Используется для генерации ШИМ на выводах
Таймер  0 выводы 5 и 6
Таймер  1 выводы 9 и 10
Таймер  2 выводы 3 и 11

Если таймер используется для других целей, например для прерывания, то параметры ШИМ соответствующих выводов могут не соответствовать указанным выше.

Поэтому, при использовании библиотек MsTimer2, TimerOne или им подобных некоторые выводы в качестве ШИМ сигналов использовать нельзя.

Увеличение частоты и разрядности ШИМ Ардуино.

Система Ардуино устанавливает на всех выводах ШИМ параметры:

  • частота 488,28 Гц;
  • разрешение 8 разрядов (0…255).

Очень низкая частота. Для большинства приложений совершенно не допустимая.

В разработке контроллера элемента Пельтье, начатой в предыдущем уроке, частота ШИМ должна быть не менее 30-50 кГц. В интернете достаточно много предложений по увеличению частоты ШИМВо всех описываются методы увеличения частоты до 31 кГц. В принципе приемлемый вариант, но мне захотелось большего.

Я разобрался с Таймером 1 микроконтроллера ATmega168/328, перевел ШИМ в быстродействующий режим и добился частоты ШИМ Ардуино до 62,5 кГц. Заодно я научился менять разрядность ШИМ. Чтобы в следующий раз не копаться в документации на микроконтроллеры ATmega168/328 я свел всевозможные варианты ШИМ для таймера 1 в таблицу.

Строчки из правого столбца для выбранного варианта необходимо написать в функции setup().

Варианты параметров ШИМ на выводах 9 и 10 Ардуино (таймер 1).

Разрешение Частота ШИМ Команды установки режима
8 бит 62 500 Гц TCCR1A = TCCR1A & 0xe0 | 1;TCCR1B = TCCR1B & 0xe0 | 0x09;
7 812,5 Гц TCCR1A = TCCR1A & 0xe0 | 1;TCCR1B = TCCR1B & 0xe0 | 0x0a;
976,56 Гц TCCR1A = TCCR1A & 0xe0 | 1;TCCR1B = TCCR1B & 0xe0 | 0x0b;
244,14 Гц TCCR1A = TCCR1A & 0xe0 | 1;TCCR1B = TCCR1B & 0xe0 | 0x0c;
61,04 Гц TCCR1A = TCCR1A & 0xe0 | 1;TCCR1B = TCCR1B & 0xe0 | 0x0d;
9 бит 31 250 Гц TCCR1A = TCCR1A & 0xe0 | 2;TCCR1B = TCCR1B & 0xe0 | 0x09;
3 906,25 Гц TCCR1A = TCCR1A & 0xe0 | 2;TCCR1B = TCCR1B & 0xe0 | 0x0a;
488,28 Гц TCCR1A = TCCR1A & 0xe0 | 2;TCCR1B = TCCR1B & 0xe0 | 0x0b;
122,07 Гц TCCR1A = TCCR1A & 0xe0 | 2;TCCR1B = TCCR1B & 0xe0 | 0x0c;
30,52 Гц TCCR1A = TCCR1A & 0xe0 | 2;TCCR1B = TCCR1B & 0xe0 | 0x0d;
10 бит 1 5625 Гц TCCR1A = TCCR1A & 0xe0 | 3;TCCR1B = TCCR1B & 0xe0 | 0x09;
1 953,13 Гц TCCR1A = TCCR1A & 0xe0 | 3;TCCR1B = TCCR1B & 0xe0 | 0x0a;
244,14 Гц TCCR1A = TCCR1A & 0xe0 | 3;TCCR1B = TCCR1B & 0xe0 | 0x0b;
61,04 Гц TCCR1A = TCCR1A & 0xe0 | 3;TCCR1B = TCCR1B & 0xe0 | 0x0c;
15,26 Гц TCCR1A = TCCR1A & 0xe0 | 3;TCCR1B = TCCR1B & 0xe0 | 0x0d;

Следующий скетч генерирует на выводе 9 ШИМ с частотой 62,5 кГц и коэффициентом заполнения примерно 10 %.

void setup() {
  // ШИМ 8 разрядов, 62,5 кГц
  TCCR1A = TCCR1A & 0xe0 | 1;
  TCCR1B = TCCR1B & 0xe0 | 0x09; 
  analogWrite(9, 25); // на выводе 9 ШИМ=10%
}

void loop() {
}

Это максимально возможная частота ШИМ Ардуино для большинства плат (с частотой генератора 16 мГц).

В следующем уроке вернемся к разработке контроллера элемента Пельтье.

Предыдущий урок     Список уроков     Следующий урок

Источник: http://mypractic.ru/urok-37-shirotno-impulsnaya-modulyaciya-v-arduino.html

Как настроить ШИМ на AVR

Что такое ШИМ
Таймеры и счётчики В AVR микроконтроллерах, ШИМ реализован аппаратно, остаётся только расставить нужные биты и он готов к работе.

В общем у таймера есть регистр сравнения OCR** и когда значение в таймере совпадает со значением регистра сравнения OCR** может произойти 2 вещи:

  • Прерывание
  • Изменение состояния внешнего вывода сравнения OC**

Выводы OC** это специальные ножки микроконтроллера

Теперь мы можем настроить ШИМ когда счётчик досчитает до значения OCR** напряжение на выбранной нами ножке OC** измениться от 5 до 0. Когда таймер досчитает до конца и начнёт считать сначала изменим напряжения с 0 до 5, на выходе у нас будут прямоугольные импульсы

Есть 3 режима работы ШИМ 

СТС (сброс при совпадении) – Это можно назвать ЧИМ частотно-импульсно моделированный сигнал, когда таймер досчитает до значения OCR** он сбрасывается и меняет значение OC** на противоположное. Таким образом скважность ШИМ всегда одинаковая.

Это используют когда нужно отсчитывать точные периоды, или генерировать прерывания через определённое время.

Fast PWM (быстрый ШИМ) – счётчик считает от 0 до 255, после чего сбрасывается в 0.

Когда значение таймера совпадает с OCR** соответствующий вывод сбрасывается в 0, при обнулении ставиться 1.

Чаще всего используется как обычный ШИМ.

Phase Correct PWM (ШИМ с точной фазой) – в этом режиме счётчик считает от 0 до 255, а потом считает в обратном направлении до нуля. При первом совпадении с OCR** вывод сбрасывается в 0, при 2 совпадении (когда счётчик идёт обратно), ставиться 1.

Используют для того чтобы не сбивалась фаза при изменении скважности.

Ок, самые главные здесь это регистры TCCR1A и TCCR1B. 

Если мы хотим работать с выводом OC1A ставим биты в COM1A1 COM1A0 

Вообще “/” означает ИЛИ. TCNT1 = OCR1A для ШИМ на выводе OC1ATimer/Counter Mode of Operation – режим работы таймера/счетчика.

Top – значение TCNT1 при котором происходит переключение значения вывода OC**.

TOV1 Flag Set on – при каких значениях устанавливается бит регистра GIFR

Выбираем из последней таблицы тот режим который нам нужен, не смотрим на Top. Из 2 таблицы выбираем любой из 2 последних вариантов. Остаётся только расставить нужные биты в регистрах.#define F_CPU 8000000UL #include
#include int main()
{ DDRD = 0xFF; OCR1A=0xC0; // Сравниваем с этим значением OCR1B=0x40; //Настройка ШИМ и таймера TCCR1A|=(1

Источник: http://4a4ik.blogspot.com/2014/03/avr.html

Raspberry Pi – ШИМ и Сервопривод

Raspberry Pi имеет несколько путей реализации PWM (ШИМ) (Широтно-импульсной модуляции). Мы рассмотрим как реализовать, ШИМ программно, и задействуем для генерации ШИМ аппаратные ресурсы Raspberry Pi. Сначала будем менять яркость светодиода, а затем научимся управлять сервоприводом.

Что такое PWM (ШИМ)?

Широтно-импульсная модуляция (ШИМ) – это импульсный сигнал постоянной частоты и переменной скважности, то есть отношение длительности импульса к периоду его следования. С помощью задания скважности (длительности импульсов) можно менять среднее значение напряжения на выходе ШИМ. Подробнее о ШИМ читайте на Википедия.

Программная реализация ШИМ

Подключим светодиод к GPIO23 как указано на схеме:

Напишем скрипт pwm_soft.py:

nano ./pwm_soft.py

Текст скрипта:

import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)
p = GPIO.PWM(23, 50) # channel=23 frequency=50Hz
p.start(0)
try: while 1: for dc in range(0, 101, 5): p.ChangeDutyCycle(dc) time.sleep(0.1) for dc in range(100, -1, -5): p.ChangeDutyCycle(dc) time.sleep(0.1)
except KeyboardInterrupt: pass
p.stop()
GPIO.cleanup()

Запустим его:

python ./pwm_soft.py

Светодиод будет плавно загораться и плавно гаснуть.

Программная реализация ШИМ позволяет сформировать ШИМ-сигнал на любому выводе. В этом примере мы используем RPi.GPIO для программной генерации ШИМ сигнала. А это значит, что тратятся вычислительные ресурсы микрокомпьютера.

Если микрокомпьютер будет отвлекаться на другие задачи, ШИМ сигнал будет искажаться и не будет стабильным. Это не принципиально, если ШИМ применяется для управления яркостью светодиода. Но может стать неприемлемым, когда ШИМ применяется для формирования управляющего сигнала.

Например, при управлении сервоприводами программная реализация ШИМ не может стабильно удерживать сервоприводы в заданном положении. Это заметно на видео ниже.

Raspberry Pi имеет техническую возможность использовать аппаратный ресурс для генерации ШИМ.

Генерирование ШИМ сигнала с использованием аппаратных ресурсов Raspberry Pi

Проект WiringPi – это библиотека, которая содержит утилиты для простого доступа к GPIO. Она позволяет настроить аппаратные модули для специальных выходов ШИМ. Установим wiringPi:

sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
cd ..

Подключим светодиод к GPIO18 как указано на схеме:

Первый выход ШИМ заведен на GPIO18, другие каналы ШИМ задействованы на аудио-выходе. Выполним следующие команды для формирования на GPIO18 ШИМ сигнала. Настраиваем первый канал PWM (GPIO18):

gpio mode 1 pwm

Задаем скважность от 0 до 1024:

gpio pwm 1 500

Светодиод должен светиться вполсилы. Поэкспериментируйте с ШИМ. Попробуйте задать следующие значения:

gpio pwm 1 10
gpio pwm 1 1023

Выключаем ШИМ:

gpio unexport 1

или

gpio unexportall

Генерирование аппаратного ШИМ сигнала на Python

Чтобы использовать ШИМ в Python надо установили WiringPi-Python:

sudo apt-get install python-dev python-setuptools
git clone https://github.com/WiringPi/WiringPi-Python
cd WiringPi-Python
git submodule update –init
python setup.py install
cd ..

Напишем срипт pwm.py:

nano pwm.py

Текст скрипта:

import time
import wiringpi
# GPIO pin 12 = BCM pin 18 = wiringpi pin 1
led_pin = 1
wiringpi.wiringPiSetup()
wiringpi.pinMode(led_pin, 2)
wiringpi.pwmWrite(led_pin, 0)
def led(led_value): wiringpi.pwmWrite(led_pin, led_value)
led(0)
while 1: for dc in range(0, 1023, 5): led(dc) time.sleep(0.01) for dc in range(1024, 0, -5): led(dc) time.sleep(0.01)

Запустим его:

python ./pwm.py

Светодиод будет плавно загораться и плавно гаснуть. Аппаратная реализация ШИМ обеспечивает более стабильный результат. К сожалению аппаратный выход в Raspberry Pi только один.

Но существует еще пара методов генерирования ШИМ. Через DMA, и использование внешнего PWM контроллера (ШИМ контроллера).

Эти методы рассмотрим ниже для управления сервоприводами, поскольку на светодиодах разница не будет заметна.

Управление сервоприводом

О сервоприводах и характеристиках управляющего сигнала я писал ранее в статье Управление сервоприводом (сервомашинкой) с помощью микроконтроллера ATMega.

Обычно сервоприводы используют питание 5В. Маломощный сервопривод можно питать от Raspberry Pi. Но если привод потребляет достаточно большой ток, или Вам нужно подключить несколько сервомашинок, лучше не нагружать Raspberry Pi и использовать отдельный источник питания. Схема подключения сервопривода:

Управление сервоприводом с помощью программно сформированного ШИМ

Сначала попробуем формировать ШИМ для управления сервоприводом программно. Создадим скрипт servo.py:

nano servo.py

Текст скрипта:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(17,GPIO.OUT)
p=GPIO.PWM(17,50)
p.start(7.5)
try: while True: p.ChangeDutyCycle(7.5) print “Left” time.sleep(1) p.ChangeDutyCycle(12.5) print “Center” time.sleep(1) p.ChangeDutyCycle(2.5) print “Right” time.sleep(1)
except KeyboardInterrupt: p.stop() GPIO.cleanup()

Запустим servo.py:

python ./servo.py

Я намеренно вставил функции print в код. Наличие этих функций оказывает описанную ранее проблему нестабильности программно сформированного ШИМ. Сервомашинка НЕ фиксируется в заданном положении и дергается. Если удалить инструкции print, проблема уменьшается или вообще исчезает.

Управление сервоприводом с помощью ШИМ, сформированного через DMA

Устанавливаем RPIO:

apt-get install python-setuptools
easy_install -U RPIO

Создаем срипт servo_dma.py:

nano ./servo_dma.py

Текст скрипта:

import time
from RPIO import PWM
servo = PWM.Servo()
# Set servo on GPIO17 to 900.s (0.9ms)
servo.set_servo(17, 900)
# Set servo on GPIO17 to 2000.s (2.0ms)
#servo.set_servo(17, 2000)
try: while True: servo.set_servo(17, 750) print “Left” time.sleep(1) servo.set_servo(17, 1500) print “Center” time.sleep(1) print “Right” servo.set_servo(17, 2500) time.sleep(1)
except KeyboardInterrupt: # Clear servo on GPIO17 servo.stop_servo(17)

Запустим его

python ./servo_dma.py

Теперь сервопривод работает стабильно. То есть, для управления сервоприводами о программном ШИМ желательно вообще забыть.

Подробности использования RPIO читайте здесь: http://pythonhosted.org/RPIO/pwm_py.html#examples

На этом видео видно разницу между различными способами генерирования ШИМ сигнала:

Servoblaster

Существует проект Servoblaster, который тоже работает через DMA. С помощью него можно управлять до 8 сервоприводами. Servoblaster устанавливается как демон и позволяет управлять сервоприводами через файлы устройств.

То есть, управлять сервами можно через файловую систему.

Это позволяет управлять сервами, используя любой язык программирования или из командной строки и не требует установки дополнительных модулей таких как RPIO, который мы устанавливали ранее для Python.

Установим Servoblaster:

git clone http://github.com/richardghirst/PiBits.git
cd PiBits/ServoBlaster/user
make
sudo make install

Проверяем установился ли Servoblaster корректно:

ls /dev | grep servoblaster

Должны увидеть:

servoblaster
servoblaster-cfg

Можно просмотреть конфиг Servoblaster-а:

cat /dev/servoblaster-cfg

Выводы на которые можно подключать сервоприводы приведены в следующей таблице:

Servo numberGPIO numberPin in P1 header
4 P1-7
1 17 P1-11
2 18 P1-12
3 21/27 * P1-13
4 22 P1-15
5 23 P1-16
6 24 P1-18
7 25 P1-22

*– RaspberryPi B и RaspberryPi B Revision 2 имеют разницу в распиновке. Подробнее здесь: http://www.avislab.com/blog/raspberry-pi-install/

Допустимые значения положения зависят от вашего сервопривода. В большинстве случаев они лежат в диапазоне от 80 до 249. Напишем следующий срипт для управления сервоприводом:

nano ./servo_blaster.py

Текст скрипта:

import time
# Servo Channel 1 => GPIO 17
servoChannel = 1
def setServo(servoChannel, position): servoStr =”%u=%u
” % (servoChannel, position) with open(“/dev/servoblaster”, “wb”) as f: f.write(servoStr)
if __name__ == '__main__': val = 50 direction = 1 while True: #print val setServo(servoChannel, val) time.sleep(.01) if val == 249: direction -= 1 elif val == 50: direction = 1 val += direction

Запустим его:

python ./servo_blaster.py

Есть одна особенность Servoblaster. Пока он запущен, он занимает 8 указанных в таблице выходов и под другие цели Вы их уже не сможете задействовать. Попробуйте запустить ранее написанные скрипты:

python ./servo.py
python ./servo_dma.py

Сервомашинка не работает как следует.

Попробуем остановить демон Servoblaster и повторить попытку. Останавливаем Servoblaster с помощью команды:

sudo killall servod

Проверяем нет теперь servod в запущенных процессах:

ps ax | grep servod

Повторяем запуск скриптов:

python ./servo.py
python ./servo_dma.py

Все работает как следует. Запускаем servod командой:

/usr/local/sbin/servod –idle-timeout=2000

Возникает вопрос: а что делать, если надо задействовать лишь несколько каналов, а не все 8? Servoblaster можно конфигурировать благодаря следующим опциям:

–pcm tells servod to use PCM rather than PWM hardware to implement delays –idle-timeout=Nms tells servod to stop sending servo pulses for a given output N milliseconds after the last update –cycle-time=Nus Control pulse cycle time in microseconds, default 20000us –step-size=Nus Pulse width increment step size in microseconds, default 10us –min={N|Nus|N%} specifies the minimum allowed pulse width, default 50 steps or 500us –max={N|Nus|N%} specifies the maximum allowed pulse width, default 250 steps or 2500us –invert Inverts outputs –dma-chan=N tells servod which dma channel to use, default 14 –p1pins= tells servod which pins on the P1 header to use

–p5pins= tells servod which pins on the P5 header to use

Источник: http://www.avislab.com/blog/raspberry-pi-pwm_ru/

Нужен ли BAM vs ШИМ и как управлять светодиодами микроконтроллером

Речь пойдёт об изготовлении каких-то больших “индикаторов” на базе микроконтроллера. Световой рекламы, например. Где принципиальной особенностью может быть необходимость плавного зажигания и гашения светодиодов.

Есть разные методы это сделать, первый и очевидный — широтно-импульсная модуляция.

Причём реализуемая в таких случаях, как правило, полностью программно ввиду того, что число каналов (отдельных диодов или диодных лент) достаточно велико и практически сопоставимо с числом выводов микроконтроллера вообще (а может быть и больше, если используется SPI и регистры сдвига), а число аппаратных модулей ШИМ у дешёвых МК обычно весьма ограничено. Практически период ШИМ должен выбираться достаточно коротким, чтобы мерцание не было заметно. Где-то от 100Гц до 1КГц, чем выше, тем лучше. Но при большом числе каналов частоту сверху начинает ограничивать производительность микроконтроллера — он просто не успеет с нужной частотой обсчитать состояние каждого вывода. А при низких частотах начинает слишком явно проявляться негативное свойство ШИМ, особенно хорошо заметное при коэффициенте заполнения близком к 0.5 — на выходе практически меандр и мерцание становится особенно заметным.

С этим можно бороться осуществляя перестановку битов на выходе ШИМ. Например, было 11111111111111100000000000000, а стало 10010011011011001001001101101. Соотношение нулей и единиц то же самое, следовательно и яркость свечения диода. А мерцание уже практически не заметно.

Вопрос, как это сделать. Можно использовать алгоритм брезенхема для равномерного перемешивания нулей и единиц (легко найти в интернете). Но он требует слишком больших вычислительных расходов. А процессорного времени и так не хватает, иначе проще было поднять частоту ШИМ.

Можно использовать свойство взаимо-простых чисел N и M, что вычисляя каждый раз i=(i+N)%M, для начального значения i=0, i пройдёт все значения от 0 до M-1, но не последовательно, а с каким-то шагом.

Переменную i можно использовать как значение “счётчика” сравниваемое на каждом шаге с амплитудой сигнала и на основе сравнения выводится 0 или единица.

Ниже приведён пример для периода ШИМ равном 30, в левой колонке что получается при обычном алгоритме ШИМ (последовательность выводимых битовых значений), в правой то, что получается по описанному выше алгоритму:

0: 00000000000000000000000000000 00000000000000000000000000000
1: 10000000000000000000000000000 00000000000000000000000000001
2: 11000000000000000000000000000 00000000000010000000000000001
3: 11100000000000000000000000000 00000000000010000000000001001
4: 11110000000000000000000000000 00000000010010000000000001001
5: 11111000000000000000000000000 00000000010010000000001001001
6: 11111100000000000000000000000 00000010010010000000001001001
7: 11111110000000000000000000000 00000010010010000001001001001
8: 11111111000000000000000000000 00010010010010000001001001001
9: 11111111100000000000000000000 00010010010010001001001001001
10: 11111111110000000000000000000 10010010010010001001001001001
11: 11111111111000000000000000000 10010010010011001001001001001
12: 11111111111100000000000000000 10010010010011001001001001101
13: 11111111111110000000000000000 10010010011011001001001001101
14: 11111111111111000000000000000 10010010011011001001001101101
15: 11111111111111100000000000000 10010011011011001001001101101
16: 11111111111111110000000000000 10010011011011001001101101101
17: 11111111111111111000000000000 10011011011011001001101101101
18: 11111111111111111100000000000 10011011011011001101101101101
19: 11111111111111111110000000000 11011011011011001101101101101
20: 11111111111111111111000000000 11011011011011101101101101101
21: 11111111111111111111100000000 11011011011011101101101101111
22: 11111111111111111111110000000 11011011011111101101101101111
23: 11111111111111111111111000000 11011011011111101101101111111
24: 11111111111111111111111100000 11011011111111101101101111111
25: 11111111111111111111111110000 11011011111111101101111111111
26: 11111111111111111111111111000 11011111111111101101111111111
27: 11111111111111111111111111100 11011111111111101111111111111
28: 11111111111111111111111111110 11111111111111101111111111111
29: 11111111111111111111111111111 11111111111111111111111111111

Очевидно, что во втором случае (правая колонка) биты оказались перемешаны более равномерно и мерцание будет менее заметно. Данные получены с помощью представленной ниже программы. Взаимо-простые числа в данном случае 29 (период на единицу больше) и 9 (шаг).

for v=0:29 printf(“%u: “, v); for i=0:28 if (v > i) printf(“1”); else printf(“0″); end end printf(” “); j=0; for i=1:29 j=mod(j+9, 29); if (v > j) printf(“1”); else printf(“0″); end end printf(”
“);
end

Шаг стоит выбирать примерно равным от четверти до половины периода. Список взаимо-простых чисел можно найти в интернете или вычислить по алгоритму приведённому в Wikipedia (en.wikipedia.org/wiki/Coprime_integers).

Другой специфической проблемой может стать источник питания. Если множество диодов переключаются синхронно, то пики потребления приводят к сильному падению напряжения в момент включения, что может быть заметно визуально и влиять на электронную схему в целом.

Либо следует применять более качественный источник питания, либо начало периода ШИМ для разных каналов разнести во времени.

Что в описываемом выше случае можно реализовать добавлением к i некоторой константы n*P/N, где n — номер канала, P — период, N — общее число каналов.

Есть также известный способ управления светодиодами называемый ВАМ (Bit Angle Modulation). У него есть преимущество, применительно к микроконтроллерам: требуется меньшее время на вычисления. Так для шим с периодом P нужно, соответственно, P раз вычислять выводимые значения. А для BAM только log2(P).
Но есть и недостатки:

  • во-первых для BAM невозможно выбирать период не кратный 2^N. Например, известно, что ШИМ не успевает отрабатывать с периодом 64, но успевает с периодом 50. А в случае с BAM останется ограничиться периодом 32. В последнем случае плавность зажигания уже под вопросом, видно ступенчатое изменения яркости.
  • Во-вторых BAM не позволит более равномерно перемешать биты на выходе как показано выше и получить меньшее мерцание, при выводе амплитуд близким к 0.5 периода мерцание при использовании BAM будет максимально.

Кроме того, BAM хоть и требует, суммарно, меньше времени на вычисления, в пике он требует такой же производительности как ШИМ: прерывания при выводе младших битов учащаются каждый раз в 2 раза и при выводе самого младшего бита идут с такой же частотой как у ШИМ.

Но если микроконтроллер успевает их обслужить в этом случае, почему он не успеет для всех остальных выводимых значений ШИМ? То преимущество BAM, что требуется меньше вычислений, по сравнению с ШИМ на самом деле весьма эфемерно и является преимуществом только в случае, например, если кроме управления светодиодами микроконтроллер занят какими-то другими задачами, требующими тоже большого количества процессорного времени, что вряд ли.

Нужно рассмотреть ещё один вопрос. Алгоритм непосредственно управления индикацией. Допустим, есть программа которая для N каналов выводит заданные для каждого канала интенсивности методом ШИМ.

Но как из этого получить динамичную картинку? Нужна “программа” по которой будут включаться те или иные сегменты изображения. И нужен интерпретатор этой программы.

Интерпретатор на самом деле не сложный, он может оперировать функциями “включить такую-то яркость на таком-то канале с такой-то скоростью перехода (плавно)”, “пауза столько-то миллисекунд” и “конец или переход на начало программы”. Это, наверное, минимум.

Возможен и более сложный язык, но это отдельная история. Можно сделать интерпретатор байткода (скорей, слов в ПЗУ), очевидно как. И какую-либо программу для перевода описания “программы” из текста в “байткод”.

Для последнего подойдёт, наприме, макроассемблер (встроенный в AVR-studio не в полной мере является таковым). Либо можно поступить проще, с помощью того же макро-ассемблера, из псевдоинструкций (“установить яркость”, “пауза”, “конец”) генерировать сразу непосредственно машинный код вызывающий нужные функции. Это будет основной цикл программы. А обработка ШИМ может вестись исключительно в прерываниях.

Источник: http://embedders.org/blog/fk0/nuzhen-li-bam-vs-shim-i-kak-upravlyat-svetodiodami-mikrokontrollerom.html

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}