Метеостанция на ардуино с дисплеем

Example Program

#include <TimerOne.h>

// This example uses the timer interrupt to blink an LED
// and also demonstrates how to share a variable between
// the interrupt and the main program.

const int led = LED_BUILTIN;  // the pin with a LED

void setup(void)
{
  pinMode(led, OUTPUT);
  Timer1.initialize(150000);
  Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds
  Serial.begin(9600);
}


// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
int ledState = LOW;
volatile unsigned long blinkCount = 0; // use volatile for shared variables

void blinkLED(void)
{
  if (ledState == LOW) {
    ledState = HIGH;
    blinkCount = blinkCount + 1;  // increase when LED turns on
  } else {
    ledState = LOW;
  }
  digitalWrite(led, ledState);
}


// The main program will print the blink count
// to the Arduino Serial Monitor
void loop(void)
{
  unsigned long blinkCopy;  // holds a copy of the blinkCount

  // to read a variable which the interrupt code writes, we
  // must temporarily disable interrupts, to be sure it will
  // not change while we are reading.  To minimize the time
  // with interrupts off, just quickly make a copy, and then
  // use the copy while allowing the interrupt to keep working.
  noInterrupts();
  blinkCopy = blinkCount;
  interrupts();

  Serial.print("blinkCount = ");
  Serial.println(blinkCopy);
  delay(100);
}

Сборка метеостанции с дисплеем 1602 и DHT11

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

  • плата Arduino UNO (NANO);
  • жидкокристаллический дисплей 1602 с I2C;
  • цифровой датчик DHT11 или DHT22;
  • провода «папа-мама», «папа-папа»;
  • макетная плата (при необходимости).

К Arduino Nano и Uno все датчики и дисплей подключаются по одной схеме — распиновка и подключение уже рассматривались на нашем сайте, поэтому не будем подробно останавливаться на этом моменте. Если у вас есть вопросы, то посмотрите следующие записи: Подключение DHT11 к Ардуино и Подключение LCD 1602 к Ардуино. Соберите метеостанцию на Ардуино с дисплеем 1602 и dht11, как на схеме ниже.

Что такое таймеры

Что же представляют собой таймеры в современной электронике? Фактически это определенный вид прерываний. Это простые часы, которые могут измерять длительность какого-нибудь события. Каждый микроконтроллер имеет встроенные часы (осциллятор), в плате Arduino Uno этот осциллятор работает на частоте 16 МГц. Частота влияет на скорость обработки. Чем выше частота, тем выше скорость обработки. Таймер использует счетчик, который считает с определенной скоростью, зависящей от частоты осциллятора. В плате Arduino Uno состояние счетчика увеличивается на 1 каждые 62 нано секунды (1/16000000 секунды). Фактически, это время за которое плата Arduino Uno переходит от одной инструкции к другой.

Модифицированные библиотеки от Paul Stoffregen

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

Плата ШИМ выводы TimerOne ШИМ выводы TimerThree
Teensy 3.1 3, 4 25, 32
Teensy 3.0 3, 4  
Teensy 2.0 4, 14, 15 9
Teensy++ 2.0 25, 26, 27 14, 15, 16
Arduino Uno 9, 10  
Arduino Leonardo 9, 10, 11 5
Arduino Mega 11, 12, 13 2, 3, 5
Wiring-S 4, 5  
Sanguino 12, 13  

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

Возобновляет работу остановленного таймера. Новый период не начинается.

Timer1

Данная библиотека представляет собой набор функций для настройки аппаратного 16-битного таймера Timer1 в ATMega168/328. В микроконтроллере доступно 3 аппаратных таймера, которые могут быть настроены различными способами для получения различных функциональных возможностей. Начало разработки данной библиотеки было вызвано необходимостью быстро и легко установить период или частоту ШИМ сигнала, но позже она разраслась, включив в себя обработку прерываний по переполнению таймера и другие функции. Она может быть легко расширена или портирована для работы с другими таймерами.

Точность таймера зависит от тактовой частоты процессора. Тактовая частота таймера Timer1 определяется установкой предварительного делителя частоты. Этот делитель может быть установлен в значения 1, 8, 64, 256 или 1024.

