Урок 4 – цифровые входы

STM32F4. Урок 4 – цифровые входы

Данная библиотека используется для считывания данных с цифровых выводов микроконтроллера. Используемые выводы должны быть объявлены в «stm32_ub_dig_in.h» и присвоены соответствующие значения в файле «stm32_ub_dig_in.c». Для каждого входа можно так же включить подтягивающее сопротивление (три режима: отсутствует, подтяжка «вверх», подтяжка «вниз»).

Начиная с библиотеки версии 1.2 в «stm32_ub_dig_in.h» можно включить защиту от дребезга контактов, использующую таймер. Тогда станут доступны функции “OnHiLevel”, “OnHiEdge” и “OnLoEdge”. Эти функции возвращают “true”, когда происходит событие.

В примере используется 4 вывода: PD3, PD6, PD11, PE4.

Требования:

  • Подключаемые модули CooCox-IDE : GPIO (TIM, MISC)
  • Поддерживаемые библиотеки: отсутствуют.

Перечисления:

typedef enum { DIN_PD3 = 0, // PD3-Pin DIN_PD6 = 1, // PD6-Pin DIN_PD11 = 2, // PD11-Pin DIN_PE4 = 3 // PE4-Pin
}DIN_NAME_t;

Функции:

void UB_DigIn_Init(void); // Инициализация выводов цифровых входов
BitAction UB_DigIn_Read(DIN_NAME_t dig_pin); // считать уровень на входе (без защиты от дребезга)
bool UB_DigIn_OnHiLevel(DIN_NAME_t dig_pin); // true, если установлен высокий уровень (с защитой от дребезга)
bool UB_DigIn_OnHiEdge(DIN_NAME_t dig_pin); // true, если появился высокий уровень по фронту (с защитой от дребезга)
bool UB_DigIn_OnLoEdge(DIN_NAME_t dig_pin); // true, если появился низкий уровень по фронту (с защитой от дребезга)

Пример использования:

//————————————————————–
// File : main.c
// Datum : 16.02.2013
// Version : 1.0
// Autor : UB
// EMail : mc-4u(@)t-online.de
// Web : www.mikrocontroller-4u.de
// CPU : STM32F4
// IDE : CooCox CoIDE 1.7.0
// Module : CMSIS_BOOT, M4_CMSIS_CORE
// Function : Demo of Button Library
// Reference: These two files must be written to 8MHz
// “cmsis_boot/stm32f4xx.h”
// “cmsis_boot/system_stm32f4xx.c”
//————————————————————– #include “main.h”
#include “stm32_ub_dig_in.h”
#include “stm32_ub_dig_out.h” int main(void)
{ BitAction wert; SystemInit(); // Инициализация настроек кварца UB_DigIn_Init(); // Инициализация цифровых входов UB_DigOut_Init(); // Инициализация цифровых выходов while(1) { // Зачитать уровень на входе PD3 и установить полученное значение на выходе PB2 wert=UB_DigIn_Read(DIN_PD3); UB_DigOut_Pin(DOUT_PB2,wert); // Зачитать уровень на входе PD6 и установить полученное значение на выходе PB7 wert=UB_DigIn_Read(DIN_PD6); UB_DigOut_Pin(DOUT_PB7,wert); // Зачитать уровень на входе PD3 и установить полученное значение на выходе PC6 wert=UB_DigIn_Read(DIN_PD11); UB_DigOut_Pin(DOUT_PC6,wert); // Зачитать уровень на входе PE4 и установить полученное значение на выходе PC13 wert=UB_DigIn_Read(DIN_PE4); UB_DigOut_Pin(DOUT_PC13,wert); }
}

Режим работы:

  • GPIO-выводы PB2, PB7, PC6 и PC13 настраиваются как цифровые выходы (в библиотеке);
  • GPIO-выводы PD3, PD6, PD11 и PE4 настраиваются как цифровые входы (в библиотеке);
  • на входах считывается уровень сигнала, и полученные данные устанавливаются на выходах.

Библиотека, использованная в примере: stm32_ub_dig_out, stm32_ub_dig_in.

В приложении проект CooCox и отдельная библиотека для использования в других проектах. Автор оригинала статьи просит задавать вопросы на его сайте на немецком или английских языках.

Оригинал статьи

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

  • Demo_04_DigIn_rus.rar (201 Кб)
  • ub_stm32f4_digin_v102_rus.rar (5 Кб)

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

цифровые микросхемы – начинающим ( занятие_4 )

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

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

  По прежнему объектом эксперементов остается микросхема К561ЛА7 (или К176ЛА7, что в принципе одно и тоже). Принципиальная схема одновибратора показа­на на рисунке 1.

 В нем, как и в мультивибрато­ре имеется всего два логических элемента, первый из них используется по своему прямому назначению как элемент “И-НЕ”, а входы второго соединены вместе и он работает как элемент “НЕ” (инвертор). Кнопка S1 выполняет функции источника запускающих импульсов.

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

2 подключен вольтметр со шкалой 0-1ОВ (лучше простой стрелочный прибор – тестер, но можно и цифровой мультиметр).

На схеме номиналы конденсаторов и резисторов даны в виде интервала, чтобы проще было найти необходимые детали. Например “R1 10-100К” обозначает, что сопротивление R1 может быть от 10 до 100 кОм, например 68 К или ЗЗК или 12К и т.д.

А конденсатор С1 должен иметь емкость в пределах 10-30 мКф, например 22 мКф.

Нужно иметь ввиду, что чем больше будет емкость С1 и больше сопротивление R2 тем более длительные импульсы будут получаться на выходе одновибратора и тем проще их будет регистрировать при помощи вольтметра.

