Site Loader

Содержание

Real Time Clock (RTC)/Часы реального времени

Статья проплачена кошками — всемирно известными производителями котят.

Если статья вам понравилась, то можете поддержать проект.

Модуль DS1307
Библиотека RTClib

Иногда требуется отслеживать определённое время наступления события. Модуль часов реального времени с литиевой батарей позволяет хранить текущую дату, независимо от наличия питания на самом устройстве. Наиболее распространённые модули RTC: DS1302 (совсем не точные), DS1307 (не очень точные), DS3231 (точные), DS3232 (точные) и др.

Модуль часов представляет собой небольшую плату, которая содержит микросхему (DS1307, DS1302, DS3231), а также сам механизм установки батарейки питания. Часы ведут отсчёт в удобных для человека единицах – минуты, часы, дни недели и другие, в отличие от обычных счётчиков и тактовых генераторов, которые считывают «тики». В Arduino имеется функция millis(), которая умеет считывать различные временные интервалы, но основным недостатком функции является сбрасывание в ноль при включении таймера. С её помощью можно считать только время, а установить дату или день недели невозможно. Модули часов реального времени позволяют решить эту задачу.

Электронная схема модуля включает в себя микросхему, источник питания, кварцевый резонатор и резисторы. Кварцевый резонатор работает на частоте 32768 Гц, которая является удобной для обычного двоичного счетчика. В схеме DS3231 имеется встроенный кварц и термостабилизация, которые позволяют получить значения высокой точности.

Как правило, все модули работают по протоколу I2C.

Модуль DS1307

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

Модуль DS1307 собран на основе микросхемы DS1307ZN, питание поступает от литиевой батарейки для реализации автономной работы в течение длительного промежутка времени. Батарея на плате крепится на обратной стороне. На модуле имеется микросхема AT24C32 – это энергонезависимая память EEPROM на 32 Кбайт. Обе микросхемы связаны между собой шиной I2C. DS1307 обладает низким энергопотреблением и содержит часы и календарь по 2100 год.

Технические характеристики

  • Питание – 5В
  • Диапазон рабочих температур от -40°С до 85°С
  • 56 байт памяти
  • Литиевая батарейка LIR2032
  • 12-ти и 24-х часовые режимы
  • Поддержка интерфейса I2C

Взаимодействие с другими устройствами и обмен с ними информацией производится с помощью интерфейса I2C с контактов SCL и SDA. В схеме установлены резисторы, которые позволяют обеспечивать необходимый уровень сигнала. Также на плате имеется специальное место для крепления датчика температуры DS18B20.Контакты распределены в 2 группы, шаг 2,54 мм.

В первой группе контактов находятся следующие выводы:

  • DS – вывод для датчика DS18B20
  • SCL – линия тактирования
  • SDA – линия данных
  • VCC – 5В
  • GND — земля

Во второй группе контактов находятся:

  • SQ – 1 МГц
  • DS
  • SCL
  • SDA
  • VCC
  • GND
  • BAT – вход для литиевой батареи

Чтобы подключить модуль к Arduino Uno, используются 4 вывода.


DS1307 | Arduino 
-----------------
   GND | GND 
   VCC | 5V 
   SCL | A5
   SDA | A4
    DS | N/A

Платы Leonardo, MEGA, ADK, DUE используют другие схемы. Ищите в интернете.

Библиотека RTClib

Для работы с модулем реального времени существует множество библиотек. Рассмотрим библиотеку от Adafruit RTClib.

Установите её через менеджер библиотек. После установки запустите один из готовых примеров из библиотеки ds1307. В Serial Monitor установите скорость 57600. Вы увидите дату на сегодняшний день.

При запуске скетча время берётся с компьютера, поэтому сначала убедитесь, что на вашем компьютере установлены правильные дата и время.

Получение даты и времени происходит через вызов функции now(), который возвращает объект DateTime. Данный объект позволяет узнать год, месяц, день, час, минуту и секунду.

Реклама

Таймер на Ардуино с настройкой включения и выключения

Всем привет! Собрав таймер на Ардуино из этой инструкции, вы сможете контролировать включение и выключение ваших устройств в нужное вам время. Это могут быть ночные фонари, система орошения сада и т.д. Мы воспользуемся Ардуино, дисплеем и RTC 1307, отображающим и управляющим временем. Вы можете задать часы «ВКЛ» и «ВЫКЛ» при помощи 4 кнопок, что позволит вам изменять настройки микросхемы таймера.

Также вы научитесь создавать часы, базирующиеся на Ардуино. Я приложил схему из fritzing и видео, так что вы без проблем соберёте данное устройство.

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

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

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

Шаг 2: Устанавливаем часы

Следуйте схеме из Fritzing.

Соедините 5V и GND с Ардуино с соответствующими контактами (Красный – 5V, синий – земля)

Дисплей к Ардуино:

  1. VSS к GND
  2. VDD к 5V
  3. VO к центру потенциометра
  4. RS к пину 2
  5. RW к GND
  6. EN или E к пину 3
  7. D0 NC
  8. D1 NC
  9. D2 NC
  10. D3 NC
  11. D4 к пину 4
  12. D5 к пину 5
  13. D6 к пину 6
  14. D7 к пину 7
  15. A к 5V
  16. K к GND через резистор 1K
  17. Остальные контакты потенциометра на 5V и GND

RTC к Arduino:

  • SDA к пину 4
  • SCL у пину 5
  • GND и 5V

Шаг 3: Устанавливаем время

Пришло время настроить часы. Запустите код «Set time RTC». Этот скетч возьмёт данные о дате и времени из вашего компьютера прямо во время компиляции кода и использует их для программирования RTC. Если у вас на компьютере неправильные установки, то поправьте их перед запуском программы. Затем нажмите кнопку Upload, чтобы немедленно загрузить откомпилированный код.

Внимание: Если вы скомпилируете код, а загрузите его позже, то данные о времени устареют.

Далее откройте окно Serial Monitor, чтобы увидеть, что время было установлено.

Файлы

Шаг 4: Часы

После того, как установите время, откройте и загрузите скетч «Clock with RTC LCD». Потенциометр в схеме нужен для настройки контрастности дисплея, покрутите его, чтобы чётко видеть символы.

Файлы

Шаг 5: Устанавливаем таймер

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

Пины 8,9, 10 и 11 соединены с GND через резисторы 10K. Когда вы нажмете на кнопку, то на контакты пойдёт напряжение 5V.

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

Шаг 6: Таймер

Откройте и загрузите код «Timer with on off set point». Нажимайте кнопки, чтобы сместить время назад или вперёд. Если электронный таймер будет в пределах настроенного интервала, то он начнет работать сразу же. Если же он не попадает в нужный интервал, то будет ждать час «ВКЛ».

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

Файлы

Весь код написан мной, кроме настройки времени на RTC и дата-логгера Adafruit. Надеюсь, эта инструкция как собрать простой таймер своими руками была для вас полезна!

Часы плоттер на ардуино или arduino-робот рисует маркером текущее время в режиме реального времени

Arduino-робот Plotclock рисует рисует последовательность цифр, отображающей текущее время  в 24-часовом формате .Собрать такого робота часовщика можно самому

на базе ардуино , 3х сервоприводов и конечно нужны будут детали напечатанные на 3д принтере . 

Немецкий дизайнер портала Thingiverse с ником Joo из Нюрнберга (также известен под именем Йоханес) разработал простого робота, который через определенные промежутки времени с помощью простого маркера отображает ход времени на миниатюрной классной доске. Элементы простого шарнирного механизма, в который установлен маркер, выполнены на 3D принтере. «Механические руки» робота стирают устаревшие значения прежде чем нарисовать снова, и каждый раз, когда робот завершает рисовать цифры, они соответствуют реальному времени 


 