для тактовой частоты 16 МГц
Делитель Длительность одного отсчета, мкс Максимальный период, мс
1 0,0625 8,192
8 0,5 65,536
64 4 524,288
256 16 2097,152
1024 64 8388,608

В общем:

  • Максимальный период = (Делитель / Частота) × 217
  • Длительность одного отсчета = (Делитель / Частота)

Скачать можно здесь (TimerOne-r11.zip) или с Google Code.

Для установки просто распакуйте и поместите файлы в каталог Arduino/hardware/libraries/Timer1/.

Interrupt Context Issues

Variables usually need to be «volatile» types. Volatile tells the compiler to
avoid optimizations that assume variable can not spontaneously change. Because your
function may change variables while your program is using them, the compiler needs
this hint. But volatile alone is often not enough.

When accessing shared variables, usually interrupts must be disabled. Even with
volatile, if the interrupt changes a multi-byte variable between a sequence of
instructions, it can be read incorrectly. If your data is multiple variables,
such as an array and a count, usually interrupts need to be disabled for the entire
sequence of your code which accesses the data.

Synchronization With Other Time Services

Time can synchronize its clock with another source of known time. You can use
the setTime functions above, or configure Time to automatically call a function
which will report the time.

timeStatus

Returns the status of time sync. Three type of status are defined, with
these names:

timeNotSet     Time's clock has not been set.  The time & date are unknown.
timeSet        Time's clock has been set.
timeNeedsSync  Time's clock is set, but the sync has failed, so it may not be accurate.

setSyncProvider

Configure Time to automatically called the getTimeFunction() regularly. This
function should obtain the time from another service and return a time_t number,
or zero if the time is not known.

setSyncInterval

Configure how often the getTimeFunction is called.

Игра на Ардуино с дисплеем LCD I2C

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

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • жидкокристаллический дисплей с I2C;
  • одна тактовая кнопка и резистор;
  • пьезодинамик;
  • провода «папа-папа», «папа-мама».


Arduino Game. Схема сборки игры на Ардуино

Вместо подключения кнопки к Ардуино через резистор на макетной плате можно использовать модуль с кнопкой. Пьезодинамик (пьезоизлучатель) подключается к плате при желании, можно обойтись и без него. Соберите схему, как на картинке выше, и загрузите следующий скетч. Скачать программу для игры «Дракончик» на Arduino с жк дисплеем можно здесь. Скорость игры и звуки можно изменить в программе.

Скетч для игры «Дракончик» на дисплее

#include <Wire.h>                             // библиотека для протокола IIC
#include <LiquidCrystal_I2C.h>        // подключаем библиотеку LCD IIC
LiquidCrystal_I2C LCD(0x27, 20, 2); // присваиваем имя lcd для дисплея

int level = 1;       // переменная для отсчета уровня
int pause = 400; // переменная для задержки
byte p = 0;          // переменная для времени прыжка

// создаем массивы дракончика, дерева, камня и птицы
byte dracon = {
 0b01110, 0b11011, 0b11111, 0b11100, 0b11111, 0b01100, 0b10010, 0b11011
};
byte derevo = {
 0b00000, 0b00000, 0b00000, 0b11011, 0b11011, 0b11011, 0b01100, 0b01100
};
byte kamen = {
 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01110, 0b11111
};
byte ptica = {
 0b00100, 0b00101, 0b01111, 0b11111, 0b10100, 0b00100, 0b00000, 0b00000
};

void setup() {
 pinMode (10, OUTPUT); // подключаем пьезодинамик
 pinMode (A1, INPUT);     // подключаем кнопку
 analogWrite(A1, LOW);
 LCD.init();                        // инициализация LCD дисплея
 LCD.backlight();              // включение подсветки дисплея

 // создаем символы дракончика, дерева, камня и птицы
 LCD.createChar(0, dracon);
 LCD.createChar(1, derevo);
 LCD.createChar(2, kamen);
 LCD.createChar(3, ptica);

 // начинаем игру: выводим надпись GO!
 LCD.setCursor(7, 0);
 LCD.print("GO!");
 delay(400);
 tone(10, 600);
 delay(100);
 noTone(10);
 LCD.clear();
}

