Синхронизация RTC с помощью GPS. Помогите разобраться

Скетч работает пока модуль GPS подключён, при отключении GPS-модуля индикация на LCD 1602 останавливается. Больно не бейте, я очень старый новичок!

// Быстрое автоматическое обновление времени RTC DS1307 с помощью GPS.

#include <TinyGPS++.h>       // Библиотека GPS
#include <Wire.h>            // Библиотека интерфейса I2C
#include <SoftwareSerial.h>  // Библитоека последовательного порта
#include <TimeLib.h>         // Библиотека времени

#include <LiquidCrystal.h>
#include "RTClib.h"

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // (rs, e, d4, d5, d6, d7)

#define DS1307_I2C_ADDRESS 0x68  // Подключение I2C
#define GPSBAUD 9600             // GPS Скорость передачи данных I2C.
#define Rx 10                    // SoftwareSerial Rx pin
#define Tx 3                     // SoftwareSerial Tx pin
#define TIMEZONE 3               // UTC Смещение 3 часа для Москвы.

SoftwareSerial gpss(Rx, Tx);     // Подключение GPS 
TinyGPSPlus gps;
int gpsChkSum, rtcChkSum;        // контрольные суммы GPS и RTC
uint32_t timerUpd;               // таймер Upd. Интервал цикла обновления

// Время RTC
byte _second, _minute, _hour, dayOfWeek, dayOfMonth, _month, _year;

// Преобразование десятичных чисел в двоично-десятичные
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
// Преобразование двоично-десятичных чисел в десятичные
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

void setup() 
{
  Wire.begin();
  Serial.begin(9600);
  lcd.begin(16,2);
  gpss.begin(GPSBAUD);
  updateRTC();                   // Сбор данных, обновление RTS.
}

void loop() 
{
 displayTime();
  if (millis() - timerUpd >=15000)   // Задаём интервал синхронизации
  {
    timerUpd = millis();             // Сброс таймера Upd
    updateRTC();                     // Сбор данных, обновление RTS.

    if (rtcChkSum == gpsChkSum)      // Если контрольные суммы равны
    {
      Serial.println("Выполнено!");  // Выполнено!
      Serial.println();              // Перевод каретки
    }
  }
  if (rtcChkSum != gpsChkSum)
  {
    Serial.println("Контрольные сумммы различны. Время не правильно"); 
    updateRTC();
  }
}