Для питания используем батарею на 9 В, составленную из двух “плоских” батарей на 4,5В, включенных последовательно, или от одной батареи на 9В типа “Крона”.

Собрав схему, показанную на рисунке 1, включите питание и сразу измерьте напряжение на выводе 4 микросхемы. Напряжение должно быть на уровне логической единицы (7-9В).

Затем измерьте напряжение на соединенных вместе выводах 5 и 6, здесь должен быть логический нуль (0-2В). На выводе 3 микросхемы тоже будет нуль.

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

Теперь подключите вольтметр обратно, к выводу 4 микросхемы и наблюдая за его стрелкой кратковременно нажмите и отпустите кнопку S1 (если кнопку найти не удалось можно просто подключить два оголенных провода, которые замыкать друг с другом, в этом случает кратковременно прикоснитесь одним проводом к другому). В этот момент на выходе элемента D1.2 уровень упадет до нулевого (следите за стрелкой вольтметра), а затем, через некоторое время, уровень снова подскочит до единичного. И так будет повторяться каждый раз когда вы будите нажимать и отпускать кнопку. Попробуйте нажать на кнопку быстро несколько раз подряд (но так чтобы уложиться во время 1-2 секунды). Несмотря на то сколько раз подряд вы успели нажать или на сколько быстро вы сделали одно нажатие, все равно, на выводе 4 микросхемы будет формироваться один импульс с одной и той же длительностью.

Длительность импульса на выходе элемента D1.2 всецело зависит от емкости конденсатора С1 и сопротивления резистора R2.

Можно попробовать последовательно с R2 включить переменный резистор сопротивлением 200-500 кОм и поворачивая его движок изменять время в течении которого стрелка прибора будет падать до нулевого уровня после нажатия на кнопку. И таким образом регулировать длительность выходного импульса.

Разобраться в принципе действия одновибратора помогут временные диаграммы, показанные на рисунке 2. В исходном положении, когда на входе 2 элемента D1.1 единица (диаграмма 1D1) на выходе этого элемента ноль (диаграмма 3D1), на входе второго элемента также ноль (5.6D1) и на его выходе единица (4D1). Теперь посмотрим что происходит при нажатии на кнопку S1. В этот момент уровень на входе 2 D1.

1 падает до нуля, поскольку в этот момент на вывод 1 этого элемента поступает единица с выхода элемента D1.2, то элемент, действуя по правилу элемента “И-НЕ” переводит свой выход в единичное состояние (диаграмма 3D1). Конденсатор С1 начинает заряжаться через R2 и в первый же момент начала его зарядки его зарядный ток устанавливает единичный уровень на входах элемента D1.2 (диаграмма 5.6D1).

В этот момент уровень на выхода этого элемента (по закону инвертора) становится нулевым (диаграмма 4D1), этот нуль поступает на вывод 1 элемента D1.1. Поскольку D1.

1 элемент “И-НЕ”, он принудительно удерживается этим уровнем в состоянии единицы на выходе, и не реагирует на изменение уровня на его втором входе, выводе 2 (можно сколь угодно продолжать нажимать кнопку, элемент на это не реагирует).

А тем времени конденсатор С1 продолжает заряжаться через R2, и скорость его заряда зависит от сопротивления R2 и емкости С1.

Постепенно напряжение на R2 падает (по мере зарядки конденсатора) и в какой-то момент оно становится равным порогу перехода элемента D1.2 с единичного на нулевой уровень. В этот момент уровень на выводах 5 и 6 D1.2 становится нулевым и на выходе D1.

2 устанавливается логическая единица. Эта единица поступает на вывод 1 D1.1 и этот элемент снова готов принять импульс, поступающий от кнопки.

Следующее логическое устройство, которое можно собрать на двух элементах микросхемы К561ЛА7 (К176ЛА7) — RS-триггер (рисунок 3). Чтобы понять что такое RS-триггер вспомним прошлогодние эксперименты с тиристором.

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

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

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

После того как вы собрали схему нажмите на кнопку S1 и отпустите её.

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

Теперь кратковременно нажмите на кнопку S2, при этом светодиод VD2 по­гаснет но загорится VD1. И будет гореть и после отпускания кнопки.

Таким образом RS-триггер пред­ставляет собой свое­образный “квазисенсорный” переключатель этих двух светодиодов, примерно та­кой как в цветных теле­визорах для переключения программ (кстати, пере­ключатели программ этих телевизоров построенны как раз на основе RS-триггеров).

Разберемся в работе RS-триггера. Пред­положим в исходном состоянии у нас горит светодиод VD1. Это значит, что на выходе элемента D1.1 логический нуль, а светодиод VD2 не горит, так как на выходе D1.2 логическая единица. Значит на вывод 2 D1.1 с выхода D1.2 поступает единица. Что произойдет если нажать на кнопку S1 ?

Пока S1 не нажата на вывод 1 D1.1 через резистор R1 поступает высокий логический уровень (от плюса питания), на вывод 2 D1.1 при этом также (с выхода D1.2) поступает единица. Если на обеих входах элемента “И- НЕ” единицы, то нет ничего удивительно в том, что на его выходе ноль и светодиод VD1 горит.