void loop() {
  // первоначальное положение дракончика и препятствия
  byte d = 1;
  byte x = 15;
  byte y = 1;
  // выбираем препятствие, которое появится, рандомно
  byte i = random (1, 4);
  if (i == 3) y = 0;
  else y = 1;

  while (x > 0) {
    // очищаем экран и выводим номер уровня
    LCD.clear();
    LCD.setCursor(0, 0);
    LCD.print(level);

    // считываем данные с кнопки и учитываем количество циклов в прыжке
    // если дакончик находится в прыжке долго - возвращаем его вниз
    if (analogRead(A1) > 100) d = 0;
    if (analogRead(A1) < 100) d = 1;
    if (p > 3) d = 1;

    // выводим дракончика в нужной строке
    LCD.setCursor(4, d);
    LCD.print(char(0));
    // выводим препятствие
    LCD.setCursor(x, y);
    tone(10, 50);
    LCD.print(char(i));
    noTone(10);

    // если дракончик наткнулся на препятствие выводим надпись GAME OVER!
    if (x == 4 && y == d) {
      delay(400);
      tone(10, 50);
      delay(100);
      noTone(10);
      delay(100);
      tone(10, 20);
      delay(300);
      noTone(10);
      LCD.clear();
      delay(200);
      LCD.setCursor(3, 0);
      LCD.print("GAME OVER!");
      delay(600);
      LCD.clear();
      delay(400);
      LCD.setCursor(3, 0);
      LCD.print("GAME OVER!");
      delay(600);
      LCD.clear();
      LCD.setCursor(3, 1);
      LCD.print("LEVEL: ");
      LCD.print(level);
      delay(400);
      LCD.setCursor(3, 0);
      LCD.print("GAME OVER!");
      delay(3000);
      LCD.clear();

      // начинаем игру заново, обнулив уровень игры
      LCD.setCursor(7, 0);
      LCD.print("GO!");
      delay(400);
      tone(10, 600);
      delay(100);
      noTone(10);
      LCD.clear();

      level = 0;
      pause = 400;
      p = 0;
      y = 1;
      x = 0;
      break;
    }

    // если дракончик прыгнул, издаем звук
    if (d == 0) { tone(10, 200); delay(100); noTone(10); }
    else { delay(100); }

    // если дракончик не столкнулся, то меняем положение препятствия
    // начинаем считать сколько циклов дракончик находится в прыжке
    delay(pause);
    x = x - 1;
    p = p + 1;
    if (p > 4) p = 0; 
 }

  // переходим на следующий уровень и сокращаем время задержки
  tone(10, 800);
  delay(20);
  level = level + 1;
  pause = pause - 20;
  if (pause < 0) pause = 0;
}

Методы библиотек TimerOne и TimerThree

Настройка

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

Обратите внимание, что это нарушает работу на цифровых выводах 9 и 10 на Arduino.

Устанавливает период в микросекундах. Минимальный период и максимальная частота, поддерживаемые данной библиотекой, равны 1 микросекунде и 1 МГц, соответственно

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

Управление запуском

Запускает таймер, начиная новый период.
Останавливает таймер.
Перезапускает таймер, обнуляя счетчик и начиная новый период.

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

Генерирует ШИМ сигнал на заданном выводе . Выходными выводами таймера Timer1 являются выводы 1 и 2, поэтому вы должны выбрать один из них, всё остальное игнорируется. На Arduino это цифровые выводы 9 и 10, эти псевдонимы также работают. Выходными выводами таймера Timer3 являются выводы , соответствующие выводам 2, 3 и 5 на Arduino Mega. Коэффициент заполнения задается, как 10-битное значение в диапазоне от 0 до 1023 (0 соответствует постоянному логическому нулю на выходе, а 1023 – постоянной логической единице)

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

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

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

Прерывания

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

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

Отключает прикрепленное прерывание.

Установка библиотеки LiquidCrystal I2C

