Главная » 2015 » Июль » 1 » Простые часы на Ардуино и OLED дисплее
21:45
Простые часы на Ардуино и OLED дисплее

В основном часы на Ардуино делают с применением модулей RTC, к примеру DS3231, но иногда можно обойтись и без дополнительных модулей. В данном примере часы реализованы на Ардуино с подключенным OLED дисплеем на контроллере SSD1306. Точность таких часов конечно не высока, но зато бкз дополнительных модулей.

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

Подключение OLED дисплея к Ардуино описано здесь

Для работы необходимо загрузить библиотеку OLED_I2C и подключить их к Arduino. Скачиваем и распаковываем архив в папку Arduino с libraries.

Код

#include <OLED_I2C.h>

const int ledPin =  13;          // номер выхода, подключенного к светодиоду
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода

long previousMillis = 0;        //переменная для хранения значений таймера
// интервал отсчёта, меняя это значение можно корректировать точность хода часов
long interval = 1000;            // интервал между включение/выключением светодиода

// Установка времени и даты
int chas =    23;    //значение часов
int minut =   5;      //значение минут
int sek =      0;      //значение секунд
int den =      1;      //день
int mesac =  7;      //месяц
int god =      2015; //год
int nedela =  3;      // день недели
int wgod =   2000;  //первый высокосный год
int key =     1;        //ключ перевода дня

// инициализация дисплея
OLED  myOLED(SDA, SCL, 8);

// Подключение шрифтов
extern uint8_t SmallFont[];        // Мелкий шрифт (латиница)
extern uint8_t RusFont[];          // русские шрифты
extern uint8_t MegaNumbers[]; // Подключение больших цифр

void setup()
{
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);
  myOLED.begin();
}


void loop()
{
  unsigned long currentMillis = millis();
  //проверяем не прошел ли нужный интервал, если прошел то
  if (currentMillis - previousMillis > interval)

  {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;
    sek++;                // Добавляем секунду

    if (sek > 59) {       //если переменная секунд больше 59 ...
      sek = 0;            //сбрасываем ее на 0
      minut++;            //пишем +1 в переменную минут
    }

    if (minut > 59) {     //если переменная минут больше 59 ...
      minut = 0;          //сбрасываем ее на 0
      chas++;             //пишем +1 в переменную часов
    }

    if (chas > 23) {      //если переменная часов больше 23 ...
      chas = 0;           //сбрасываем ее на 0
      nedela++;           // переводим день недели
      if (nedela == 8) {  // Если день недели = 8
      nedela = 1;         // то ставим на 1 (Понедельник)
      }

// Если сейчас февраль и 29 число
      if (mesac == 2 && den == 29) {
        den = 1;          // Переводим день на 1 число
        mesac++;          // Переводим месяц
        key = 0;          // Устанавливаем флаг перевода дня
      }
// Если сейчас февраль и 28 число
      if (mesac == 2 && den == 28) {
// Высчитываем ближайший високосный год
        do {              
          wgod = wgod + 4;    // в циклк вычисяем высокосные года
        } while (wgod < god); // и сравниваем с текущим годом
// Если сравниваемый високосный год равен текущему
        if (wgod == god) {
          den++;              // прибавляем день
          key = 0;            // Устанавливаем флаг перевода дня
        }
        else {    // Если сравниваемый високосный год НЕ равен текущему
          den = 1;            // Устанавливаем первое число
          mesac++;            // Переводим месяц
          key = 0;            // Устанавливаем флаг перевода дня
        }
        wgod = wgod - 4;      // Откатываем сравниваемый високосный год на предыдущий високосный год
      }


// если сечас 30 число
      if ( den == 30 ) {
// и сейчас 4, 6, 9 или 11 месяц
        if (mesac == 4 || mesac == 6 || mesac == 9 || mesac == 11 ) {
          den = 1;            // Устанавливаем первое число
          mesac++;            // Переводим месяц
          key = 0;            // Устанавливаем флаг перевода дня
        }
      }
// Если сейчас 31 число
      if ( den == 31 ) {
// И сейчас 1, 3, 5, 7, 8, 10 или 12 месяц        
        if (mesac == 1 || mesac == 3 || mesac == 5 || mesac == 7 || mesac == 8 || mesac == 10 || mesac == 12 ) {
          den = 1;            // Устанавливаем первое число
          // если текущий месяц - Декабрь
          if (mesac == 12) {
            mesac = 1;            // Переводим месяц на Январь
            god++;                // Переводим на следующий год
          } else{
            mesac++;              // Переводим месяц
          }
          key = 0;                // Устанавливаем флаг перевода дня
        }
      }
// если флаг перевода дня равен 1
      if (key == 1 ) {
        den++;            // Добавляем день
      } else {            // иначе если был установлен флаг перевода дня, день не добавляется
        key = 1;          // и сбрасывается флаг перевода дня
      }

    }

lcd();  // Вывод информации на дисплей

  } // конец опроса

} // конец цикла

 