Arduino-робот Plotclock рисует рисует последовательность цифр, отображающей текущее время  в 24-часовом формате

.

Основные характеристики:

  • Робот Plotclock, выполненный на платформе Arduino Uno, с помощью маркера в прямом смысле рисует на белой поверхности  последовательность цифр, отображающих текущее время  в 24-часовом формате;
     
  • Затем робот стирает с поверхности устаревшее значение, и рисует новые значения часов и минут;
     
  • Пластиковые элементы механической конструкции робота изготовлены на 3D принтере.

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


Для управления «механической рукой» робота Plotclock используются три серводвигателя и плата Arduino.

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

Код для ардуино можно взять на гитхабе https://github.com/9a/plotclock  

    Для сборки Plotclock пользователям потебуется:

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

#include <Servo.h>

class Flasher

{

// Переменные-участники класса устанавливаются при запуске

int ledPin; // Номер контакта со светодиодом

long OnTime; // длительность ВКЛ в мс

long OffTime; // длительность ВЫКЛ в мс

 

// Контроль текущего состояния

int ledState; // устанавливает текущее состояние светодиода

unsigned long previousMillis; // время последнего обновления состояния светодиода

 

// Конструктор — создает объект Flasher, инициализирует переменные-участники и состояние

public:

Flasher(int pin, long on, long off)

{

  ledPin = pin;

  pinMode(ledPin, OUTPUT);

 

  OnTime = on;

  OffTime = off;

 

  ledState = LOW;

  previousMillis = 0;

}

 

void Update(unsigned long currentMillis)

{

  if((ledState == HIGH) && (currentMillis — previousMillis >= OnTime))

  {

   ledState = LOW; // ВЫКЛ

   previousMillis = currentMillis; // Запомнить время

   digitalWrite(ledPin, ledState); // Обновить состояние светодиода

  }

  else if ((ledState == LOW) && (currentMillis — previousMillis >= OffTime))

  {

   ledState = HIGH; // ВКЛ

   previousMillis = currentMillis; // Запомнить время

   digitalWrite(ledPin, ledState); // Обновить состояние светодиода

  }

}

};

 

class Sweeper

{

Servo servo; // объект servo

int pos; // текущее положение сервопривода

int increment; // определяем увеличение перемещения на каждом интервале

int updateInterval; // определяем время между обновлениями

unsigned long lastUpdate; // определяем последнее обновление положения

 

public:

Sweeper(int interval)

{

  updateInterval = interval;

  increment = 1;

}

void Attach(int pin)

{

  servo.attach(pin);

}

void Detach()

{

  servo.detach();

}

void reset()

{

  pos = 0;

  servo.write(pos);

  increment = abs(increment);

}

 

void Update(unsigned long currentMillis)

{

  if((currentMillis — lastUpdate) > updateInterval) //время обновиться

  {

   lastUpdate = millis();

   pos += increment;

   servo.write(pos);

   if ((pos >= 180) || (pos <= 0)) // инициализируем конец вращения

   {

    // инициализируем обратное направление

    increment = -increment;

   }

  }

}

};

 

Flasher led1(11, 123, 400);

Flasher led2(12, 350, 350);

Flasher led3(13, 200, 222);

 

Sweeper sweeper1(25);

Sweeper sweeper2(35);

 

void setup()

{

sweeper1.Attach(9);

sweeper2.Attach(10);

 

// Timer0 уже используется millis() — прерываемся примерно посередине и вызываем ниже функцию «Compare A»

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

 

pinMode(2, INPUT_PULLUP);

attachInterrupt(0, Reset, FALLING);

}

 

void Reset()

{

sweeper1.reset();

sweeper2.reset();

}

 

// Прерывание вызывается один раз в миллисекунду, ищет любые новые данные, и если нашло, сохраняет их

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

 

// if(digitalRead(2) == HIGH)

{

  sweeper2.Update(currentMillis);

  led1.Update(currentMillis);

}

 

led2.Update(currentMillis);

led3.Update(currentMillis);

}

 

void loop()

{

}

DS3231 Настройка даты и времени. Управление энкодером.

Часы на модуле DS3231 с настройкой и установкой даты и времени с помощью энкодера. Есть вариант 12 или 24 часового режима работы, Вывод года даты и времени, а также температуры. Простое подключение, готовый скетч, минимум деталей, схема сборки.
Сегодня я покажу как ещё можно устанавливать и изменять дату и время на часах. Часы будут на модуле DS3231, так как я считаю, что это одни из самых доступных и точных модулей часов. А если честно, то других я и не знаю, если не считать DS1307.
DS1307 конечно дешевле, но по многим параметрам уступают DS3231.
Это уже моё пятое видео про часы за этот месяц. Надеюсь, что не очень утомил, но теперь долгое время я к часам не притронусь.

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

  • Ну во-первых, все регулировки будут с помощью одного энкодера, вместо кнопок.
  • Второе – это возможность выбора 12 часового или 24 режима. Для этого надо просто нажать и некоторое время удерживать кнопку на энкодере.
  • Название месяца и дня недели, я вывел на русском языке.
  • И здесь присутствует некоторая автоматика. Например если менять год, то день недели будет устанавливаться сам. Тоже самое будет если изменять дату.

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

Принцип работы с часами такой.
Для выбора объекта изменения надо нажимать кнопку на энкодере.
Узнать какой элемент сейчас активен и доступен к редактированию, можно по курсору снизу.
Как только вы выбрали нужный объект, то надо вращать ручку энкодера вправо или влево для уменьшения или увеличения значения.
Доступ  к редактированию ограничен по времен, и если вы не начали редактирование в течении 2 секунд, выделение сбросится и надо будет снова его выбирать.
Как я уже говорил, что для выбора 12 часового или 24 часового режима надо удерживать нажатой кнопку в течении пары секунд.
12 часовой режим обозначен АМ, а 24 часовой — МТ.
Год можно редактировать с 2000 по 2099год.
По окончании редактирования значение будет сохранено в память.

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

Сегодня нам понадобятся

  • Модуль часов DS3231
  • LCD дисплей 1602
  • Энкодер. Я применил в виде модуля KY-040
  • И любая плата Ардуино.

Как и во многих предыдущих видео я взял LCD дисплей 1602 в версии с I2C. Но как и все дешёвые экранчики, у него нет русской кодировки, и для того чтобы это изменить я использовал специальную библиотеку LCD_1602_RUS_ALL которая это изменит.
У меня есть очень хорошее видео про настройки про дисплеи и русификатор.
Как всегда все используемые библиотеки и сами скетчи можно скачать с моего сайта. Ссылка будет в описании.

Теперь давайте посмотрим схему подключения.
У модуля дисплея, и у модуля часов одинаковые выходы, так как они работаю по одной шине. Шине I2C. Поэтому и подключаем их одинаково. И выводы SDA и SCL подключаем к выводам A4 и A5 соответственно. Питание обоих модулей 5 вольт.
Контакты энкодера подключаем к выводам D2 – D4.

  • D2 – Clock.
  • D3 – Data.
  • D4– Switch.  Это кнопка.

В модуле контакты Clock и Data подтянуты к питанию резисторами 10 кОм. Если у вас просто экнкодер, то вам надо самим припаять два резистора.

При вращении ручки энкодера сигнал сначала появляется на выводе CLK,  а затем на  DT.
Так программа понимает в какую сторону крутится вал. Если сначала сигнал на DT, а затем CLK то движение против часовой стрелки. Как видите всё довольно просто.

Скетч, я сегодня не хочу рассматривать. Если есть желание, то сами посмотрите, а нет, то и так всё заработает. Всё равно этот момент 80% прокручивают.  