Теперь, когда мы нажимаем кнопку S1 уровень на выводе 2 D1.1 падает до нуля, и по логике действия элемента “И-НЕ” на его выходе должна установиться единица. Так оно и будет. Но как получается так, что на его выходе останется единица и после отпускания кнопки S1? Дело в том, что эта единица (с выхода D1.

1 поступит на один вход (вывод 5) элемента D1.2, на второй вход которого и без того поступает единица через резистор R2. В этот момент, по логике действия элемента “И-НЕ”, на выходе D1.2 установится логический нуль, который поступит на вывод 2 D1.1 и будет удерживать элемент D1.

1 в состоянии единицы на выходе (если на один из входов элемента И-НЕ поступает нуль, на его выходе всегда будет единица, независимо от того какой уровень на втором входе). Таким образом RS- триггер перейдет в противоположное устойчивое положение, при котором на выходе элемента D1.

2 будет ноль и будет гореть светодиод VD2, а на выходе D1.1 будет единица и светодиод VD1 погаснет.

Почему RS-триггер так называется ? Дело в том, что R — значит “Reset”, выключение, сброс, a S — “Set”, включение. Предположим что у нас имеется только один светодиод VD1, при этом за состояние “S” примем зажигание этого светодиода, а за “R” его выключение.

Тогда кнопка S2 — будет вход “S” триггера, поскольку при нажатии на нее светодиод включится, а кнопка S1 — будет вход “R”, потому что при нажатии на нее триггер “сбрасывается” и светодиод VD1 выключается.

Второй выход — светодиод VD2, если мы его подключим, в данном случае он (этот выход) будет инверсным, это значит, что его состояние полностью противоположно состоя­нию светодиода VD1, который мы приняли за прямой выход.

И так что нужно знать о RS-триггере. У него есть два входа R и S и два выхода прямой и инверсный.

Если триггер сделан на элементах И-НЕ, то при подаче отрицательного импульса на его вход S включается его прямой выход и выключается инверсный, а при подаче импульса на вход R включается инверсный выход, и прямой выключается.

Если RS-триггер установился в какое то положение он будет оставаться в нем до тех пор пока не поступит импульс переключения его в противоположное положение.

Раздел: [Теоретические материалы]

Источник: http://www.cavr.ru/article/5221-cifrovye-mikrosxemy—nachinayushhim-(-zanyatie_4-)

Аналоговые выводы (пины)

Опубликовано 09.07.2014 11:54:00

Продолжим знакомство с платформой Arduino и в данной статье рассмотрим аналоговые входы.

Основным применением аналоговых входов в тематике Arduino является чтение значений аналоговых датчиков. В тоже время стоит не забыть упомянуть, что аналоговые входы могут использоваться как цифровые порты входов/выходов рассмотренные в предыдущем уроке (об этом в конце статьи). 

На плате Arduino UNO их 6 (A0-A5). У других плат количество может отличаться, смотрите в спецификации.

Благодаря встроенному АЦП (аналого-цифровой преобразователь), данные входы могут считывать напряжение подаваемое на них. Микроконтроллеры Atmega 328, используемые в Arduino UNO, содержат шестиканальный АЦП, разрешение которого составляет 10 бит. Это позволяет на выходе получать значения от 0 до 1023 (всего 1024 градации). 

Для того чтобы считать показание на аналоговом входе следует вызвать функцию

  // Производим чтение с аналогового входа A0
  analogRead(0);

Данная функция возвращает значение от 0 до 1023 пропорционально напряжению на аналоговом входе

В качестве первого примера работы с аналоговыми входами подключим потенциометр. 

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

Большим потенциометром с крутилкой конечно удобнее пользоваться, но он обладает толстыми ножками которые быстро расшатывают контакты макетной платы.

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

Для эксперимента нам понадобятся:

Плата Arduino, соединительные провода “папа-папа”, макетная плата на 400 контактов, потенциометр 10кОм

Описание примера:

Потенциометр  это резистор меняющий свое сопротивление в зависимости от угла поворота крутилки. Он имеет 3 вывода.

 На крайние выводы подаем 5V и GND (полярность не имеет особого значения, если выводы поменять местами, значения просто инвертируются).

 Между крайними выводами расположено резистивное вещество, по которому движется ползунок соединенный со средним выводом. При повороте крутилки изменяется сопротивление, а вместе с тем и напряжение. 

На реальной макетной плате всё будет выглядеть следующим образом:

Пример программного кода:

void setup()
{
  Serial.begin(9600); // Задаем скорость работы монитор порта
} void loop()
{
  int analogValue = analogRead(0); // Задаем переменную analogValue для считывания показаний
  Serial.println(analogValue); // Выводим полученое значение в порт
  delay(500); // Ждем пол секунды
}

 

Перевод значения аналогового сигнала в вольты

Для перевода получившегося значения в вольты достаточно вычислить шаг и умножить его на получаемое значение.

Для вычисления шага поделим опорное напряжение на 1024 градации

5В / 1024 =  0.0049 Вольт

Т.е. При получаемом аналоговом значении в 500, на порт контроллера приходит ( 500 * 0.0049) 2.45В.

пример программного кода:

float Step = 5.0F / 1024; // Вычисляем шаг Uопорн / на градацию void setup() { 
Serial.begin(9600); // Задаем скорость работы монитор порта
}  void loop() { 
int analogValue = analogRead(0); // Задаем переменную analogValue для считывания показаний
float voltageValue = analogValue * Step; // Переводим в вольты (показание * шаг)
Serial.println(voltageValue); // Выводим значение в вольтах в порт
delay(500); // Ждем пол секунды
}

Более точная работа аналогового входа 

Для того чтобы добиться более точных показаний с аналогового входа можно использовать 2 варианта:

• Функция analogReference()​

Задает опорное напряжение относительно которого происходят аналоговые измерения. 

analogReference(type);

Возможные настройки (type):

DEFAULT: установлено по умолчанию. при данной конфигурации опорное напряжение автоматически принимается за напряжение питания платы Arduino. 5В (на платформах с напряжением питания 5 В) или за 3.3 В (на платформах с напряжением питания 3.3В)   

