Sv1ca-4.ru

Строй журнал
15 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Розетка с таймером arduino

Программируемый цифровой коммутирующий таймер

В этой статье мы рассмотрим создание таймера обратного отсчета на основе платы Arduino. Для получения информации о текущем времени в данном проекте мы не будем использовать модуль часов реального времени (Real Time Clock, RTC). Длительность временного промежутка для счета будет задаваться с помощью клавиатуры 4х4 и ЖК дисплея 16×2. Когда таймер будет досчитывать до нуля будет издаваться звуковой сигнал с помощью зуммера.

Шаг 1: Материалы

  • Arduino Uno
  • Модуль RTC 1307
  • Дисплей 16X2
  • Модуль реле 5V
  • Подстроечный потенциометр 10K
  • Резистор 1K
  • Резисторы 10K x 4 штуки
  • Кнопки x 4 штуки
  • Макетная плата, джамперы.

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

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

Шаг третий. Датчик приближения

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

Подключу датчик напрямую к плате, как делал это в предыдущем проекте. Отличие одно: 4 контакт уже занят светодиодом, поэтому подключу сигнальную линию к 7 контакту.

Изменится и код.

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

БИБЛИОТЕКА GYVERTIMER

GyverTimer v3.2

GTimer – полноценный таймер на базе системных millis() / micros(), обеспечивающий удобную мультизадачность и работу с временем, используя всего одно родное прерывание таймера (Timer 0)

  • Миллисекундный и микросекундный таймер
  • Два режима работы:
  • Режим интервала: таймер “срабатывает” каждый заданный интервал времени
  • Режим таймаута: таймер “срабатывает” один раз по истечении времени (до следующего перезапуска)
  • Служебные функции:
  • Старт
  • Стоп
  • Сброс
  • Продолжить

    Поддерживаемые платформы: все Arduino (используются стандартные Wiring-функции)

    Программирование таймеров в плате Arduino UNO

    В этом проекте мы будем использовать прерывание переполнения таймера (Timer Overflow Interrupt) и использовать его для включения и выключения светодиода на определенные интервалы времени при помощи установки заранее определяемого значения (preloader value) регистра TCNT1 с помощью кнопок. Полный код программы будет приведен в конце статьи, здесь же рассмотрим его основные части.

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

    Анод светодиода подключен к контакту 7 платы Arduino, поэтому определим (инициализируем) его как ledPin.

    #define ledPin 7

    Затем сообщим плате Arduino к каким ее контактам подключен ЖК дисплей.

    Установим заранее определенное значение (preloader value) равное 3035 – это будет соответствовать интервалу времени в 4 секунды. Формула для расчета этого значения приведена выше в статье.

    float value = 3035;

    Затем в функции void setup() установим режим работы ЖК дисплея 16х2 и высветим приветственное сообщение на нем на несколько секунд.

    Читать еще:  Когда надо маркировать розетки

    lcd.begin(16,2);
    lcd.setCursor(0,0);
    lcd.print(«ARDUINO TIMERS»);
    delay(2000);
    lcd.clear();

    Затем контакт, к которому подключен светодиод, установим в режим вывода данных, а контакты, к которым подключены кнопки – в режим ввода данных.

    pinMode(ledPin, OUTPUT);
    pinMode(2,INPUT);
    pinMode(4,INPUT);

    После этого отключим все прерывания.

    Далее инициализируем Timer1.

    TCCR1A = 0;
    TCCR1B = 0;

    Загрузим заранее определенное значение (3035) в TCNT1.

    Затем установим коэффициент деления предделителя равный 1024 при помощи конфигурирования битов CS в регистре TCCR1B.

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

    Теперь разрешим все прерывания.

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

    ISR(TIMER1_OVF_vect)
    <
    TCNT1 = value;
    digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
    >

    В функции void loop() предварительно загружаемое значение увеличивается и уменьшается на 10 (инкрементируется и декрементируется) при помощи кнопок в схеме. Также это значение отображается на экране ЖК дисплея 16х2.

    if(digitalRead(2) == HIGH)
    <
    value = value+10; //увеличиваем preload value
    >
    if(digitalRead(4)== HIGH)
    <
    value = value-10; //уменьшаем preload value
    >
    lcd.setCursor(0,0);
    lcd.print(value);
    >

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

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

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

    Прерывания и их источники

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

    Проще говоря, прерывания – это набор приоритетов для тех или иных процессов, исполняемых контроллером.

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

    Источником сигнала прерывания может стать таймер Arduino или процесс изменения состояния одного из контактов (пинов). Еще одним источником может стать какой-либо вход внешних прерываний: нужный сигнал появится при изменении его состояния.

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

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

    Особенности прерывания по таймеру

    Как же управлять временем и запускать процессы в нужном вам порядке? При работе с микросхемой Arduino для этого можно использовать millis(), ее эффективность зависит от постоянного обращения к ней. Тогда, в случае вызова этой функции, можно будет понять – наступило время определенной операции или нет.

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

    Читать еще:  Как запитать автомагнитолу от розетки

    Микроконтроллер Arduino Uno укомплектован тремя таймерами: из них timer0 предназначен для генерации прерываний с интервалом в одну миллисекунду. При этом будет постоянно обновляться счетчик, передающий информацию функции millis(). Вести точный подсчет таймеру позволяет определенная частота, получаемая из 16 МГц процессора.

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

    Функция timer0 оперирует тактовым делителем на 64 и изменять это значение не стоит. Оно позволяет получить частоту прерывания, близкую к 1 кГц, оптимальную для целей большинства схемотехников. Если попытаться изменить данный параметр, то можно нарушить работу функции millis().

    Регистры сравнения и их роль в генерации прерывания

    Регистры сравнения выполняют функцию анализа хранимых данных с текущим состоянием счетчика прерывания. Например, регистр сравнения (OCR0A) эффективно применяется для прерывания в середине счета.

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

    Для оптимизации работы кода и микроконтроллера следует полностью отказаться от loop(). Для этого необходимо определение по вектору обработчика прерывания с помощью функции TIMER0_COMPA_vect. Благодаря ей обработчик и будет выполнять все те операции, что раньше делались в loop().

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

    Какие внешние воздействия вызывают прерывание

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

    Микроконтроллер Arduino может иметь несколько пинов, способных обрабатывать внешние прерывания. Так, на плате Arduino Uno их два, а на Arduino Mega 2560 – 6. Продемонстрировать их функционал можно с помощью кнопки сброса сервопривода. Для этого при написании кода в класс Sweeper необходимо добавит функцию reset(). Она способна установить нулевое положение и перетаскивать в нее сервопривод.

    Соединить обработчик с внешним прерыванием поможет другая функция – attachInterrupt(). На приведенных в качестве примеров микроконтроллерах Interrupt0 реализована на втором контакте. Она сообщает микроконтроллеру о том, что на данном входе ожидается спад сигнала.

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

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

    Полный код программы с таймерами и внешними прерываниями:

    Библиотеки прерываний

    У схемотехников, благодаря Всемирной паутине есть доступ к широкому кругу библиотек, которые существенно облегчат работу с таймерами. Большинство из них предназначены для тех, кто применяет функцию millis(), но есть и такие, которые позволяют произвести желаемую настройку таймеров и сгенерировать прерывания. Оптимальным вариантом для этого являются библиотеки TimerThree и TimerOne, разработанные Paul Stoffregan.

    Благодаря им, схемотехники получают широкий выбор возможностей, с помощью которых можно сконфигурировать прерывания с помощью таймера. Первая из этих библиотек не работает с Adruino Uno, но прекрасно зарекомендовала себя с платами Teensy, микроконтроллерами Adruino Mega2560 и Adruino Leonardo.

    Читать еще:  774424 акустическая розетка двойная

    Недостатком Adruino Uno является наличие всего двух ходов, предназначенных для работы с внешними прерываниями. Если требуется большее количество подобных пинов, то отчаиваться не стоит, ведь этот микроконтроллер поддерживает pin-change – прерывания по изменению входа и работает это на всех восьми входах.

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

    Наиболее информативное и практичной библиотекой для прерываний по изменению входа является PinChangeInt.

    Прерывания: основные правила работы

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

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

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

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

    Не стоит использовать длительную обработку в loop(), лучше разработать код для обработчика прерывания с установкой переменной volatile. Она подскажет программе, что дальнейшая обработка не нужна.

    Если вызов функции Update() все же необходим, то предварительно необходимо будет проверить переменную состояния. Это позволит выяснить, необходима ли последующая обработка.

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

    Какими функциями оперирует тот или иной таймер?

    Для микроконтроллера Arduino Uno у каждого из трех таймеров свои операции.

    Так Timer0 отвечает за ШИМ на пятом и шестом пине, функции millis(), micros(), delay().

    Другой таймер – Timer1, используется с ШИМ на девятом и десятом пине, с библиотеками WaveHC и Servo.

    Timer2 работает с ШИМ на 11 и 13 пинах, а также с Tone.

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

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

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

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

    0 0 голоса
    Рейтинг статьи
  • Ссылка на основную публикацию
    ВсеИнструменты