Если вам нравятся мои видео, то вы можете помочь в развитии канала став его спонсором. Все ваши вклады пойдут на закупки новых модулей. Вам же за это будут предоставлены дополнительные бонусы, и они довольно интересные.
Вы видите ссылки на видео, которые, я думаю будут вам интересны. Перейдя на любое из этих видео вы узнаете что-то новое, а ещё поможете мне. Ведь любой ваш просмотр — это знак YOUTUBE, что это кому-то интересно и что его надо показывать чаще.
Спасибо.
А пока на этом всё.

 

Как установить время в часы реального времени

В этой статье мы попросили мастера ответить на вопрос: «Как установить время в часы реального времени?», а также дать полезные рекомендации по теме. Что из этого получилось, читайте далее.

В этом уроке мы научимся не только выводить, но и устанавливать время RTC модуля при помощи трёх кнопок.

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

  • Библиотека iarduino_RTC (для подключения RTC часов реального времени DS1302, DS1307, DS3231)
  • Библиотека LiquidCrystal_I2C_V112 (для подключения дисплеев LCD1602 по шине I2C)

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki — Установка библиотек в Arduino IDE .

Подключение модулей RTC и LCD, данного урока, осуществляется к аппаратным выводам SDA, и SCL.

подключение кнопок: кнопка «SET» к выводу 2, кнопка «UP» к выводу 3 и копка «DOWN» к выводу 4.

При подключении библиотеки «iarduino_RTC» нужно указать, с каким модулем ей работать, в данном случае это модуль Trema на базе чипа DS1307:

Аналогичный алгоритм действий при подключении библиотеки «LiquidCrystal_I2C» для работы с LCD дисплеем LCD1602 IIC/I2C(синий) или LCD1602 IIC/I2C(зелёный) :

Осталось подключить 3 кнопки: «SET», «UP» и «DOWN» . Для этого им нужно назначить номера выводов и указать, что эти выводы работают как вход:

В библиотеке «iarduino_RTC», для работы с датой и временем реализованы две функции: settime() — установка и gettime() — получение времени.

В библиотеке «iarduino_RTC» доступны 9 числовых переменных: seconds, minutes, hours, Hours, midday, day, weekday, month и year, значения которых обновляются после каждого вызова функции gettime(). Эти переменные мы будим использовать для изменения даты и времени.

Еще одна функция библиотеки «iarduino_RTC», которая нам понадобится, это blinktime(), она заставляет функцию gettime(), мигать одним из параметров времени (0 — не мигать, 1 — мигать секундами, 2 — мигать минутами, 3 — мигать часами, 4 — мигать днями и т.д.).

И последнее, о чем надо позаботиться перед созданием кода программы — это алгоритм работы кнопок и определение переменных

  • В режиме вывода даты или времени (обычный режим):
    • Кратковременное нажатие на кнопку SET переключает вывод даты и вывод времени
    • Удержание кнопки SET переводит часы в режим установки даты или времени (зависит от того, что было на дисплее, дата или время)
    • Кнопки UP и DOWN неактивны.
  • В режиме установки даты или времени:
    • Кратковременное нажатие на кнопку SET — переход между устанавливаемыми параметрами (сек, мин, час, дни, мес, год, д.н.)
    • Удержание кнопки SET выводит часы из режима установки
    • Каждое нажатие на кнопку UP увеличивает значение устанавливаемого параметра даты или времени
    • Каждое нажатие на кнопку DOWN уменьшает значение устанавливаемого параметра даты или времени

Исходя из алгоритма, нам понадобятся две переменные, назовем их: VAR_mode_SHOW и VAR_mode_SET . Первая будет указывать режим вывода (1-выводим_время, 2-выводим_дату). Вторая, будет указывать режим установки времени (0-нет, 1-сек, 2-мин, 3-час, 4-день, 5-мес, 6-год, 7-д.н.).

Компьютеры IBM AT и PS/2 оснащены часами реального времени. Эти часы питаются от аккумулятора, поэтому их показания не пропадают при выключении компьютера.

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

Использование регистров КМОП-памяти часами реального времени приведено в таблице:

Часы реального времени вырабатывают аппаратное прерывание IRQ8, которому соответствует прерывание с номером 70h. Это прерывание может вырабатываться по трем причинам:

  • Прерывание по окончанию изменения данных. Вырабатывается при установленном в 1 бите 4 регистра состояния B после каждого обновления регистров часов.
  • Прерывание будильника вырабатывается при совпадении регистров часов и регистров будильника и при установленном в 1 бите 5 регистра состояний B.
  • Периодическое прерывание вырабатывается с интервалом примерно 1 миллисекунда при установленном в 1 бите 6 регистра состояний B.

При срабатывании будильника BIOS вырабатывает прерывание INT 4Ah. Программа может подготовить собственный обработчик для этого прерывания.

Для работы с часами реального времени вы можете обращаться непосредственно к перечисленным выше ячейкам КМОП-памяти, используя порты 70h и 71h. Однако лучше всего воспользоваться функциями 2 — 7 прерывания 1Ah, описанными ниже.

Эта функция позволяет установить будильник на заданное время. Когда будильник «зазвенит», будет вызвано прерывание INT 4Ah (это прерывание вызывают модули BIOS после прихода аппаратного прерывания от часов реального времени IRQ8, т.е. прерывания с номером 70h). Программа, использующая функцию будильника, должна подготовить обработчик прерывания INT 4Ah, завершающий свою работу выполнением команды IRET.

Программа может установить только один будильник.

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

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

Так как установленное время срабатывания будильника хранится в КМОП-памяти, питающейся от аккумулятора, будильник не будет сброшен при случайном выключении компьютера.

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

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

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

Перед установкой будильника программа подключает свой обработчик прерывания 4Ah. Это прерывание вызывается при срабатывании будильника. Перед завершением работы программа сбрасывает будильник и восстанавливает вектор прерывания 4Ah.

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

  • компьютер с установленной Arduino IDE;
  • плата Arduino;
  • микросхема DS1307 или модуль RTC на ее основе;
  • перемычки;
  • макетная плата;
  • комплектующие из списка элементов.

Вы можете заменить плату Arduino на контроллер Atmel, но убедитесь, что у него достаточно входных и выходных выводов и есть аппаратная реализация интерфейса I2C. Я использую ATMega168A-PU. Если вы будете использовать отдельный микроконтроллер, то вам понадобится программатор, например, AVR MKII ISP.

Предполагается, что читатель знаком с макетированием, программированием в Arduino IDE и имеет некоторые знания языка программирования C. Обе программы, приведенные ниже, не нуждаются в дополнительном разъяснении.

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

Вот здесь и будет удобно использование микросхемы RTC (Real Time Clock, часов реального времени). Эта микросхема с батарейкой 3В или каким-либо другим источником питания следит за временем и датой. Часы/календарь обеспечивают информацию о секундах, минутах, часах, дне недели, дате, месяце и годе. Микросхема корректно работает с месяцами продолжительностью 30/31 день и с високосными годами. Связь осуществляется через шину I2C (шина I2C в данной статье не обсуждается).

Если напряжение на главной шине питания Vcc падает ниже напряжения на батарее Vbat, RTC автоматически переключается в режим низкого энергопотребления от резервной батареи. Резервная батарея – это обычно миниатюрная батарея (в виде «монетки», «таблетки») напряжением 3 вольта, подключенная между выводом 3 и корпусом. Таким образом, микросхема по-прежнему будет следить за временем и датой, и когда на основную схему будет подано питание, микроконтроллер получит текущие время и дату.

В этом проекте мы будем использовать DS1307. У этой микросхемы вывод 7 является выводом SQW/OUT (выходом прямоугольных импульсов). Вы можете использовать этот вывод для мигания светодиодом и оповещения микроконтроллера о необходимости фиксации времени. Мы будем делать и то, и другое. Ниже приведено объяснение работы с выводом SQW/OUT.

Для управления работой вывода SQW/OUT используется регистр управления DS1307.