Для работы с данным модулем необходимо установить библиотеку LiquidCrystal I2C. Скачиваем, распаковываем и закидываем в папку libraries в папке Arduino. В случае, если на момент добавления библиотеки, Arduino IDE была открытой, перезагружаем среду.

Библиотеку можно установить из самой среды следующим образом:

  1. В Arduino IDE открываем менеджер библиотек: Скетч->Подключить библиотеку->Управлять библиотеками…
  2. В строке поиска вводим «LiquidCrystal I2C», находим библиотеку Фрэнка де Брабандера (Frank de Brabander), выбираем последнюю версию и кликаем Установить.
  3. Библиотека установлена (INSTALLED).

Что за идея

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

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

На скриншоте выше видно, что код реализован таким образом, что теперь инкремент s будет выполняться каждую 1 секунду и не больше, в зависимости от времени выполнения цикла loop{}.

В связи с этим резисторы и потенциометры мы полностью удалили.

Кнопки настройки времени вы можете использовать встроенные в микросхему ATmega328P.

pinMode(hs, INPUT_PULLUP) избегает использования внешнего Pullup. Подробнее о INPUT_PULLUP читайте в нашем Справочнике программиста Ардуино.

Избегайте потенциометра ЖК-дисплея.

Контрастность ЖК-дисплея может быть установлена с помощью сигнала PWM (Широтно-импульсная модуляция (ШИМ, англ. pulse-width modulation (PWM))) Arduino.

То же самое для подсветки, которая питается сигналом ШИМ (PWM) Arduino, поэтому её можно установить как вкл/выкл с помощью Arduino.

Подключение LCD keypad shield к Arduino

Необходимые детали:
► Arduino UNO R3 x 1 шт.
► LCD модуль keypad (LCD1602, 2×16, 5V)
► Кабель USB 2.0 A-B x 1 шт.

Подключение
Установите модуль на плату Arduino UNO, подключите кабель и закрущите данный скетч.

/*
Тестирование производилось на Arduino IDE 1.6.12
Дата тестирования 06.12.2016г.
*/

#include <LiquidCrystal.h> // Подключяем библиотеку
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); // Указываем порты

void setup()
{
lcd.begin(16, 2); // Инициализируем LCD 16×2
lcd.setCursor(0,0); // Установить курсор на первую строку
lcd.print(«LCD1602»); // Вывести текст
lcd.setCursor(0,1); // Установить курсор на вторую строку
lcd.print(«www.robotchip.ru»); // Вывести текст
Serial.begin(9600); // Включаем последовательный порт
}

void loop() {
int x; // Создаем переменную x
x = analogRead (0); // Задаем номер порта с которого производим считывание
lcd.setCursor(10,1); // Установить курсор на вторую строку
if (x < 100) { // Если x меньше 100 перейти на следующею строк
lcd.print («Right «); // Вывести текст
Serial.print(«Value A0 ‘Right’ is :»); // Вывести текст
Serial.println(x,DEC); // Вывести значение переменной x
}
else if (x < 200) { // Если х меньше 200 перейти на следующию строку
lcd.print («Up «); // Вывести текст
Serial.print(«Value A0 ‘UP’ is :»); // Вывести текст
Serial.println(x,DEC); // Вывести значение переменной x
}
else if (x < 400){ // Если х меньше 400 перейти на следующию строку
lcd.print («Down «); // Вывести текст
Serial.print(«Value A0 ‘Down’ is :»); // Вывести текст
Serial.println(x,DEC); // Вывести значение переменной x
}
else if (x < 600){ // Если х меньше 600 перейти на следующию строку
lcd.print («Left «); // Вывести текст
Serial.print(«Value A0 ‘Left’ is :»); // Вывести текст
Serial.println(x,DEC); // Вывести значение переменной x
}
else if (x < 800){ // Если х меньше 800 перейти на следующию строку
lcd.print («Select»); // Вывести текст
Serial.print(«Value A0 ‘Select’ is :»);// Вывести текст
Serial.println(x,DEC); // Вывести значение переменной x
}
}

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