void lcd(){
//вывод символов на дисплей//

 

// Установка большого шрифта
    myOLED.setFont(MegaNumbers);
// отображение часов
    if (chas < 10) {                      // если число меньше 10
      myOLED.print("0", 4, 12);           // первый знак будет 0 (01)
      myOLED.print(String(chas), 27, 12);
    }
    else {
      myOLED.print(String(chas), 4, 12);
    }
// Отображение Двоеточия
    if (ledState == LOW) {          // мигаем двоеточием
      ledState = HIGH;              // Переключаем порт
      myOLED.print("/", 51, 12);    // Выводим ":"
    }else{
      ledState = LOW;              // Переключаем порт
      myOLED.print("-", 51, 12);    // Выводим " "
    }

// Отображение минут
    if (minut < 10) {                      // если число меньше 10
      myOLED.print("0", 75, 12);           // первый знак будет 0 (01)
      myOLED.print(String(minut), 100, 12);
    }else {
      myOLED.print(String(minut), 75, 12);
    }


// Отображение секунд
// Установка маленького шрифта
    myOLED.setFont(SmallFont);
    myOLED.print(":", 110, 5);            // Выводим ":"
    if (sek < 10) {                       // если число меньше 10
      myOLED.print("0", 115, 5);          // первый знак будет 0 (01)
      myOLED.print(String(sek), 121, 5);
    }else {
      myOLED.print(String(sek), 115, 5);
    }

 

// Отображение дня
    if (den < 10) {                       // если число меньше 10
      myOLED.print("0", 10, 55);          // первый знак будет 0 (01)
      myOLED.print(String(den), 16, 55);
    }else {
      myOLED.print(String(den), 10, 55);
    }


// Отображение месяца
    myOLED.print(".", 22, 55);              // Выводим "."
    if (mesac < 10) {                       // если число меньше 10
      myOLED.print("0", 28, 55);            // первый знак будет 0 (01)
      myOLED.print(String(mesac), 34, 55);
    }else {
      myOLED.print(String(mesac), 28, 55);
    }

    myOLED.print(".", 40, 55);              // Выводим "."
// Отображение года
    myOLED.print(String(god), 46, 55);

// Отображение дня недели
    myOLED.setFont(RusFont);
    switch (nedela)
    {
      case 1:     myOLED.print("GJYTLTKMYBR", CENTER, 0);    break;   //Понедельник
      case 2:     myOLED.print("  DNJHYBR  ", CENTER, 0);    break;   //Вторник
      case 3:     myOLED.print("   CHTLF   ", CENTER, 0);    break;   //Среда
      case 4:     myOLED.print("  XTNDTHU  ", CENTER, 0);    break;   //Четверг
      case 5:     myOLED.print("  GZNYBWF  ", CENTER, 0);    break;   //Пятница
      case 6:     myOLED.print("  CE<<JNF  ", CENTER, 0);    break;   //Суббота
      case 7:     myOLED.print("DJCRHTCTYMT", CENTER, 0);    break;   //Воскресенье
    }
// Обновление дисплея
    myOLED.update();

}

Категория: Электроника | Просмотров: 4288 | Добавил: graftsv | Теги: Ардуино, OLED, часы
Всего комментариев: 10
avatar
0
1
Такая ошибка при компиляции
sketch_jul27a.cpp.o: In function `lcd()':
C:\Users\User\РАДИО\6.ПРОГРАММИРОВАНИЕ\Arduino\arduino-1.0.6/sketch_jul27a.ino:117: undefined reference to `MegaNumbers'
C:\Users\User\РАДИО\6.ПРОГРАММИРОВАНИЕ\Arduino\arduino-1.0.6/sketch_jul27a.ino:117: undefined reference to `MegaNumbers'
C:\Users\User\РАДИО\6.ПРОГРАММИРОВАНИЕ\Arduino\arduino-1.0.6/sketch_jul27a.ino:173: undefined reference to `RusFont'
C:\Users\User\РАДИО\6.ПРОГРАММИРОВАНИЕ\Arduino\arduino-1.0.6/sketch_jul27a.ino:173: undefined reference to `RusFont'
avatar
0
2
Русские буквы в пути. Желательно что-то типа C:\Users\Graft\Documents\Arduino\
avatar
0
3
Скетч не компилируется- ошибка в последней строке
avatar
0
4
Проверьте всё ли правильно скопировали.
avatar
0
5
Сильно не пинайте-я начинающий,изменил имена папок и всё пошло(компиляция)
Но часики молчат,потом разобрался у меня модуль 7пин.
Может поможете с программкой под мой модуль OLED?
avatar
0
6
Для начала нужно выяснить какой дисплей и найти соответствующую библиотеку
avatar
0
7
Дисплейчик SPI.
Решение нашел здесь- http://arduino.ru/forum/apparatnye-voprosy/ne-mogu-podklyuchit-displei-oled-128x64-po-iic
avatar
0
8
Поздравляю!
avatar
0
9
Не поможете к Вашему скетчу прикрутить термометр вот отсюда - https://geektimes.ru/post/255556/
Вроде все библиотеки установил ,а кусок с ds18d20 не могу правильно воткнуть.
avatar
0
10
Там очень подробно всё описано. А так как вариант создать процедуру в которой будет считываться информация с датчика DS18B20 и вывод инфы на дисплей, а в в основном цикле loop прописать
if (x >= 30) {
DS18B20();
x=0;
} else {
lcd();

}
x++;

Только стоит не забывать, данный код часов работает в основном цикле, без использования прерываний, и на время чтения и вывода данных с DS18B20 будут задержки в отсчёте времени. В таком случае лучше использовать как в той статье часовой модуль DS1307.
avatar