На платформах Arduino “из коробки” вывод AREF не задействован. В этом случае при настройке DEFAULT к выводу подключается внутреннее напряжение AVCC. Соединение является низко-импедансным и любое напряжение подведенное к выводу в этот момент может повредить микросхему ATmega.

INTERNAL: встроенное опорное напряжение 1.1В на микроконтроллерах ATmega168 и ATmega328, и 2.56В на ATmega8.

Это может пригодиться для более точного измерения напряжения лежащего в пределах ниже 1.1В либо 2.56В. Болле точная работа достигается за счет меньшего шага 5/1024 против 1.1/1024. Значения соответствующее или превышающее 1.1В (2.56В) будут конвертироваться АЦП в 1023. 

EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF. 

После того как мы задали функцию, происходит отключение обоих внутренних источников. Теперь можно подключить внешнее напряжение, которое и будет являться опорным для АЦП. Внешнее напряжение рекомендуется подключать к выводу AREF через резистор 5 кОм.

• Ручная установка опорного напряжения

Актуальна для измерения крайне малого напряжения   

Искажения при работе с аналоговыми входами появляются по причине того, что по дефолту за опорное напряжение принимается 5В, в то время как стабилизаторы напряжения на плате Arduino могут немного отклоняться от эталонного значения и выдавать к примеру 4.85В.   4.85 / 1024 = 0.0047 (при эталонном шаге в 0.0049)

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

float Step = 4.85F / 1024; // Вычисляем шаг Uопорн / на градацию

Использование аналоговых входов в качестве цифровых выводов

Аналоговые входы могут использоваться как цифровые порты входов/выходов рассмотренные в предыдущем уроке

Для этого, для UNO, в коде их нужно записывать как цифровые с 14 по 19. К примеру, для A0 

  // Инициализируем аналоговый pin 0 как выход
  pinMode(14, OUTPUT);
  // Инициализируем аналоговый pin 0 как вход
  pinMode(14, INPUT);

Читать ранее:

•  Урок 1. Цифровые выводы

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

Источник: http://zelectro.cc/arduino_lesson_2

Урок 13. Подключение клавиатуры 4*4 и пьезоизлучателя к Arduino

Теперь научимся подключать устройство ввода к Ардуине. В этом примере разберемся, как подключить мембранную клавиатуру 4*4

Данный пример будет выполнять две задачи:

  1. Первая задача: определяет, какая из клавиш была нажата на клавиатуре и передать информацию по сериал порту на компьютер, где в “мониторе последовательного порта “.
  2. Вторая задача: при каждом нажатии клавиш издавать звуковой сигнал. У каждой клавиши звуковой сигнал будет разный.

В данном уроке нам понадобится:

Для реализации проекта нам необходимо установить библиотеки:

  • Библитетка keypad для клавиатуры 4×4

Сборка:

1) Клавиатуру удобнее всего подключить к Ардуине проводками Папа-Папа.

Контакты на клавиатуре отсчитываются слева на право.

Клавиатура 4*4Arduino (uno)
Контакт 1 pin 11
Контакт 2 pin 10
Контакт 3 pin 9
Контакт 4 pin 8
Контакт 5 pin 7
Контакт 6 pin 6
Контакт 7 pin 5
Контакт 8 pin 4

Контакты к которым подключаем клавиатуру, могут быть перенастроены на любые другие цифровые контакты. Настраиваются здесь:

byte rowPins[ROWS] = {11,10, 9, 8}; byte colPins[COLS] = {7, 6, 5, 4};

2) Звуковой сигнал будет издаваться с помощью зуммера, его подключаем следующим образом:

ЗуммерArduino
GND GND
IO pin 3
VCC 5V или 3V

Контакт Pin3 так же может быть изменен на любой удобный вам цифровой выход. Настраивается здесь:

tone(3, (int)key*10, 300); // 3 – это и есть номер цифрового порта

Скетч:

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