/*
  Тестирование производилось на Arduino IDE 1.6.12
  Дата тестирования 06.12.2016г.

*/

 
#include <LiquidCrystal.h>                // Подключяем библиотеку

LiquidCrystal lcd(8,9,4,5,6,7);// Указываем порты        

voidsetup()

{

lcd.begin(16,2);// Инициализируем LCD 16×2  

lcd.setCursor(,);// Установить курсор на первую строку  

lcd.print(«LCD1602»);// Вывести текст

lcd.setCursor(,1);// Установить курсор на вторую строку

lcd.print(«www.robotchip.ru»);// Вывести текст

Serial.begin(9600);// Включаем последовательный порт

}
 

voidloop(){

intx;// Создаем переменную x

x=analogRead();// Задаем номер порта с которого производим считывание

lcd.setCursor(10,1);// Установить курсор на вторую строку

if(x<100){// Если x меньше 100 перейти на следующею строк

lcd.print(«Right «);// Вывести текст

Serial.print(«Value A0 ‘Right’ is  :»);// Вывести текст

Serial.println(x,DEC);// Вывести значение переменной x

}

elseif(x<200){// Если х меньше 200 перейти на следующию строку

lcd.print(«Up    «);// Вывести текст

Serial.print(«Value A0 ‘UP’ is  :»);// Вывести текст

Serial.println(x,DEC);// Вывести значение переменной x

}

elseif(x<400){// Если х меньше 400 перейти на следующию строку

lcd.print(«Down  «);// Вывести текст

Serial.print(«Value A0 ‘Down’ is  :»);// Вывести текст

Serial.println(x,DEC);// Вывести значение переменной x

}

elseif(x<600){// Если х меньше 600 перейти на следующию строку

lcd.print(«Left  «);// Вывести текст

Serial.print(«Value A0 ‘Left’ is  :»);// Вывести текст

Serial.println(x,DEC);// Вывести значение переменной x

}

elseif(x<800){// Если х меньше 800 перейти на следующию строку

lcd.print(«Select»);// Вывести текст

Serial.print(«Value A0 ‘Select’ is  :»);// Вывести текст

Serial.println(x,DEC);// Вывести значение переменной x

}
}

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

Ссылки  Документация к LCD1602A  Документация к LCD ZYMC1602  Документация к HD44780U

Купить на Aliexpress  Контроллер Arduino UNO R3  LCD модуля keypad (LCD1602, 2×16, 5V)

Купить в Самаре и области  Купить контроллер Arduino UNO R3  Купить LCD модуля keypad (LCD1602, 2×16, 5V)

Технические параметры

Описание дисплея

LCD 1602A представляет собой электронный модуль основанный на драйвере HD44780 от Hitachi. LCD1602 имеет 16 контактов и может работать в 4-битном режиме (с использованием только 4 линии данных) или 8-битном режиме (с использованием всех 8 строк данных), так же можно использовать интерфейс I2C. В этой статье я расскажу о подключении в 4-битном режиме.

Назначение контактов:
► VSS:   «-» питание модуля
► VDD:  «+» питание модуля
► VO:    Вывод управления контрастом
► RS:     Выбор регистра
► RW:   Выбор режима записи или чтения (при подключении к земле, устанавливается режим записи)
► E:       Строб по спаду
► DB0-DB3: Биты интерфейса
► DB4-DB7: Биты интерфейса
► A:      «+» питание подсветки
► K:      «-»  питание подсветки

На лицевой части модуля располагается LCD дисплей и группа контактов.

На задней части модуля расположено два чипа в «капельном» исполнении (ST7066U и ST7065S) и электрическая обвязка, рисовать принципиальную схему не вижу смысла, только расскажу о резисторе R8 (100 Ом), который служит ограничительным резистором для светодиодной подсветки, так что можно подключить 5В напрямую к контакту A. Немного попозже напишу статью в которой расскажу как можно менять подсветку LCD дисплея с помощью ШИП и транзистора.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Код

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

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