void updateRTC() 
{
  unsigned long timer;  // Неопределённый таймер.
  bool updated = 0;     // Выполняем, пока флаг
  Serial.println();
  Serial.println("Ждём данные GPS");
  Serial.println("...");
  do // Выполнять действия с GPS до тех пор, пока не будет достигнут результат.
  { 
    while (gpss.available() > 0) // пока данные GPS доступны
      gps.encode(gpss.read());   // Читаем данные GPS
    // Если и время, и дата GPS готовы, обновляем их.
    if (gps.time.isUpdated() && gps.date.isUpdated()) 
    {  
      byte Year = gps.date.year();
      byte Month = gps.date.month();
      byte Day = gps.date.day();
      byte Hour = gps.time.hour();
      byte Minute = gps.time.minute();
      byte Second = gps.time.second();
      setTime(Hour, Minute, Second, Day, Month, Year);
      adjustTime(TIMEZONE * SECS_PER_HOUR);   // Устанавливаем время в назначенный часовой пояс
    
      // Установка времени RTC по GPS.
      if (1 && gps.satellites.value()>0)      // Ввод условий if для подтверждения обновления.
      {
        Wire.beginTransmission(DS1307_I2C_ADDRESS);
        Wire.write(0);                        // установить начинало с секундного регистра
        Wire.write(decToBcd(second()));       // Установка секунд
        Wire.write(decToBcd(minute()));       // Установка минут
        Wire.write(decToBcd(hour()));         // Установка часов
        Wire.write(decToBcd(weekday()));      // Установка дня недели (1=Воскресенье, 7=Суббота)
        Wire.write(decToBcd(day()));          // Установка числа месяца (1...31)
        Wire.write(decToBcd(month()));        // Учтановка месяца
        Wire.write(decToBcd(year() - 2000));  // 2000 Доавка двух первых цифр года для RTC. 
        Wire.endTransmission();               // Конец обновления 
        Serial.println();                     // Перевод каретки
        Serial.println ("RTC Обновлены!");    // Выводим информацию об успешном обновлении
      }
      updated = 1;  // флаг обновления true, прерываем цикл
    
      // Показываем время GPS
      Serial.print("Время GPS:  ");    // Выводим в порт: GPS TIME:
      if (hour() < 10)                 // Если часов меньше 10
      {
        Serial.print("0");             // выводим 0
      }
      Serial.print(hour());            // Выводим часы
      Serial.print(":");               // Выводим двоеточие
      if (minute() < 10)               // Если часов меньше 10
      {
        Serial.print("0");             // выводим 0
      }
      Serial.print(minute());          // Выводим минуты
      Serial.print(":");               // Выводим двоеточие
      if (second() < 10)               // Если минут меньше 10
      {
        Serial.print("0");             // выводим 0
      }
      Serial.print(second());          // Выводим секунды
      Serial.print(" ");               // Выводим данные
	  if (day() < 10)                  // Если часов меньше 10
      {
        Serial.print("0");             // выводим 0
      }
      Serial.print(day());             // Выводим день
      Serial.print("/");               // Выводим черту
	  if (month() < 10)                // Если часов меньше 10
      {
        Serial.print("0");             // выводим 0
      }
      Serial.print(month());           // Выводим месяц
      Serial.print("/");               // Выводим черту
      Serial.print(year());            // Выводим год
      Serial.print(" День недели: ");  // Выводим день Day of week:
      Serial.print(weekday());         // Выводим день недели - число
      Serial.print(" ");               // Выводим день недели
      switch (weekday()) 
      {
        case 1:
          Serial.println("Воскрксенье");
          break;
        case 2:
          Serial.println("Понедельник");
          break;
        case 3:
          Serial.println("Втрник");
          break;
        case 4:
          Serial.println("Среда");
          break;
        case 5:
          Serial.println("Четверг");
          break;
        case 6:
          Serial.println("Пятница");
          break;
        case 7:
          Serial.println("Суббота");
          break;
      }
    
      // Извлечение обновленного времени RTC.
      readDS1307time(&_second, &_minute, &_hour, &dayOfWeek, &dayOfMonth, &_month, &_year);
    
      // Генерация контрольной суммы.
      rtcChkSum = _second + _minute + _hour + dayOfWeek + dayOfMonth + _month + _year;
      gpsChkSum = second() + minute() + hour() + weekday() + day() + month() + year() - 2000;
    
      // Извлечение времени RTC.
      Serial.print("Время RTC:  ");
	  if (_hour < 10)
      {
        Serial.print("0");
      }
      Serial.print(_hour, DEC);
      Serial.print(":");
      if (_minute < 10)
      {
        Serial.print("0");
      }
      Serial.print(_minute, DEC);
      Serial.print(":");
      if (_second < 10)
      {
        Serial.print("0");
      }
      Serial.print(_second, DEC);
      Serial.print(" ");
      if (dayOfMonth < 10)
      {
        Serial.print("0");
      }
      Serial.print(dayOfMonth, DEC);
      Serial.print("/");
      if (_month < 10)
      {
        Serial.print("0");
      }
      Serial.print(_month, DEC);
      Serial.print("/");
      Serial.print(_year + 2000, DEC);
      Serial.print(" День недели: ");
      Serial.print(dayOfWeek);
      Serial.print(" ");
      switch (dayOfWeek) 
      {
        case 1:
          Serial.println("Воскрксенье");
          break;
        case 2:
          Serial.println("Понедельник");
          break;
        case 3:
          Serial.println("Втрник");
          break;
        case 4:
          Serial.println("Среда");
          break;
        case 5:
          Serial.println("Четверг");
          break;
        case 6:
          Serial.println("Пятница");
          break;
        case 7:
          Serial.println("Суббота");
          break;
      }
      Serial.print("Контрольные суммы:  GPS: ");  // Контрольная сумма GPS-данных
      Serial.print(gpsChkSum);                    // Контрольная сумма GPS-данных
      Serial.print("  RTC: ");                    // Контрольная сумма RTS-данных
      Serial.println(rtcChkSum);                  // Контрольная сумма RTS-данных
      Serial.print("Спутников: ");                // Вывод данных о количестве спутников
      Serial.println(gps.satellites.value());     // Вывод данных о количестве спутников
    }
  }
  while (!updated);
}