#include // Подключаем библиотеку const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца
char keys[ROWS][COLS] = { {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'}
}; byte rowPins[ROWS] = {11,10, 9, 8}; byte colPins[COLS] = {7, 6, 5, 4}; Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup(){ Serial.begin(9600);
}
void loop(){ char key = keypad.getKey(); if (key){ Serial.println(key); // Передаем название нажатой клавиши в сериал порт tone(3, (int)key*10, 300); // Издаем звуковой сигнал длиной 300 миллисекунд }
}

Скачать скетч можно по этой ссылке

Видео:

Источник: https://lesson.iarduino.ru/page/urok-13-podklyuchenie-klaviatury-4-4-i-pezoizluchatelya-k-arduino

Работа ШИМ в ARDUINO | Что и как строить на земельном участке

Множество людей, почитав мое вступление и начальные уроки, так  и не поняли

Что такое ШИМ?

ШИМ- Широтно-Импульсная Модуляция, проще говоря- это оцифрованный аналоговый сигнал.

Применяется, например, для оцифровки звука, всем известный формат MP3 использует именно ШИМ для сжатия сигнала, например bitrate 256 kb/s означает что аналоговый сигнал переведен в цифровой (оцифрован) со значением 256 килобит, т.е. 256/8= 32 кБайта в секунду. Опять мало что говорит это значение? Представьте аналоговый сигнал длиной 1 секунду.

Принцип сжатия звука на основе MP3

Вертикальные прямоугольники, идущие от 0 до уровня сигнала называются битами оцифровки. Они следуют точно от 0 до моментального значения сигнала. Паузы между ними нет, они следуют строго друг за другом.

Что же означает, например 128 кБит/с- это значает что для оцифровки 1 секунды аналогового сигнала потребовалось 128*1024 (в цифровой технике приставка кило означает не 1000 а 1024)/8 (столько информации содержит 1 бит)= 16384, т.е.

таких вот серых прямоугольников! Каждый прямоугольник содержит информацию об уровне сигнала относительно 0, например моментальное значение 4 бита равно 110, оно передается в бинарном (цифровом) коде как 01101110, число 200 передастся как 11001000, всегда передается 8 значений в каждом бите информации, максимальное значение -255, ему соответствует код 11111111. Обратите внимание на 3 группу с надписью 256 кБит/с. Вы можете заметить что прямоугольники в 2 раза уже чем 128 кБит/с. Что это означает? Это означает что для описания 1 секунды аналогового сигнала нужно передать в 2 раза больше информации, соответственно нужно уже 16384*2=32768 бита. Но в то же время более узкий прямоугольник описывает более точно аналоговый сигнал. В самом деле взгляните на рисунок-

Как сжимается сигнал разными битрейтами.

там где при 128 битах расположен 1 прямоугольник, при 256 располагается уже 2, значит и форму сигнала он передаст более точно. Но одновременно с этим возрастает и поток данных. Именно таким образом происходит оцифровка аналогового сигнала.

Существует еще так называемый «плавающий битрейт«, он работает по следующему принципу: АЦП определяет участки где сигнал не имеет резких перепадов и изменений, тогда он понижает степень сжатия на этом участке- соответственно понижается битрейт, при частых сменах уровня сигнала и его перепадах требуется больше информации чтобы описать более точно сигнал и АЦП повышает битрейт. Этот вид сжатия позволяет экономить информацию передаваемую АЦП. Да, внешний вид оцифрованного сигнала не имеет такой плавности, он, скорее, построен из отрезков, описывающих этот сигнал, но зато его уже можно передавать и восстанавливать при частичной утере битов! Существует теорема Котельникова которая звучит примерно так:-«Любой цифровой сигнал можно восстановить если частота преобразования выше частоты сигнала в 2 раза».  Т.е. для восстановления аналогового сигнала в 20 кГц исходный сигнал должен быть не менее 40 кГц. Поэтому при качественных записях ставят качество 44кГц, а то и 96кГц! Это позволяет передавать более точно сигнал и, опять же , при утере битов восстанавливать потерянную информацию.

Как же все это относится к ARDUINO. Нам уже известно что цифровые входы/выходы работают в 8-битном режиме. Значит на порт постоянно передается информация из 8 сочетаний нолей и единиц, например число 110 из предыдущего примера передается как 01101110, МК сам расшифровывает его (если это необходимо) и получает точное значение. Предел 8 битных значений- от 0 до 255.

Аналоговые входы содержат 10- битный АЦП (Аналогово- Цифровой Преобразователь) и получается что любой поступающий аналоговый сигнал преобразуется в цифру но содержит уже не 8 сочетаний нолей и единиц а 10! Т.е. повышается точность получаемых данных! Предел 10-битных значений- от 0 до 1023.

Например, возьмем напряжение 5В и распределим его на 8 и на 10 бит. Значение 1 единицы 8-битных данных= 5/256=0,02В, 10-битное=5/1024=0,005В. Налицо более высокая точность 10-битных данных! Но в то же время просто соединить 10 и 8 битные данные нельзя из за их максимальных значений.

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

Чтобы преобразовать сигнал из 10- в 8-битное значение нужно просто разделить 10-битный сигнал на 4, как написано в примере здесь. Чтобы 8-битный сигнал привести к 10-битному нужно, соответственно, 8-битный сигнал умножить на 4. Кроме того в ARDUINO есть замечательная функция маппинга, т.е.

можно растягивать/сжимать любое значение. Выглядит она так:

y = map(x, 1, 50, 25, 100); — где, х- значение которое нужно обработать, т.е. преобразовать из одного типа в другой, 1-нижний предел преобразуемого значения, 50- верхний предел преобразуемого значения, 25- нижний предел преобразованного значения, 100- верхний предел преобразованного значения.

Пример:

/* Map an analog value to 8 bits (0 to 255) */
void setup() {}

void loop()
{
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 255);
  analogWrite(9, val);
}

Данный пример преобразует полученные данные с аналогового порта 0 (0-1023) в 8- битный цифровой сигнал (0-255), присваивает полученное значение в переменную val и передает его в 9 цифровой порт, который является ШИМ-портом. Т.е.

эту функцию можно с успехом использовать здесь и не делить полученные данные на 4 для перевода из 10-битного значения в 8-битное (Хотя, если честно, получается совершенно такой же результат). Кроме того, данная функция позволяет более точно преобразовывать нужные участки данных и поэтому её использование более предпочтительно во всех случаях.

Например вам не надо обрабатывать ВЕСЬ поток поступающих данных а ограничится значением до 511 по аналоговому входу. Тогда пример будет выглядеть так:

/* Map an analog value to 8 bits (0 to 255) */
void setup() {}

void loop()
{
  int val = analogRead(0);
  val = map(val, 0, 511, 0, 255);
  analogWrite(9, val);
}

Заметьте что 10- битный сигнал от 0 до 511 преобразовался в 8- битный от 0 до 255 (По сравнению с предыдущим примером мы «сжали» аналоговый сигнал и теперь на 1 бит цифрового сигнала приходится 512/256=2 бита аналогового, в предыдущем примере на 1 цифровой бит приходилось 1024/256=4 бита аналогового сигнала ). Так же можно повышать/ понижать любые пределы, т.е. при записи   val = map(val, 255, 768, 70, 198); мы сдвинули как диапазон по приему (255-768), так и ограничили значение val (70-198). Таким образом происходит преобразование аналогового сигнала в цифровой.

ШИМ выходы не могут быть «наполовину включенными», т.к. это все равно- цифровой выход и он может принимать только 2 значения- 0 (выключено) или 1 (включено).

Поэтому последовательность нулей и единиц задает время включения нагрузки. Нагрузка не успевает за такое короткое время включиться на полную мощность (если конечно не передается значение 255 на 8 битном выходе).

Покажу это на примере числа 110 из верхнего примера.

Форма сигнала на выходе ШИМ

Как видно из рисунка выход не включен на полную мощность, он включен всего в 5 битах из 8.

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

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

Например, если бы это была нагрузка типа лампы накаливания на 220В или ТЭНа на 220В, в данном случае она работала бы так как будто на нее подали напряжение приблизительно 100В! А так как скорость переключения битов очень высокая мы даже не заметим мерцания лампы (она же то и дело включается/отключается). Получается что мы регулируем напряжение шириной и частотой импульсов. Это и есть ШИМ- модуляция.

Следующий урок>>

Источник: http://samosdel.ru/arduino/urok-4-shim/

Модуль 4. Цифровые запоминающие устройства. Устройства сопряжения аналоговых и цифровых схем. – презентация

1 Модуль 4. Цифровые запоминающие устройства. Устройства сопряжения аналоговых и цифровых схем.<\p>

2 ТЕМА 15. Постоянные запоминающие устройства (ПЗУ). Структура ПЗУ с прожиганием. Программирование ПЗУ. Классификация ПЗУ. Оперативные запоминающие устройства (ОЗУ). Элемент статического ОЗУ. Типовая структура ОЗУ. Временная диаграмма работы Постоянные запоминающие устройства (ПЗУ). Структура ПЗУ с прожиганием. Программирование ПЗУ. Классификация ПЗУ. Оперативные запоминающие устройства (ОЗУ). Элемент статического ОЗУ. Типовая структура ОЗУ. Временная диаграмма работы<\p>

3 Постоянные запоминающие устройства (ПЗУ) ПЗУ представляет собой чисто комбинационную схему, имеющую n адресных входов и m выходов. Рисунок 15.1 Схемное обозначение ПЗУ<\p>

4 1)Всевозможные конъюнкции с помощью дешифратор 2)C помощью схем или собираются все нужные конъюнкции. 1)Всевозможные конъюнкции с помощью дешифратор 2)C помощью схем или собираются все нужные конъюнкции. ПЗУ организуются по двухъярусной структуре:<\p>