/*
 ###  Самые простые часы на Arduino UNO ###

 Для проекта часов нужны только жк-дисплей 16х2 LCD и 2 кнопки
 Никаких потенциометров для контраса, никаких резисторов 
 Функции кнопок:
 
 - короткое нажатие одной из кнопок включает подсветку на 30 с
 
 Настройка времени
 - Нажмите H для увеличения Часов
 - Нажмите M для увеличения Минут и сброса секунд
*/

#include "LiquidCrystal.h"

// Определяем соединение ЖК-дисплея с цифровыми контактами
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// Настройка контрастности ЖК
int cs=9;// пин 9 для контраста ШИМ
const int contrast = 100;// контраст по умолчанию

// Начальное отображение времени 12:59:45 PM
int h=12;
int m=59;
int s=45;
int flag=1; //PM

// Кнопки установки времени
int button1;
int button2;

// Определение пинов для Кнопок установки времени
int hs=0;// pin 0 для настройки Часов
int ms=1;// pin 1 для настройки Минут

// Тайм-аут подсветки 
const int Time_light=150;
int bl_TO=Time_light;// Тайм-аут подсветки
int bl=10; // Пин подсветки
const int backlight=120; // НЕ БОЛЕЕ 7mA !!!

// Для точного считывания времени используйте часы реального времени Arduino, а не только задержку delay()
static uint32_t last_time, now = 0; // RTC

void setup()
{
  lcd.begin(16,2);
  pinMode(hs,INPUT_PULLUP);// избегать внешних Pullup резисторов для кнопки 1
  pinMode(ms,INPUT_PULLUP);// и кнопки 2
  analogWrite(cs,contrast);// Настроить контрастность VO
  analogWrite(bl,backlight);// Включить подсветку 
  now=millis(); // читать начальное значение RTC  
}

void loop()
{ 
  lcd.begin(16,2);// каждую секунду
// Обновить ЖК-дисплей
// Вывести время TIME в Hour, Min, Sec + AM/PM (часы, минуты, секунды)
 lcd.setCursor(0,0);
 lcd.print("Time ");
 if(h<10)lcd.print("0");// всегда 2 цифры
 lcd.print(h);
 lcd.print(":");
 if(m<10)lcd.print("0");
 lcd.print(m);
 lcd.print(":");
 if(s<10)lcd.print("0");
 lcd.print(s);

 if(flag==0) lcd.print(" AM");
 if(flag==1) lcd.print(" PM");
 
 lcd.setCursor(0,1);// для Line 2
 lcd.print("Precision clock");

// улучшенная замена delay(1000) 
// гораздо лучшая точность, менее зависимая от времени выполнения цикла

for ( int i=0 ;i<5 ;i++)// сделать 5-кратный цикл 200 мс, для более быстрого ответа кнопок
{
  while ((now-last_time)<200) //задержка delay 200ms
  { 
    now=millis();
  }
 // внутренний цикл 200ms
 last_time=now; // готовим следующий цикл 

 // read Setting Buttons (читаем кнопки настройки)
 button1=digitalRead(hs);// Read Buttons
 button2=digitalRead(ms);

 //Время подсветки 
 bl_TO--;
 if(bl_TO==0)
 {
  analogWrite(bl,0);// ВЫКЛ подсветки
  bl_TO++;
 }
 
 // Нажмите что-либо, чтобы активировать подсветку 
 if(  ((button1==0)|(button2==0)) & (bl_TO==1)  )
 {
  bl_TO=Time_light;
  analogWrite(bl,backlight);
  // дождитесь отпускания кнопки
  while ((button1==0)|(button2==0))
  {
   button1=digitalRead(hs);// Read Buttons
   button2=digitalRead(ms);
  }
 }
 else
 // Поведение Кнопки 1 или Кнопки 2 пока подсветка ВКЛ 
 {
  if(button1==0){
   h=h+1;
   bl_TO=Time_light;
   analogWrite(bl,backlight);
  }

 if(button2==0){
  s=0;
  m=m+1;
  bl_TO=Time_light;
  analogWrite(bl,backlight);
  }

/* ---- управлять секундами, минутами, часами am / pm ----*/
 if(s==60){
  s=0;
  m=m+1;
 }
 if(m==60)
 {
  m=0;
  h=h+1;
 }
 if(h==13)
 {
  h=1;
  flag=flag+1;
  if(flag==2)flag=0;
 }

 if((button1==0)|(button2==0))// Обновить дисплей, если нажата кнопка
 {
  // Обновить ЖК
  // Вывести время TIME в часах, минутах, секундах + AM/PM
  lcd.setCursor(0,0);
  lcd.print("Time ");
  if(h<10)lcd.print("0");// всегда 2 цифры
  lcd.print(h);
  lcd.print(":");
  if(m<10)lcd.print("0");
  lcd.print(m);
  lcd.print(":");
  if(s<10)lcd.print("0");
  lcd.print(s);

  if(flag==0) lcd.print(" AM");
  if(flag==1) lcd.print(" PM");
 
  lcd.setCursor(0,1);// для Line 2
  lcd.print("Precision clock");
 }

 } // end if else
}// end for

// outer 1000ms loop (завершение цикла)
 s=s+1; //увеличение секунд
        
// ---- управлять секундами, минутами, часами + am/pm ----
 if(s==60){
  s=0;
  m=m+1;
 }
 if(m==60)
 {
  m=0;
  h=h+1;
 }
 if(h==13)
 {
  h=1;
  flag=flag+1;
  if(flag==2)flag=0;
 }  
// Loop end (конец цикла)
}