Возможно у Вас есть свои мнения на тему «Как установить время в часы реального времени»? Напишите об этом в комментариях.

Arduino задержка без delay — Вместе мастерим

Задержки в Ардуино играют очень большую роль. Без них не сможет работать даже самый простой пример Blink, который моргает светодиодом через заданный промежуток времени. Но большинство начинающих программистов мало знают о временных задержках и используют только Arduino delay, не зная побочных эффектов этой команды. В этой статье я подробно расскажу о временных функциях и особенностях их использования в среде разработки Arduino IDE.

Функции времени в Ардуино

В Arduino cуществует несколько различных команд, которые отвечают за работу со временем и паузы:

Они отличаются по точности и имеют свои особенности, которые стоит учитывать при написании кода.

Использование функции arduino delay

Синтаксис

Ардуино delay является самой простой командой и её чаще всего используют новички. По сути она является задержкой, которая приостанавливает работу программы, на указанное в скобках число миллисекунд. (В одной секунде 1000 миллисекунд.) Максимальное значение может быть 4294967295 мс, что примерно ровняется 50 суткам. Давайте рассмотрим простой пример, наглядно показывающий работу этой команды.

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

Пример delay с миганием светодиодом

Пример схемы для иллюстрации работы функции delay.
Можно построить схему со светодиодом и резистором. Тогда у нас получится стандартный пример – мигание светодиодом. Для этого на пин, который мы обозначили как выходной, необходимо подключить светодиод плюсовым контактом. Свободную ногу светодиода через резистор приблизительно на 220 Ом (можно немного больше) подключаем на землю. Определить полярность можно, если посмотреть на его внутренности. Большая чашечка внутри соединена с минусом, а маленькая ножка с плюсом. Если ваш светодиод новый, то определить полярность можно по длине выводов: длинная ножка – плюс, короткая – минус.

Функция delayMicroseconds

Данная функция является полным аналогом delay за исключением того, что единицы измерения у нее не миллисекунды, а микросекунды (в 1 секунде – 1000000 микросекунд). Максимальное значение будет 16383, что равно 16 миллисекундам. Разрешение равно 4, то есть число будет всегда кратно четырем. Кусочек примера будет выглядеть следующим образом:

Проблема с delayMicroseconds точно такая же, как у delay – эти функции полностью «вешают» программу и она на некоторое время буквально замирает. В это время невозможна работа с портами, считывание информации с датчиков и произведение математических операций. Для мигалок данный вариант подходит, но опытные пользователи не используют её для больших проектов, так как там не нужны такие сбои. Поэтому, гораздо лучше использовать функции, описанные ниже.

Функция millis вместо delay

Функция millis() позволит выполнить задержку без delay на ардуино, тем самым обойти недостатки предыдущих способов. Максимальное значение параметра millis такое же, как и у функции delay (4294967295мс или 50 суток). При переполнении значение просто сбрасывается в 0, не забывайте об этом.

С помощью millis мы не останавливаем выполнение всего скетча, а просто указываем, сколько времени ардуино должна просто “обходить” именно тот блок кода, который мы хотим приостановить. В отличие от delay millis сама по себе ничего не останавливает. Данная команда просто возвращает нам от встроенного таймера микроконтроллера количество миллисекунд, прошедших с момента запуска. При каждом вызове loop Мы сами измеряем время, прошедшее с последнего вызова нашего кода и если разница времени меньше желаемой паузы, то игнорируем код. Как только разница станет больше нужной паузы, мы выполняем код, получаем текущее время с помощью той же millis и запоминаем его – это время будет новой точкой отсчета. В следующем цикле отсчет уже будет от новой точки и мы опять будем игнорировать код, пока новая разница millis и нашего сохраненного прежде значения не достигнет вновь желаемой паузы.

Вот пример, наглядно иллюстрирующий работу команды:

Сначала мы вводим переменную timing, в ней будет храниться количество миллисекунд. По умолчанию значение переменной равно 0. В основной части программы проверяем условие: если количество миллисекунд с запуска микроконтроллера минус число, записанное в переменную timing больше, чем 10000, то выполняется действие по выводу сообщения в монитор порта и в переменную записывается текущее значение времени. В результате работы программы каждые 10 секунд в монитор порта будет выводиться надпись 10 seconds. Данный способ позволяет моргать светодиодом без delay.

Функция micros вместо delay

Данная функция так же может выполнить задержку, не используя команду delay. Она работает точно так же, как и millis, но считает не миллисекунды, а микросекунды с разрешением в 4мкс. Её максимальное значение 4294967295 микросекунд или 70 минут. При переполнении значение просто сбрасывается в 0, не забывайте об этом.

Резюме

Платформа Arduino предоставляет нам несколько способов выполнения задержки в своем проекте. С помощью delay вы можете быстро поставить на паузу выполнение скетча, но при этом заблокируете работу микроконтроллера. Использование команды millis позволяет обойтись в ардуино без delay, но для этого потребуется чуть больше программировать. Выбирайте лучший способ в зависимости от сложности вашего проекта. Как правило, в простых скетчах и при задержке меньше 10 секунд используют delay. Если логика работы сложнее и требуется большая задержка, то вместо delay лучше использовать millis.

Задержки в Ардуино играют очень большую роль. Без них не сможет работать даже самый простой пример Blink, который моргает светодиодом через заданный промежуток времени. Но большинство начинающих программистов мало знают о временных задержках и используют только Arduino delay, не зная побочных эффектов этой команды. В этой статье я подробно расскажу о временных функциях и особенностях их использования в среде разработки Arduino IDE.

Функции времени в Ардуино

В Arduino cуществует несколько различных команд, которые отвечают за работу со временем и паузы:

Они отличаются по точности и имеют свои особенности, которые стоит учитывать при написании кода.

Использование функции arduino delay

Синтаксис

Ардуино delay является самой простой командой и её чаще всего используют новички. По сути она является задержкой, которая приостанавливает работу программы, на указанное в скобках число миллисекунд. (В одной секунде 1000 миллисекунд.) Максимальное значение может быть 4294967295 мс, что примерно ровняется 50 суткам. Давайте рассмотрим простой пример, наглядно показывающий работу этой команды.

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

Пример delay с миганием светодиодом

Пример схемы для иллюстрации работы функции delay.
Можно построить схему со светодиодом и резистором. Тогда у нас получится стандартный пример – мигание светодиодом. Для этого на пин, который мы обозначили как выходной, необходимо подключить светодиод плюсовым контактом. Свободную ногу светодиода через резистор приблизительно на 220 Ом (можно немного больше) подключаем на землю. Определить полярность можно, если посмотреть на его внутренности. Большая чашечка внутри соединена с минусом, а маленькая ножка с плюсом. Если ваш светодиод новый, то определить полярность можно по длине выводов: длинная ножка – плюс, короткая – минус.

Функция delayMicroseconds

Данная функция является полным аналогом delay за исключением того, что единицы измерения у нее не миллисекунды, а микросекунды (в 1 секунде – 1000000 микросекунд). Максимальное значение будет 16383, что равно 16 миллисекундам. Разрешение равно 4, то есть число будет всегда кратно четырем. Кусочек примера будет выглядеть следующим образом:

Проблема с delayMicroseconds точно такая же, как у delay – эти функции полностью «вешают» программу и она на некоторое время буквально замирает. В это время невозможна работа с портами, считывание информации с датчиков и произведение математических операций. Для мигалок данный вариант подходит, но опытные пользователи не используют её для больших проектов, так как там не нужны такие сбои. Поэтому, гораздо лучше использовать функции, описанные ниже.

Функция millis вместо delay

Функция millis() позволит выполнить задержку без delay на ардуино, тем самым обойти недостатки предыдущих способов. Максимальное значение параметра millis такое же, как и у функции delay (4294967295мс или 50 суток). При переполнении значение просто сбрасывается в 0, не забывайте об этом.