5 Рисунок 15.2 Структура ПЗУ Работа схемы: если все плавкие перемычки целы, то при выборе любого адреса на входы всех дизъюнкторов будет поступать хотя бы по одной единице, поэтому y 0 = y 1 = ··· = y m-1 = 1. Для занесения в схему какой-либо информации некоторые перемычки пережигаются (ПЗУ с прожиганием), тогда на некоторых дизъюнкторах на все входы поступают 0 и на выход подается 0. Работа схемы: если все плавкие перемычки целы, то при выборе любого адреса на входы всех дизъюнкторов будет поступать хотя бы по одной единице, поэтому y 0 = y 1 = ··· = y m-1 = 1. Для занесения в схему какой-либо информации некоторые перемычки пережигаются (ПЗУ с прожиганием), тогда на некоторых дизъюнкторах на все входы поступают 0 и на выход подается 0.<\p>

6 Прожигаемая ПЗУ Примером такой ПЗУ является К155РЕ3. ЕЕ структура 32 8 (32 слова по 8 битов каждое). Рисунок 15.3 ПЗУ К155РЕ3<\p>

7 Если перемычка П 0 – цела, то при выборе транзистора VT0 (по адресу открывается 0 выход дешифратора), тогда ток этого транзистора создает через делитель R1R2 на базе VT2 некоторый потенциал, VT2 открывается, и на выходе y0 появится 0. Если перемычка П 0 – цела, то при выборе транзистора VT0 (по адресу открывается 0 выход дешифратора), тогда ток этого транзистора создает через делитель R1R2 на базе VT2 некоторый потенциал, VT2 открывается, и на выходе y0 появится 0. VT1 в это время закрыт, т.к. потенциал его базы равен 0. Чтобы на выходе у0 по­лучить 1 необходимо перемычку П0 сжечь. Для этого Uпит2 повышают до уровня В; открывается стабилитрон VD, на базе VT1 появляется положительный потенциал, транзистор VT1 открывается и его ток сжигает перемычку. Для этого Uпит2 повышают до уровня В; открывается стабилитрон VD, на базе VT1 появляется положительный потенциал, транзистор VT1 открывается и его ток сжигает перемычку. Теперь на базе VT2 не будет положительного потенциала, VT2 – закрыт, следовательно у 0 = 1. Длительность прожигающего импульса выбирается в интервале 5 20мс. Если перемычка П 0 – цела, то при выборе транзистора VT0 (по адресу открывается 0 выход дешифратора), тогда ток этого транзистора создает через делитель R1R2 на базе VT2 некоторый потенциал, VT2 открывается, и на выходе y0 появится 0. Если перемычка П 0 – цела, то при выборе транзистора VT0 (по адресу открывается 0 выход дешифратора), тогда ток этого транзистора создает через делитель R1R2 на базе VT2 некоторый потенциал, VT2 открывается, и на выходе y0 появится 0. VT1 в это время закрыт, т.к. потенциал его базы равен 0. Чтобы на выходе у0 по­лучить 1 необходимо перемычку П0 сжечь. Для этого Uпит2 повышают до уровня В; открывается стабилитрон VD, на базе VT1 появляется положительный потенциал, транзистор VT1 открывается и его ток сжигает перемычку. Для этого Uпит2 повышают до уровня В; открывается стабилитрон VD, на базе VT1 появляется положительный потенциал, транзистор VT1 открывается и его ток сжигает перемычку. Теперь на базе VT2 не будет положительного потенциала, VT2 – закрыт, следовательно у 0 = 1. Длительность прожигающего импульса выбирается в интервале 5 20мс.<\p>