Описание методов библиотеки LiquidCrystal I2C

LiquidCrystal_I2C(uint8_t, uint8_t, uint8_t)

Конструктор для создания экземпляра класса, первый параметр это I2C адрес устройства, второй — число символов, третий — число строк.

LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);

1 LiquidCrystal_I2C(uint8_tlcd_Addr,uint8_tlcd_cols,uint8_tlcd_rows);

init()

Инициализация ЖК-дисплея.

void init();

1 voidinit();

backlight()

Включение подсветки дисплея.

void backlight();

1 voidbacklight();

setCursor(uint8_t, uint8_t)

Установка позиции курсора.

void setCursor(uint8_t, uint8_t);

1 voidsetCursor(uint8_t,uint8_t);

clear()

Возвращает курсор в начало экрана.

void clear();

1 voidclear();

home()

Возвращает курсор в начало экрана и удаляет все, что было на экране до этого.

void home();

1 voidhome();

write(uint8_t)

Позволяет вывести одиночный символ на экран.

#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif

1
2
3
4
5

#if defined(ARDUINO) && ARDUINO >= 100

virtualsize_twrite(uint8_t);

#else

virtualvoidwrite(uint8_t);

#endif

cursor()

Показывает курсор на экране.

void cursor();

1 voidcursor();

noCursor()

Скрывает курсор на экране.

void noCursor();

1 voidnoCursor();

blink()

Курсор мигает (если до этого было включено его отображение).

void blink();

1 voidblink();

noBlink()

Курсор не мигает (если до этого было включено его отображение).

void noBlink();

1 voidnoBlink();

display()

Позволяет включить дисплей.

void display();

1 voiddisplay();

noDisplay()

Позволяет отключить дисплей.

void noDisplay();

1 voidnoDisplay();

scrollDisplayLeft()

Прокручивает экран на один знак влево.

void scrollDisplayLeft();

1 voidscrollDisplayLeft();

scrollDisplayRight()

Прокручивает экран на один знак вправо.

void scrollDisplayRight();

1 voidscrollDisplayRight();

autoscroll()

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

void autoscroll();

1 voidautoscroll();

noAutoscroll()

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

void noAutoscroll();

1 voidnoAutoscroll();

leftToRight()

Установка направление выводимого текста — слева направо.

void leftToRight();

1 voidleftToRight();

rightToLeft()

Установка направление выводимого текста — справа налево.

void rightToLeft();

1 voidrightToLeft();

createChar(uint8_t, uint8_t[])

Создает символ. Первый параметр — это номер (код) символа от 0 до 7, а второй — массив 8 битовых масок для создания черных и белых точек.

void createChar(uint8_t, uint8_t[]);

1 voidcreateChar(uint8_t,uint8_t);
Оцените статью:
Оставить комментарий