Задумал я собрать часы, которые не нуждались бы в настройке (подводке). Было два варианта реализации с помощью модуля часов DS3231 и с помощью GPS модуля VK2828U7G5LF. Был ещё вариант использовать оба модуля, но это показалось мне излишним. В общем остановился на GPS модуле.

Основное окно

Второе окно

Далее представлен код для ардуино с пояснениями.

Имя  
Эл. почта  
Сообщение  
  
#include <TinyGPS++.h> // Инициируем GPS
TinyGPSPlus gps;

#include <LiquidCrystal_1602_RUS.h> // Инициируем монитор
LiquidCrystal_1602_RUS lcd(7, 5, 6, 8, 9, 10); //Порты для дисплея

#include <bigNumbers.h>   // Инициируем библиотеку отоброжения больших цифер
bigNumbers <LiquidCrystal> bigNumbersLcd(&lcd);


#include <SoftwareSerial.h>

SoftwareSerial ss(4, 3); // Порты GPS RX 4; TX 3
int knop = 13;           // Пин подключения кнопки переключения экрана
int hour;                // Переменная час
int minute;              // Переменная минуты
int day;                 // Переменная день
int month;               // Переменная месяц
int GMT = 11;            // часовой пояс по Гринвичу (установить какой надо) 
int altitude;            // Переменная высота


byte customChar[8] = {          // Создаём элемент Двоеточие (одна точка)
  B00000,
  B00000,
  B00000,
  B00000,
  B01110,
  B01110,
  B01110,
  B00000
};

byte customChar1[8] = {          // Создаём элемент Двоеточие (вторая точка)
  B00000,
  B01110,
  B01110,
  B01110,
  B00000,
  B00000,
  B00000,
  B00000
};

void setup() {

 lcd.createChar(11, customChar);   // Создаём симвло Двоеточие верхняя точка
 lcd.createChar(12, customChar1);  // Создаём симвло Двоеточие нижняя точка

 pinMode(knop, INPUT);             // Настраиваем порт кнопки на вход
  
 Serial.begin(115200);      // Запуск последовательного интерфейса
 lcd.begin(20,4);           // Дисплей 20 символов 4 строки

 bigNumbersLcd.intNumbers(); // Подключаем отоброжение больших цифер 
 
 ss.begin(9600);  // Скорость соеденения с GPS
 Serial.print(F("Biblioteca TinyGPS++ v. "));
 Serial.println(TinyGPSPlus::libraryVersion()); // Выводим версию библиотеки в последовательный порт.
 Serial.println();  
}