С помощью millis мы не останавливаем выполнение всего скетча, а просто указываем, сколько времени ардуино должна просто “обходить” именно тот блок кода, который мы хотим приостановить. В отличие от delay millis сама по себе ничего не останавливает. Данная команда просто возвращает нам от встроенного таймера микроконтроллера количество миллисекунд, прошедших с момента запуска. При каждом вызове loop Мы сами измеряем время, прошедшее с последнего вызова нашего кода и если разница времени меньше желаемой паузы, то игнорируем код. Как только разница станет больше нужной паузы, мы выполняем код, получаем текущее время с помощью той же millis и запоминаем его – это время будет новой точкой отсчета. В следующем цикле отсчет уже будет от новой точки и мы опять будем игнорировать код, пока новая разница millis и нашего сохраненного прежде значения не достигнет вновь желаемой паузы.

Вот пример, наглядно иллюстрирующий работу команды:

Сначала мы вводим переменную timing, в ней будет храниться количество миллисекунд. По умолчанию значение переменной равно 0. В основной части программы проверяем условие: если количество миллисекунд с запуска микроконтроллера минус число, записанное в переменную timing больше, чем 10000, то выполняется действие по выводу сообщения в монитор порта и в переменную записывается текущее значение времени. В результате работы программы каждые 10 секунд в монитор порта будет выводиться надпись 10 seconds. Данный способ позволяет моргать светодиодом без delay.

Функция micros вместо delay

Данная функция так же может выполнить задержку, не используя команду delay. Она работает точно так же, как и millis, но считает не миллисекунды, а микросекунды с разрешением в 4мкс. Её максимальное значение 4294967295 микросекунд или 70 минут. При переполнении значение просто сбрасывается в 0, не забывайте об этом.

Резюме

Платформа Arduino предоставляет нам несколько способов выполнения задержки в своем проекте. С помощью delay вы можете быстро поставить на паузу выполнение скетча, но при этом заблокируете работу микроконтроллера. Использование команды millis позволяет обойтись в ардуино без delay, но для этого потребуется чуть больше программировать. Выбирайте лучший способ в зависимости от сложности вашего проекта. Как правило, в простых скетчах и при задержке меньше 10 секунд используют delay. Если логика работы сложнее и требуется большая задержка, то вместо delay лучше использовать millis.

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

Мы рисовали общую схему нашего устройства, но сейчас посмотрим на элементы, с которыми мы будем работать в данном уроке. Собственно — их 5. — это зуммер, реле с 2 типами контактов, светодиод, показывающий состояние прохода и кнопка мгновенного действия. Подготовим для всех них понятные имена

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

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

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

К счастью, в ардуино уже есть для этого инструменты. Попытаюсь дать короткое объяснение, почему delay это плохо. Для этого отвлечёмся и представим абстрактную задачу, где один светодиод у нас моргает каждую 1 секунду, а другой, каждые 0,2 секунды. Возьмём обычный пример мигания через delay

Естественно, в данном примере, они мигают по очереди, потому-что пока выполняется delay, контроллер делает бесполезные операции в цикле. Можно конечно сделать мигание второго диода в прерывании, но опять же, использовать там delay не получится, чтобы выдержать 200мс.

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

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

Как ещё можно реализовать задержку, чтобы в это время, можно было делать другой код? Самое лучшее решение — запустить условие проверки с некой переменной, которая постоянно увеличивает значение. В ардуино уже реализована такая переменная millis() , которая увеличивается каждую миллисекунду на 1. Её максимальное значение равно 4294967295мс, что приблизительно составляет почти 50 суток. Пока не будем думать, о том, что она может переполнится (в этом ничего страшного нет), и посмотрим, как мы можем использовать эту переменную

Всё просто! Мы используем вспомогательную переменную текущего времени currentTime, На старте её значение равно = 0, как и millis() = 0. Но millis() у нас постоянно увеличивается, а currentTime — нет. Поэтому через 1000мс, сработает условие if (millis() — currentTime > 1000), т.е. мы создали задержку в 1с, но код при этом выполнялся циклично в loop, и мы могли успеть обработать много периферии. Потом мы просто обновляем нашу переменную currentTime, и она снова ждёт сравнения с millis(), когда она вырастет на 1000мс. Попробуем сделать вышестоящую задачу, мигание двумя светодиодами с разной задержкой. но при этом вставим в loop какой нибудь код, пусть будет отправка в терминал, и проверим, как это работает. Я сделал для наглядности вторую переменную currentTime2, для второго светодиода.

Для состояний светодиодов, возьмём переменную bool ledState и ledState2. Мы задали её тип как boolean, а это значит что она может принимать два значения — true и false, что в принципе равно 0 и 1. Чтобы не писать по несколько раз HIGH, LOW, мы подставляем туда состояние светодиода ledState. А меняем его каждый раз логическим отрицанием (!) на противоположное значение.

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

Смотрим, что получилось

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

Время счета с Arduino (без RTC) · Один транзистор

Простой код для часов Arduino без модуля RTC. Подсчитайте время и дату с помощью простой функции.

Когда дело доходит до подсчета времени с использованием Arduino или другой платформы MCU, настоятельно рекомендуется использовать схему RTC (часы реального времени). Эти устройства дешевы, обладают хорошей точностью и продолжают отсчитывать время, даже когда основной MCU отключен. Они работают от маленькой батарейки и потребляют слабый ток. Существует довольно много библиотек Arduino, которые имеют дело со временем и упрощают взаимодействие с источником времени.Одна из них — библиотека Time Пола Стоффрегена. Это хорошо написанная библиотека с внутренним временем, основанным на стандартном времени Unix time_t (количество секунд, прошедших с 1 января 1970 года).

Но хотелось чего-то более простого. Я написал функцию из 50 строк кода, которая увеличивает переменную в секундах при каждом ее вызове. Когда секунды переполняются (достигают 60), он увеличивает переменную минут и сбрасывает секунды. И так далее. Только когда переменная времени изменяется, она печатается на устройстве вывода (в данном случае ЖК-дисплей 16×2).Вокруг этой функции я добавил код, который превращает Arduino в обычные часы. В качестве прототипа использовались ЖК-экран и экран клавиатуры, установленные на плате, совместимой с Arduino Uno. Код должен компилироваться на любой другой плате разработки, потому что он не использует определенные функции или библиотеки. Вам нужно будет настроить конфигурацию выводов ЖК-дисплея и кнопки клавиатуры (требуется изменение при использовании кнопок, подключенных к выводам цифрового входа, вместо аналоговой клавиатуры).

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

 байт чч, мм, сс;
байт dd, MM, YY;
byte wd;