8 ПЗУ с УФ стиранием ПЗУ со стиранием информации ультрафиолетовым излучением в настоящее время наиболее широко используются в микропроцессорных системах. В БИС таких ПЗУ каждый бит хранимой информации отображается состоянием соответствующего МОП-транзистора с плавающим затвором (у него нет наружного вывода для подключения). Затворы транзисторов при программировании «1» заряжаются лавинной инжекцией, т.е. обратимым пробоем изолирующего слоя, окружающего затвор под действием электрического импульса напряжением 18 – 26 В. Заряд, накопленный в затворе, может сохраняться очень долго из-за высокого качества изолирующего слоя. Так, например, для ППЗУ серии К573 гарантируется сохранение информации не менее 15 – 25 тысяч часов во включенном состоянии и до 100 тысяч часов (более 10 лет) в выключенном.<\p>

9 ПЗУ с электрическим стиранием Они позволяют производить как запись, так и стирание (или перезапись) информации с помощью электрических сигналов. Для построения таких ППЗУ применяются структуры с лавинной инжекцией заряда, аналогичные тем, на которых строятся ППЗУ с УФ стиранием, но с дополнительными управляющими затворами, размещаемыми над плавающими затворами. Подача напряжения на управляющий затвор приводит к рассасыванию заряда за счет туннелирования носителей сквозь изолирующий слой и стиранию информации. По этой технологии изготовляют микросхемы К573РР2. Достоинства ППЗУ с электрическим стиранием:высокая скорость перезаписи информации и значительное допустимое число циклов перезаписи не менее Они позволяют производить как запись, так и стирание (или перезапись) информации с помощью электрических сигналов. Для построения таких ППЗУ применяются структуры с лавинной инжекцией заряда, аналогичные тем, на которых строятся ППЗУ с УФ стиранием, но с дополнительными управляющими затворами, размещаемыми над плавающими затворами. Подача напряжения на управляющий затвор приводит к рассасыванию заряда за счет туннелирования носителей сквозь изолирующий слой и стиранию информации. По этой технологии изготовляют микросхемы К573РР2. Достоинства ППЗУ с электрическим стиранием:высокая скорость перезаписи информации и значительное допустимое число циклов перезаписи не менее<\p>

10 Рассматриваемые типы запоминающих устройств (ЗУ) применяются в компьютерах для хранения информации, которая изменя­ется в процессе вычислений, производимых в соответствии с программой, и называются оператив­ными (ОЗУ). Информация, записанная в них, раз­рушается при отключении питания. Главной частью ЗУ является накопитель, состоящий из триггеров Рассматриваемые типы запоминающих устройств (ЗУ) применяются в компьютерах для хранения информации, которая изменя­ется в процессе вычислений, производимых в соответствии с программой, и называются оператив­ными (ОЗУ). Информация, записанная в них, раз­рушается при отключении питания. Главной частью ЗУ является накопитель, состоящий из триггеров Статические ОЗУ ОЗУ<\p>

11 Рисунок 15.4 Матрица ЗУ<\p>

12 Накопитель двухкоордииатпого ЗУ состоит из нескольких матриц (рис.9-1), количество которых определяется числом разрядов записываемого слова. Запоминаю­щие элементы(ЗЭ) одной матрицы расположены на пересечении адресных шин Х строк и Y столбцов, имеют одну общую для всех элементов разрядную шину. В ЗЭ одной матрицы записываются одноимен­ные разряды всех слов, а каждое слово в идентично расположенные запоминающие элементы ЗЭi, всех матриц, составляющие ячейку памяти. Таким обра­зом, в двухкоординатное четырехматричное ЗУ, матрицы которого содержат по 16 запоминающих элемен­тов (рис. 1), можно записать 16 четырехразрядных слов.<\p>

13 Динамические ОЗУ В них запоминающий элемент содержит только один транзисторн.(рис.15.5) Рисунок 15.5 Элемент динамической ОЗУ<\p>

14 Информация в таком элементе хранится в виде заря­да на запоминающем конденсаторе, обкладками которо­го являются области стока МОП-транзистора и подлож­ки. Запись и считывание ннформаини производятся пу­тем открывания транзистора по затвору и подключения тем самым заноминаюшей емкости к схеме усилителя- регенератора. Последний, по существу является триггерным элементом,который В зависимости от предварительной подготовки или принимает (счи­ тывает) цнформацию из емкоетной запоминающец ячейки, устаиавливаясь при этом в состояние 0 пли 1,или, наоборот, в режиме записи соотвегствующим образом заряжает ячейку, будучи иредварительно установленным в 0 нли 1<\p>

15 В режиме чтения триггер усилителя регенератора в начале специальным управляющим сигналом устанав­ ливается в неустойчивое равновесное состояние, из которого при подключении к нему запоминающей емкости он переключается в 0 или 1. При этом в начале он по­ требляет часть заряда, а затем при установке в устойчивое состояние, возвращает его ячейке осуществляя таким образом регенерацию ее состояния. В режиме хранения информации необходимо периодически производить регенерацию для компенсации ес­тественных утечек заряда. максимальный период цикла регенерации для каждой из ячеек обычно составляет 1 2 мс.<\p>

Источник: http://www.myshared.ru/slide/689751/

Аналоговые измерения с Arduino | РОБОТОША

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