void loop() {
  
  while (ss.available() > 0)
  (gps.encode(ss.read()));      // читаем данные с GPS
  
  if (gps.time.isUpdated())     // проверяем данные времени на изменение
  {
  hour = gps.time.hour() + GMT; // читаем в переменную данные о часе + поправка на пояс.
  minute = gps.time.minute();   // читаем в переменную данные о минутах
  day = gps.date.day();         // читаем в переменную данные о дне  
  if (hour > 23) day = day +1;       // поправки связанные с применением часового пояса
  if (hour > 23) hour = hour - 24; 
  }  
  if (gps.altitude.isUpdated())   // проверяем данные высоты на изменение
   { 
    altitude = gps.altitude.meters(); // читаем в переменную данные о Высоте
   }

  if (gps.date.isValid())            // проверяем данные даты на изменение
  { 
    month = gps.date.month();        // читаем данные месяц   
  }
   
  if(digitalRead(knop) == HIGH) {  // Кнопка не нажата
    

    // Выводим время и дату   
  // Отоброжение на экране LCD значения час (большими цифрами)
  if (hour <= 9) 
    { 
     bigNumbersLcd.printNumber(0, 1);      // устанавливаем 0 для корректности отоброжения
     bigNumbersLcd.printNumber(hour, 5);   // Отоброжаем значение час от 0 до 9 
    }
  if (hour > 9 &  hour <= 19)
    {
     bigNumbersLcd.printNumber(1, 1);
     bigNumbersLcd.printNumber((hour-10), 5);  // Отоброжаем значение час от 10 до 19 
    }
  if (hour > 19 &  hour <= 23)
    {
     bigNumbersLcd.printNumber(2, 1);
     bigNumbersLcd.printNumber((hour-20), 5);  // Отоброжаем значение час от 20 до 23 
    }

  // Отоброжваем двоеточие 
    lcd.setCursor(9,0);                    // Установка курсора в 9 позицию 1 строки
    lcd.write((uint8_t)11);                // Отоброжаем верхнюю точку Двоеточия
    lcd.setCursor(9,1);
    lcd.write((uint8_t)12);                // Отоброжаем нижнюю точку Двоеточия
    
  // Отоброжаем Минуты (большими цифрами)
  if (minute <= 9)
    {
     bigNumbersLcd.printNumber(0, 11);       // устанавливаем 0 для корректности отоброжения
     bigNumbersLcd.printNumber(minute, 15);  // Отоброжаем значение минут от 0 до 9
    }
  if (minute > 9 & minute <= 19)
    {
     bigNumbersLcd.printNumber(1, 11);
     bigNumbersLcd.printNumber((minute-10), 15);  // Отоброжаем значение минут от 10 до 19 
    }
  if (minute > 19 & minute <= 29)
    {
     bigNumbersLcd.printNumber(2, 11);
     bigNumbersLcd.printNumber((minute-20), 15);  // Отоброжаем значение минут от 20 до 29 
    }
  if (minute > 29 & minute <= 39)
    {
     bigNumbersLcd.printNumber(3, 11);
     bigNumbersLcd.printNumber((minute-30), 15);  // Отоброжаем значение минут от 30 до 39  
    }
  if (minute > 39 & minute <= 49)
    {
     bigNumbersLcd.printNumber(4, 11);
     bigNumbersLcd.printNumber((minute-40), 15);  // Отоброжаем значение минут от 40 до 49  
    }
  if (minute > 49 & minute <= 59)
    {
     bigNumbersLcd.printNumber(5, 11);
     bigNumbersLcd.printNumber((minute-50), 15);  // Отоброжаем значение минут от 50 до 59  
    }

 // Отображение на LCD даты, месяца и года
    lcd.setCursor(5,3);                   //Установка курсора в 5 позицию 2 строки
    if (day <= 9)lcd.print("0");          // устанавливаем 0 для корректности отоброжения
    lcd.print(day);lcd.print(F("/"));     // Отоброжение на экране LCD данных день 
    if (month <= 9)lcd.print("0");        // устанавливаем 0 для корректности отоброжения
    lcd.print(month);lcd.print(F("/"));   // Отоброжение на экране LCD данных месяц
    lcd.print(gps.date.year());           // Отоброжение на экране LCD данных год
          
  }else{                                  // Когда кнопка нажата

    // Выводим высоту и координаты
 
    lcd.setCursor(0,0);                   //Установка курсора в начало 1 строки
    lcd.print("Altitude = "); lcd.print(altitude); lcd.print(" m ");     
    lcd.setCursor(0,2);                          //Установка курсора в начало 3 строки
    lcd.print("LAT = "); lcd.print(gps.location.lat(), 6);   // отоброжаем широту
    lcd.setCursor(0,3);                          //Установка курсора в начало 4 строки
    lcd.print("LNG = "); lcd.print(gps.location.lng(), 6);   // отоброжаем долготу   
    delay(5000); 
    lcd.clear(); //Очистка памяти диспея
   }
  
    // Отоброжаем данные в монтторе порта

     Serial.print(F(" "));
     Serial.println(F("================================"));
     Serial.print(F(" "));
     Serial.print(hour);
     Serial.print(F(":"));
     Serial.print(minute); //mes
     Serial.println(F("   "));
     Serial.print(day); 
     Serial.print(F("/"));
     Serial.print(month); 
     Serial.print(F("/"));
     Serial.println(gps.date.year());       
     Serial.print("Высота = "); Serial.print(altitude); Serial.println(" м ");
     Serial.print("Широта = "); Serial.println(gps.location.lat(), 6);
     Serial.print("Долгота = "); Serial.println(gps.location.lng(), 6);
 
     //delay(500); 
   }

 Архивы со скетчем, библиотеками, схемой и STL файлами для печати корпусов устройства можно - скачать с яндекса.

Напишите отзыв.

Схема работы в принципе проста. GPS модуль принимает с низкоорбитальных спутников (четырёх и более) данные из которых вычисляет свое местоположение. Также с этих данных берётся точное время, дата и другие параметры.

Ардуино считывает необходимые данные с GPS модуля и выводит на четырёхстрочный LCD экран. Для лучшего восприятия цифры отображающие время сделаны высотой в две строчки, для этого используется библиотека bigNumbers.h. Данная библиотека может выводить цифры от 0 до 9. Для работы с модулем GPS используется библиотека TinyGPS++.h. Библиотека SoftwareSerial.h также необходима для связи с модулем GPS. 

       Для LCD экрана используется библиотека  LiquidCrystal_1602_RUS.h  (с поддержкой русского языка – если кто захочет сделать русские надписи на экране вместо а’нглцких). Подключение модуля GPS осуществляется по четырём проводам (VCC, TX, RX, GND), провода 1PPS и EN не используются (хотя 1PPS можно использовать для синхронизации устройств – это так, небольшое отступление).

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

Схема устройства изображена на следующем рисунке.

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

В схему был добавлен датчик KY-018 (фоторезистор), Датчик выводится на освещённую часть корпуса, через просверленное в корпусе отверстие.  Модернизированная схема приведена ниже.

В скетч было добавлено несколько строк.

В переменные добавлено:

int photoresistorPin = A1;     // выбор          //вх.пина для фоторезистора

int ledPin = 12;           // выбор пина            // для регулятора подсветки

int photoresistorValue = 0;                         // переменная для значения                // принятого от датчика

В void setup() добавлена строка:

pinMode(ledPin, OUTPUT);

В void loop() добавлены строки:

pinMode(ledPin, OUTPUT);

В void loop() добавлены строки:

photoresistorValue = analogRead(photoresistorPin);

if (photoresistorValue >= 512) digitalWrite(ledPin, HIGH); // значение   // надо подбирать в зависимости

 // от освещения

else digitalWrite(ledPin, LOW);

   С помощью переменных резисторов «Яркость дисплея день» и «Яркость дисплея ночь», устанавливаем необходимое свечение экрана - соответственно при освещённом датчике и затемнённом.

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

Часы с GPS модулем и LCD экраном на Ардуино.