byte daysOfMonth [12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const char * months [12] = {«Янв», «Фев», «Мар», «Апр», «Май», «Июнь», «Июль», «Авг», «Сен», «Октябрь», « Ноя "," дек "};
const char * wdays [7] = {«Пн», «Вт», «Ср», «Чт», «Пт», «Сб», «Вс»};
 

У меня также есть функции, отображающие каждую из этих переменных в определенных местах на ЖК-экране. Перейдем к функции счета времени, которую я подробно объясню.При каждом вызове этой функции увеличиваются секунды сс .

 void countTime () {
 // считать секунды
 ss ++;
 if (ss <60) {
 dispSec ();
 возвращение;
 }
 сс = 0;
 dispSec ();

 // считать минуты
 мм ++;
 if (мм <60) {
 dispMin ();
 возвращение;
 }
 мм = 0;
 dispMin ();

 // подсчитываем часы
 чч ++;
 if (hh <24) {
 dispHour ();
 возвращение;
 }
 чч = 0;
 dispHour ();

 dd ++; wd ++;
 если (wd == 7) wd = 0;
 if (dd 

Первые строки кода функции увеличивают секунды.Пока они не достигают 60, функция обновляет отображение и возвращается. Когда секунды достигают 60, их значение по умолчанию равно 0, и с этого момента функция больше не возвращается. Пора увеличивать минуты. Как и в случае с секундами, если минуты не достигли 60, функция отображает их и возвращается. Когда минуты достигают 60, они очищаются, и функция переходит на час. То же самое происходит с часами, если они меньше 24. Когда часы достигают 24, пора увеличивать не только день, но и переменную дня недели.Переменная дня недели отсчитывает от 0 до 6, а максимальное значение дней зависит от текущего месяца (взято из массива). Месяц увеличивается до 12, а затем увеличивается год. Год не имеет предела. Но на этом этапе мы должны позаботиться о високосных годах. Если год кратен четырем, в нем 366 дней. Из этого правила есть исключение: если год кратен 100, но не делится на 400, то это не високосный год и состоит из 365 дней. Нет необходимости иметь дело с делимостью 400, потому что мой код не готов к достижению 2400 года.К тому времени я, вероятно, выпущу новую версию 😉 Для любого високосного года количество дней в феврале должно быть скорректировано в массиве.

Это почти все, что нужно для правильной работы этой функции. Но есть кое-что, что необходимо принять во внимание: пользователь должен иметь возможность редактировать переменные времени и даты. Я придумал простой интерфейс с двумя кнопками, который является обычным для цифровых часов. Вы нажимаете одну кнопку для переключения между минутами, часами, днем, месяцем и годом, а другую кнопку - для увеличения выбранной переменной.Выбранная переменная мигает на ЖК-дисплее. Когда он переполняется, он должен вернуться к исходному значению (0 для часа и минуты, 1 для дня и месяца, 2000 для года).

Переполнение дня и увеличение месяца и года требует настройки дня недели. При переполнении дней день недели должен вернуться к значению, которое было в первый день текущего месяца. Если количество дней в месяце делится на 7, это произойдет. Но поскольку это не так, мы вычисляем остаток от ближайшего числа, кратного 7, к дням в текущем месяце и корректируем с ним текущий будний день (т.е. 35-31 = 4 для 31-дневного месяца).

, случай 3: дд = (дд + 1)% daysOfMonth [MM];
 вд = (ср + 1)% 7;
 если (dd == 0) wd = (wd + 35 - daysOfMonth [MM])% 7;
 

Код приращения месяца добавляет дни текущего месяца к переменной рабочих дней. После этого он может выполнять приращение. Переполнение месяцев требует того же подхода, что и переполнение дней. Мы вычисляем остаток от ближайшего кратного 7 к дням текущего года и добавляем его к дням недели (т.е. 371 - 365 = 6, для невисокосного года).

, случай 4: wd = (wd + daysOfMonth [MM])% 7;
 ММ = (ММ + 1)% 12;
 if (MM == 0) {
 вд = (ср + 6)% 7;
 если ((YY% 4) == 0) wd = (wd + 5)% 7;
 }
 

Увеличение на год проще. Мы корректируем дни недели с учетом количества дней в году. Но что происходит при переполнении? Чтобы упростить ситуацию, я выбрал переполнение в 56 лет. Почему 56? Что ж, с 2000 по 2055 год 14 високосных лет.Важно то, что общее количество дней между 1 января 2000 г. и 31 декабря 2055 г. делится на 7. Поэтому, если первый день приходится на субботу, последний должен быть в пятницу, а дни недели могут увеличиваться без корректировки.

 беззнаковых целых дней = 365;
 если ((ГГ% 4) == 0) дней = 366;
 если ((ГГ% 100) == 0) дней = 365;
 wd = (wd + days)% 7;
 ГГ = (ГГ + 1)% 56;
 

Полный скетч содержит около 300 строк кода и доступен на GitHub.Для моего следующего проекта часов я получил модуль RTC и добавил функцию будильника. Проверить это.

Учебное пособие по

arduino => Управление временем

Синтаксис

  • беззнаковый длинный миллис ()

  • беззнаковые длинные микросхемы ()

  • пустая задержка (беззнаковые длинные миллисекунды)

  • void delayMicroseconds (длинные микросекунды без знака)

  • См. Заголовок elapsedMillis для конструкторов и операторов этого класса.Вкратце:

    • elapsedMillis elapsedMillisObject; создает объект для отслеживания времени с момента его создания или с момента некоторого другого явно установленного момента времени
    • elapsedMillisObject = 0; сбрасывает время, отслеживаемое объектом, на «с настоящего момента».
    • беззнаковый длинный deltaT = elapsedMillisObject; позволяет нам посмотреть отслеживаемое время
    • elapsedMillisObject + = и - = они работают как ожидалось

Блокировка vs.неблокирующий код

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

  • Напрасная трата времени ЦП: для более сложных эскизов может потребоваться ЦП для чего-то еще в ожидании окончания периода мигания светодиода.
  • Неожиданные задержки
  • : при вызове delay () в подпрограммах, которые явно не вызываются, например в библиотеках, которые вы включаете.
  • пропущенных событий, которые происходят во время задержки и не обрабатываются обработчиком прерывания, например, нажатие кнопки по запросу: кнопка может быть нажата в течение 100 мс, но это может быть затенено задержкой (500) .

Подробности реализации

millis () обычно использует аппаратный таймер, который работает со скоростью намного выше 1 кГц. Когда вызывается millis () , реализация возвращает некоторое значение, но вы не знаете, сколько ему лет на самом деле.Возможно, что «текущая» миллисекунда только началась или закончится сразу после вызова этой функции. Это означает, что при вычислении разницы между двумя результатами из millis () вы можете отклониться от любого значения от почти нуля до почти одной миллисекунды. Используйте микросхемы () , если требуется более высокая точность.

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




Синхронизация программы Arduino - Circuit Cellar

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

При написании программы Arduino для светодиодных ламп RGB, упомянутых в моей майской колонке (Circuit Cellar 310), я задавался вопросом, сколько времени требуется на тригонометрические вычисления с плавающей запятой. Вместо того, чтобы оборачивать программные измерения вокруг кода, я добавил пару инструкций для переключения выходного бита, а затем посмотрел результаты на осциллографе. Это классический метод, который помогает вам отлаживать программное обеспечение, когда нет другого способа увидеть, что происходит внутри вашего кода, или когда сложные процедуры трассировки нарушают нормальную работу микропрограммы.

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

ОСНОВНАЯ ШИРИНА ИМПУЛЬСА

В листинге 1 показана простейшая программа Arduino, которая производит видимый результат. Эти две линии переключают контакт 13, светодиод, который есть почти на всех платах Arduino, чтобы сформировать 5.Импульсы длительностью 1 мкс на Фото 1, каждый из которых отмечает одну итерацию цикла (), который выполняется непрерывно после завершения настройки в разделе setup (). Хотя показание курсора осциллографа дает три дробных разряда, истинное разрешение значительно хуже, поскольку каждый горизонтальный пиксель покрывает 0,040 мкс.

СПИСОК 1: Простейшая из возможных программ Arduino производит одиночный импульс на выходном бите во время каждой итерации loop (). Хотя микроконтроллер ATmega328 может немного перевернуть бит с помощью одной инструкции на языке ассемблера, каждая из этих высокоуровневых функций выполняет десятки инструкций сборки до и после смены бита.

Микроконтроллер Atmel ATmega328 может переключать выходной бит с помощью одной инструкции, что делает функцию digitalWrite () в инфраструктуре времени выполнения Arduino слишком сложной: пятнадцать строк кода с длиной пути 12 строк. Среди других задач код должен выбрать и проверить аппаратный порт, создать битовую маску для выбора вывода, обработать особый случай вывода ШИМ и отключить прерывания при манипулировании портом.

ФОТО 1: Для каждой функции digitalWrite (), генерирующей этот импульс, требуется 5.1 мкс, примерно 50 инструкций на микроконтроллере ATmega328 16 МГц. Цикл Arduino () добавляет 0,40 мкс к нижней части сигнала.

Домашнее задание: найдите и изучите функцию digitalWrite () в исходном коде Arduino, а затем объясните, почему вся эта дополнительная логика не является обязательной.

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

Кварцевый генератор 16 МГц на клонированной плате Arduino UNO, которую я использовал для этих измерений, выдает цикл команд 62,5 нс, поэтому каждый импульс 5 мкс содержит около 80 циклов. Для большинства арифметических инструкций AVR требуется один или два цикла, для ветвей требуется два или три цикла, а пары подпрограмм CALL / RETURN поглощают восемь, поэтому при условии 1.6 циклов / инструкция для коротких подпрограмм кажутся разумными и позволяют представить результат в уме: 10 инструкций на микросекунду. Это означает, что компилятор переводит дюжину высокоуровневых строк кода в функции digitalWrite () в 50 инструкций машинного уровня.

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

Низкая часть импульса возникает, когда выполнение продолжается через инфраструктуру Arduino, поскольку loop () возвращает управление первой строке digitalWrite (), добавляя 400 нс за кулисами.Это всего шесть машинных циклов, возможно, три или четыре машинных инструкции и совсем немного накладных расходов.

ОТСЛЕЖИВАНИЕ ОТСУТСТВУЮЩЕГО ИМПУЛЬСА

Запуск осциллографа по сигналу, полученному в листинге 1, должен давать устойчивый дисплей, но вы увидите «призрачные» кривые, которые, как кажется, показывают пропущенные импульсы. Установка триггера на создание одиночных разверток в конечном итоге приведет к отображению изображения, аналогичному фото 2, с явно пропущенным импульсом.

ФОТО 2: «Отсутствие импульса» возникает, когда прерывание по таймеру выполняет дополнительные инструкции, которые не отображаются в пользовательской программе.Прерывание также может произойти, когда импульс высокий, вызывая неожиданно длинный импульс.

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

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

Поскольку loop () в листинге 1 повторяется каждые 10,4 мкс, прерывание таймера будет происходить один раз через каждые 96 импульсов, растягивая либо верхнюю, либо нижнюю часть импульса. Преимущество осциллографа должно быть очевидным: проблема, которая возникает в 1% случаев, может не проявляться среди всех «правильных» значений, показываемых простым программным измерением.

Оператор if () в листинге 2 определяет, изменилось ли возвращаемое значение из millis (), и, если да, генерирует импульс на выводе 11. Нижняя кривая на фото 3 показывает этот импульс, когда осциллограф запускает одиночную развертку. на этом булавке и триггерной точке в центре экрана. Верхняя кривая, как и раньше, исходит от контакта 13 и показывает тот же «пропущенный» импульс из-за обработчика прерывания таймера.

СПИСОК 2: Функция millis () возвращает количество миллисекунд, прошедших с момента последнего сброса микроконтроллера.В 98,7% случаев сравнение будет ложным, но этот тест добавляет 2 мкс к среднему времени цикла ().

Курсоры, ограничивающие импульс в 7,4 мкс на верхнем графике, показывают, что оператор if () добавляет 2,3 мкс ко времени выполнения кода в листинге 1, даже если значение millis () не изменяется. ЦП использует эти 35 тактовых циклов и две дюжины инструкций для вызова функции millis (), проверки ее возвращаемого значения и перехода по коду внутри условного блока. Вы можете увидеть эффект каждой инструкции в этой шкале времени!

ФОТО 3: Импульс на нижнем графике показывает, что «пропущенный импульс» возникает при изменении возвращаемого значения функции millis ().Проверка значения millis () увеличивает длительность loop (), как показано при сравнении импульсов на верхней кривой с импульсами на Фото 2.

Длинный импульс в середине верхней кривой показывает, что происходит сразу после того, как происходит прерывание таймера: обнаружение изменение, генерация синхроимпульса в нижней трассе и обновление переменной Millis_Previous требует на 22 мкс, примерно на 15 мкс и на 150 инструкций больше, чем в предыдущем коде.

Логический анализатор может запускать захват на основе логической комбинации многих входов, ситуация, которая зависит от наличия доступа ко всем этим сигналам.Микроконтроллер закапывает эти сигналы внутри ЦП, где для их объединения в триггер требуется программное обеспечение, а не оборудование. Аналогичная ситуация возникает с логикой вентильной матрицы, где добавление дополнительной логики внутри FPGA может сгенерировать подходящие триггеры, если у вас есть запасной выходной контакт, и может быть единственным способом изолировать неуловимые сбои из-за комбинаций, которые возникают так редко, что быть невидимым.

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

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

Эд Нисли - инженер-электрик и писатель из Покипси, штат Нью-Йорк. Он пишет для Circuit Cellar с 1988 года. Его регулярная колонка «Над землей» появляется раз в два месяца в журнале Circuit Cellar.

GPS-часы Arduino с местным временем с использованием модуля NEO-6M

/ *

* GPS-часы Arduino с местным временем с использованием модуля NEO-6M и ЖК-дисплея 20x4.

* Это бесплатное программное обеспечение БЕЗ ГАРАНТИЙ.

* https: // простая схема.com /

* /

#include // включить библиотеку TinyGPS ++

#include // включить библиотеку времени Arduino

#include // включить последовательную библиотеку программного обеспечения

#include // включить библиотеку ЖК-дисплея

TinyGPSPlus gps;

#define S_RX 9 // определение программного последовательного вывода RX

#define S_TX 8 // определение программного последовательного вывода TX

SoftwareSerial SoftSerial (S_RX, S_TX); // настройка библиотеки SoftSerial

// Подключения ЖК-модуля (RS, E, D4, D5, D6, D7)

LiquidCrystal lcd (2, 3, 4, 5, 6, 7);

#define time_offset 3600 // определить смещение часов на 3600 секунд (1 час) ==> UTC + 1

// определения переменных

char Time [] = "TIME: 00:00:00 ";

char Date [] = "ДАТА: 00-00-2000";

байт последняя_секунда, секунда, минута, час, день, месяц;

int Год;

void setup (void)

{

SoftSerial.begin (9600); // инициализация программного обеспечения на скорости 9600 бод

// установка количества столбцов и строк ЖК-дисплея

lcd.begin (20, 4);

lcd.setCursor (1, 0); // перемещаем курсор ЖК-дисплея в столбец 1, строку 0 [верхнее левое положение (0, 0)]

lcd.print ("GPS CLOCK (UTC + 1)");

}

void loop ()

{

while (SoftSerial.available ()> 0)

{

if (gps.encode (SoftSerial.read ()))

{

// получаем время от модуля GPS

if (gps.time.isValid ())

{

Minute = gps.time.minute ();

Секунда = gps.time.second ();

Час = gps.time.hour ();

}

// получить дату от модуля GPS

if (gps.date.isValid ())

{

Day = gps.date.day ();

Месяц = ​​GPS.date.month ();

Год = gps.date.year ();

}

if (last_second! = Gps.time.second ()) // если время изменилось

{

last_second = gps.time.second ();

// установить текущее время UTC

setTime (час, минута, секунда, день, месяц, год);

// добавляем смещение, чтобы получить местное время

adjustTime (time_offset);

// обновить массив времени

Time [12] = second () / 10 + '0';

Время [13] = секунда ()% 10 + '0';

Время [9] = минута () / 10 + '0';

Время [10] = минута ()% 10 + '0';

Время [6] = час () / 10 + '0';

Время [7] = час ()% 10 + '0';

// обновить массив дат

Date [14] = (year () / 10)% 10 + '0';

Дата [15] = год ()% 10 + '0';

Дата [9] = месяц () / 10 + '0';

Дата [10] = месяц ()% 10 + '0';

Дата [6] = день () / 10 + '0';

Дата [7] = день ()% 10 + '0';

// распечатать время и дату

print_wday (weekday ()); // выводим день недели

lcd.setCursor (0, 2); // перемещаем курсор в столбец 0 строка 2

lcd.print (Time); // время печати (ЧЧ: ММ: СС)

lcd.setCursor (0, 3); // перемещаем курсор в столбец 0 строка 3

lcd.print (Date); // печать даты (ДД-ММ-ГГГГ)

}

}

}

}

// функция отображения дня недели

wday)

{

ЖК.setCursor (5, 1); // перемещаем курсор в столбец 5, строка 1

switch (wday)

{

case 1: lcd.print ("SUNDAY"); сломать;

корпус 2: lcd.print («ПОНЕДЕЛЬНИК»); сломать;

корпус 3: lcd.print («ВТОРНИК»); сломать;

корпус 4: lcd.print («СРЕДА»); сломать;

корпус 5: lcd.print («ЧЕТВЕРГ»); сломать;

корпус 6: lcd.print («ПЯТНИЦА»); сломать;

по умолчанию: lcd.print («СУББОТА»);

}

}

// конец кода.

Как создать говорящие часы Arduino с RTC и преобразованием текста в речь | Ардуино

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

Использование микросхемы RTC

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

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

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

Требуемое оборудование
  • Arduino UNO
  • DS1307 Модуль RTC
  • Макетная плата
  • Соединительные провода
  • Источник питания
  • Кнопка
  • HC-05 Модуль Bluetooth

Требуемое программное обеспечение
  • Arduino IDE
  • Arduino Bluetooth Text-to-Speech Application
  • Модуль DS-1307 RTC

    DS1307 - это часы реального времени (RTC), которые имеют восемь контактов и используют интерфейс I2C.Это часы с низким энергопотреблением с 56-байтовым резервным ОЗУ с резервным аккумулятором. Часы показывают секунды, минуты, часы, день, месяц и год. Дата окончания каждого месяца корректируется автоматически, включая те месяцы, в которых меньше 31 дня.

    Анализ времени выполнения Arduino - Protological

    Недавно меня попросили взглянуть на код для Arduino Yun, который был разработан в качестве доказательства концепции медицинского устройства. Компания, разрабатывающая устройство, «исчерпывала возможности» и не могла заставить Arduino опробовать все входы АЦП в желаемый период времени.Я подозреваю, что они имеют в виду, что у них заканчивается время обработки для выборки / управления несколькими выходами в пределах своего окна обработки. Я всегда работал на уровень ниже схемы проводки Arduino и, честно говоря, мало работал с семейством Arduino, но когда появляется контрактная работа, вы ее принимаете. Первое, что я заметил в коде, - это интенсивное использование значений с плавающей запятой в качестве параметров и возвращаемых значений для множества функций. Любой, кто встраивается, знает, что операции с плавающей запятой занимают НАМНОГО больше времени, чем целочисленная математика, но мне было любопытно, насколько дольше.Я не нашел хороших интернет-ресурсов, в которых говорилось бы, что «деление с плавающей запятой принимает инструкции XXX», поэтому я решил получить эту информацию сам.

    Хотя у меня нет Yun, у меня есть Arduino Uno, который использует ATMega328, 8-битный микроконтроллер с большинством инструкций, выполняемых с частотой 1 инструкция за такт с использованием кристалла 16 МГц. Я решил изучить каждую базовую математическую операцию для целочисленных типов без знака и типов с плавающей запятой. Все входные и выходные переменные были созданы как изменчивые, чтобы компилятор не выполнял оптимизацию, каждая операция выполнялась 1000 раз, а результаты являются средними.Методом записи времени была функция micros (), которая имеет точность 4us и включает в себя длинный сдвиг без знака, добавляя uint8_t и умножая на буквальное значение uint16. Вот результаты на Uno:

    Запуск теста, цикл 1000 раз
    Управление циклом 10 мс: время 10009 мкс
    Div с плавающей запятой: 34 нас ~ 544 инструкции, 29 / мс
    Float mul: 12 us ~ 192 инструкций, 83 / мс
    Сложение с плавающей точкой: 11 us ~ 176 инструкций , 90 / мс
    Float sub: 11 us ~ 176 инструкций, 90 / ms
    uint8 div: 8 us ~ 128 инструкций, 125 / ms
    uint8 mul: 3 us ~ 48 инструкций, 333 / ms
    uint8 add: 3 us ~ 48 инструкций, 333 / мс
    uint8 sub: 3 us ~ 48 инструкций, 333 / мс
    uint16 div: 16 us ~ 256 инструкций, 62 / мс
    uint16 mul: 4 us ~ 64 инструкции, 250 / мс
    uint16 add: 3 us ~ 48 инструкций, 333 / мс
    uint16 sub: 3 us ~ 48 инструкций, 333 / мс
    uint32 div: 41 us, ~ 656 инструкций, 24 / мс
    uint32 mul: 9 us, ~ 144 инструкций, 111 / мс
    uint32 add: 4 us, ~ 64 инструкции, 250 / мс
    uint32 sub: 4 us, ~ 64 инструкции, 250 / мс

    Интересно то, что деление uint32_t занимает больше времени, чем деление с плавающей запятой! В целом очевидно, что по мере увеличения целого числа время обработки увеличивается.Операции с плавающей запятой в 3-4 раза длиннее целочисленных операций (за исключением деления uint32_t). Я оценил количество инструкций на операцию, исходя из частоты 16 МГц, и сколько из каждой операции можно было выполнить за 1 мс.

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

    Вот код, который я использовал для получения этих значений: http://protological.com/browser/files/timer_sketch.ino.
    (Вот тот же код, но с функцией макроса, он немного чище)

    MEP EP # 287: предвзято для Arduino

    Паркер Диллманн |

    Система тестирования смещения
    • Получена первая плата, построенная и установленная на Arduino
    • .
    • Первые испытания прошли успешно
    • Библиотека
    • Arduino - работает «впервые»
    • 2.Опорное напряжение 5 В
      • MCP1501T-25E / CHY
      • Начальная точность 0,1%
      • Дрейф 50ppm
      • Я измерил несколько из них на работе и обнаружил, что результат находится в этом диапазоне - 2,498
    • Arduinos и USB шумят
    • Измерения сопротивления постоянным током
      • Источник постоянного тока, управляемый операционным усилителем
      • Измеренный выходной ток 1 мА при 1,001 мА с резистором 1 кОм
      • Выходной ток в некоторой степени зависит от нагрузки - выше при более высоких значениях сопротивления
      • Возможно, следовало пойти с параллельной конфигурацией операционных усилителей
    • Проверка
      • Напряжения вроде хорошо читаются.
      • От 0 до 300 В было в пределах 1% от счетчика
      • Малое «смещение» показания
        • Это связано с смещением усилителя входного буфера.
          • В техническом описании указано 125 как стандартное и 750 как максимальное
        • Я видел диапазон от 100 до 400 мкВ
        • Откалибруем
      • При выполнении простой коррекции смещения я могу получить показания 0,00000X
      • Для резистивных измерений наблюдается странная ошибка смещения усиления.
      • Проверил ток и напряжение, но показания не совпадают
      • Около 1.7% низкий для всех показаний
    • Что дальше
      • Завершить проверку оборудования с использованием лучших стандартов и измерителей
      • Объедините библиотеки scipi и ads1256
      • Сделайте графический интерфейс
      • Прибыль
    Нарекания на arduino
    • Когда укусить пулю и решить проблему?
      • Штифт заголовка
      • Монтажные отверстия
    • Решение….

    alexxlab

    Добавить комментарий

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