Сегодня я расскажу об использовании и проведу тест производительности аналого-цифрового преобразователя (АЦП) Arduino. Тест я буду производить, используя оригинальную плату Arduino Mega 2560, в основе которой лежит микроконтроллер ATMega2560, работающий на частоте 16 Мгц.

Микроконтроллер ATMega328, на котором основаны Arduino Uno и Arduino Nano, также работает на частоте 16 МГц, так что все вышеизложенное, скорее всего, справедливо и для этих и аналогичных плат.

analogRead

Давайте посмотрим сколько же времени занимает аналого-цифровое преобразование с использованием стандартной функции analogRead.

Для определения моментов начала и конца преобразования я буду использовать 12 вывод в качестве маркера. Для начала повторим эксперимент, который я описывал в статье Оптимизируем digitalWrite на Arduino. Будем изменять уровень напряжения на 12 цифровом пине между состояниями LOW и HIGH. Для чистоты эксперимента я помещу внутрь loop бесконечный цикл.

Скетч, реализующий простые переключения на 12 цифровом выводе выглядит следующим образом:

void setup()

{

DDRB = B01000000; //устанавливаем 12 пин в режим выхода

}

void loop()

{

while(1)

{

  PORTB = B01000000; // устанавливаем пин 12 в состояние HIGH  

  PORTB = B00000000; // устанавливаем пин 12 в состояние LOW

}

}

Воспользуемся осциллографом и посмотрим на временные параметры работы этой программы:

Отсюда видно, что время переключения состояния пина занимает у нас 62 нс (длительность положительного импульса).

Теперь немного изменим скетч и добавим между переключениями функцию чтения аналогового сигнала analogRead на 3 аналоговом пине:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

int analogPin = 3; // входной аналоговый пин

int analogValue = 0; // значение аналогового сигнала

void setup()

{

DDRB = B01000000; // устанавливаем 12 пин в режим выхода

}

void loop()

{

while(1)

{

  PORTB = B01000000; // устанавливаем пин 12 в состояние HIGH

  analogValue = analogRead(analogPin); // читаем аналоговый сигнал

  PORTB = B00000000; // устанавливаем пин 12 в состояние LOW

  analogValue = analogRead(analogPin); // читаем аналоговый сигнал

}

}

Осцилограмма сигнала на 12 цифровом пине теперь будет выглядеть следующим образом:

Длительность переключения в 62 нс и время циклического возврата к началу работы программы в 124 нс не превышают погрешность измерения на этом временном масштабе и мы можем пренебречь этими временными промежутками. Отсюда видно, что время, которое затрачивается на аналого-цифровое преобразование примерно равно 112 мкс, поэтому максимальная частота выборки при использовании функции analogRead не превышает 8.9 кГц.

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

Используем прерывания АЦП

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

Такую выборку можно реализовать несколько более сложным способом, используя прерывания.

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

Разовая выборка

Разовая выборка — это на самом деле то, что Arduino делает при вызове функции analogRead. Мы не сможем получить значительных преимуществ, реализовав разовую выборку с помощью других средств. Поскольку перед запуском АЦП, в первую очередь проверяется флаг готовности АЦП, то это означает, что проверка флага в цикле ничем не отличается от того, что делает Arduino.

Непрерывная выборка

Хорошей идеей при непрерывной выборке сигнала является использование прерываний. Микроконтроллеры ATMega328 и ATMega2560 могут быть переведены в режим непрерывной выборки (free running mode).

В этом режиме АЦП запускается автоматически после завершения предыдущей обработки.

Каждый раз преобразование заканчивается генерированием прерывания, которое вызывает функцию обработки прерывания ISR (ADC_vect), в которой результат аналого-цифрового преобразования может быть считан и обработан.

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

Внутреннее опорное напряжение 1.1 В и входной аналоговый канал ADC3 выбираются при помощи ADMUX. Тактовая частота задается при помощи ADCSRA и в нашем примере установлена в виде делителя ÷16.

Одно аналоговое преобразование занимает 13 тактовых периодов. Частота дискретизации может быть вычислена, исходя из тактовой частоты микроконтроллера: 16 Мгц/(16*13) ≈ 77 кГц.

Установкой 6 бита регистра ADCSRA в состояние HIGH,  запускается непрерывная выборка.

Результат аналого-цифрового преобразования считывается в функцию обработки прерывания ISR (ADC_vect). Поскольку, результат имеет длину 10 бит, то он делится на два регистра ADCL и ADCH, размером в один байт каждый. Для корректного чтения значения сначала нужно считать значение регистра ADCL, а затем — регистра ADCH.

Пример скетча, в котором результат, полученный из АЦП копируется в целочисленную переменную analogValue:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

int analogValue = 0; // значение аналогового сигнала

void setup()

{

DDRB = B01000000; // pin 12 в режиме OUTPUT

DIDR0 = 0x3F; // отключаем цифровые входы

ADMUX = 0x43; // измеряем на ADC3, используем внутреннее опорное напр.= 1.1В

ADCSRA = 0xAC; // включаем АЦП, разрешаем прерывания, делитель = 16

ADCSRB = 0x40; // включаем АЦ коналы MUX, режим скользящей выборки

bitWrite(ADCSRA, 6, 1); // Запускаем преобразование установкой бита 6 (=ADSC) в ADCSRA

sei(); // устанавливаем флаг прерывания

}

void loop()

{

}

/*** Процедура обработки прерывания АЦП ***/

ISR(ADC_vect)

{

PORTB = B00000000; // пин 12 переводим в состояние LOW

analogValue = ADCL; // сохраняем младший байт результата АЦП

analogValue += ADCH

Источник: http://robotosha.ru/arduino/analog-measurements-arduino.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}