//Получаем время от RTC
void readDS1307time(byte * _second,
                    byte * _minute,
                    byte * _hour,
                    byte * dayOfWeek,
                    byte * dayOfMonth,
                    byte * _month,
                    byte * _year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);  // установка указателя регистра DS1307 в 00h
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// Запрос семи байт данных из DS1307, начиная с регистра 00h
  *_second = bcdToDec(Wire.read() & 0x7f);
  *_minute = bcdToDec(Wire.read());
  *_hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *_month = bcdToDec(Wire.read());
  *_year = bcdToDec(Wire.read());
}

void displayTime()
{
  readDS1307time(&_second, &_minute, &_hour, &dayOfWeek, &dayOfMonth, &_month, &_year);
  lcd.setCursor(0,0);
  lcd.print("Time: ");
  if (_hour < 10)
  {
    lcd.print("0");
  }
  lcd.print(_hour, DEC);
  lcd.print(':');
  if (_minute < 10)
  {
    lcd.print("0");
  }
  lcd.print(_minute, DEC);
  lcd.print(':');
  if (_second < 10)
  {
    lcd.print("0");
  }
  lcd.print(_second, DEC);
  lcd.print(" ");
  lcd.print(dayOfWeek, DEC);
  lcd.setCursor(0,1);
  lcd.print("Date: ");
    if (dayOfMonth < 10)
  {
    lcd.print("0");
  }
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");
    if (_month < 10)
  {
    lcd.print("0");
  }
  lcd.print(_month, DEC);
  lcd.print("/");
  lcd.print(_year +2000, DEC);
}

Измени логику и все «взлетит» (ну то есть будет работать как тебе хочется).

Здесь посмотрите

Спасибо!

Не мгу понять, как while (!updated); наодящаяся в void updateRTC() мешает выполнению void displayTime().

Если uppdated = 0 это выражение становится равным выражению while(1);
со всеми вытекающими

бесконечный цикл получается

Сделал вот так: включил displayTime() в цикл и всё заработало!

‘’’ }
displayTime();
}
while (!updated);
}‘’’

Ущё раз спасибо за наводку. Вопрос решён.

Похоже, вы так и не поняли, что происходит в строке

можно то же самое так записать:

Естественно в свои 78 я не совсем всё понимаю, но я стараюсь.

Можете на досуге запустить скетч и посмотреть, как это работает

Спойлер

byte count = 0;

void setup() {
 Serial.begin(9600);
}

void loop() {
 
 while(count == 4);
 Serial.println(count);
 count = count + 1;

}

У меня хорошо работает. Сбрасываю время RTC, зпускаю макет - ждёт подключения GPS, после подключения ждёт связь со спутниками. Как находит - синхронизирует время.

Это пока вы функционал не надумаете расширить. И тогда окажется, что пока нет подключения GPS, у вас ничего не работает, т.к. функция void updateRTC() не отдает управления и крутится в бесконечном цикле ))

Это я понял. Мне главное - понять и добиться. А вот теперь буду уходить от do while

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

Поймите другое - то что вы написали в сообщении 9 - вовсе не решение.

Всё понимаю. Это мой всего второй проект и сделан всего второй шаг, а будут 3, 4 и тд - сколько успею…

Все у вас правильно написано. Димыч просто не заметил do {} while(!updated);

1 лайк

До чего?

Смотри пост 9