bigboystoys13
Published

Simple clock with RGB indicator set using GPS

This project started with an idea of making a simple clock for a child that just wants to know "should I get up yet".

BeginnerFull instructions provided1 hour161
Simple clock with RGB indicator set using GPS

Things used in this project

Hardware components

Spresense boards (main & extension)
Sony Spresense boards (main & extension)
Main board and extension board, provided as part of the "Spresense Developer Challenge 2022".
×1
Grove-LCD RGB Backlight
×1
Cables -Grove 4 pin Male Jumper to Grove 4 pin Conversion Cable
×1
Generic USB to MicroUSB cable
×1

Story

Read more

Schematics

Wiring diagram

Shows how to wire up the board. The Grove board has a special connector which is why you need a cable that goes from Grove to regular male pins that can plug into the Spresence board headers.

Code

Arduino Code

Arduino
Arduino Code for my project. You may need to install libraries for the following products:

- Spresense Main Board
- Grove-LCD RGB Backlight
/*
   This code supports the key high level functions:
       - Set RTC using GNSS/GPS
       - Sent time / status updates via serial port
       - Display time on external RGB display

   The following example code was using in this project:
   Example > Spresense > RTC > rtc_gnss: Starting point for code.
   Example > Spresense > GNSS > gnss: For reference/code review.
   Example > Grove - LCD RGB Backlight > HelloWorld: Copied some parts of code as starting point for display.

    This code is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    V3 = Grove-LCD RGB
    Last revised: 21 July 2022
*/

// From rtc_gnss
#include <RTC.h>
#include <GNSS.h>

// From RGB-LCD
#include "rgb_lcd.h"

rgb_lcd lcd;
SpGnss Gnss;

#define MY_TIMEZONE -4 // EST

void setup()
{
  // Turn all LEDs on then off
      ledOn(PIN_LED0);
      ledOn(PIN_LED1);
      ledOn(PIN_LED2);
      ledOn(PIN_LED3);
delay(500);
      ledOff(PIN_LED0);
      ledOff(PIN_LED1);
      ledOff(PIN_LED2);
      ledOff(PIN_LED3);

  //Init Grove-LCD
  lcd.begin(16, 2);


  updateLCD("Wait on serial");
  Serial.begin(115200);
  while (!Serial);

  Serial.println("Simple Clock: RTC set by GPS");
  updateLCD("Simple Clock");
  delay(2000);

  // Initialize RTC at first
  RTC.begin();
  updateLCD("RTC: Started");

  // Initialize and start GNSS library
  int ret;
  ret = Gnss.begin();
  assert(ret == 0);

  ret = Gnss.start();
  assert(ret == 0);

  updateLCD("GPS: Started");
}

void loop()
{
  // Wait for GNSS data
  if (Gnss.waitUpdate()) {
    SpNavData  NavData;

    // Get the UTC time
    Gnss.getNavData(&NavData);
    SpGnssTime *time = &NavData.time;

    printf("GPS: %04d/%02d/%02d %02d:%02d:%02d\n",
           time->year, time->month, time->day,
           time->hour, time->minute, time->sec);

    // Check if the acquired UTC time is accurate
    if (time->year >= 2000) {
      RtcTime now = RTC.getTime();
      // Convert SpGnssTime to RtcTime
      RtcTime gps(time->year, time->month, time->day,
                  time->hour, time->minute, time->sec, time->usec * 1000);
                  
#ifdef MY_TIMEZONE
      // Set the time difference
      gps += (MY_TIMEZONE * 60 * 60);
#endif

      int diff = now - gps;
      if (abs(diff) >= 1) {
        RTC.setTime(gps);
       Serial.println("RTC set to GPS");
      }
    }
  }

  // Display the current time every a second
  updateClock();
}

void updateClock()
{
  static RtcTime old;
  RtcTime now = RTC.getTime();

  // Display only when the second is updated
  if (now != old) {
    printClock(now);
    old = now;
  }
}

void printClock(RtcTime &rtc)
{
  printf("RTC: %04d/%02d/%02d %02d:%02d:%02d\n",
         rtc.year(), rtc.month(), rtc.day(),
         rtc.hour(), rtc.minute(), rtc.second());

  // Print to OLED
#define STRING_BUFFER_SIZE  128
  char StringBuffer[STRING_BUFFER_SIZE];

  lcd.clear();

  //Date MM/DD/YYYY format
  snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d/%02d/%04d",
           rtc.month(), rtc.day(), rtc.year());

  lcd.setCursor(0, 0);

  if (rtc.year() > 2000) {
    lcd.print(StringBuffer);
  } else {

    // lcd.print(StringBuffer);
    lcd.print("Waiting on GPS");
  }

  //Time

  // Display AM/PM instead of 24 hour
 int var2 = rtc.hour();
  switch (var2) {
    case 0:
      snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d AM",   
               rtc.hour()+12, rtc.minute(), rtc.second());
             break; 
    case 1 ... 11:
      snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d AM",   
               rtc.hour(), rtc.minute(), rtc.second());

      break;
    case 12:
      snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d PM",    
               rtc.hour(), rtc.minute(), rtc.second());

      break;
    case 13 ... 23:
      snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d PM",    
               rtc.hour() - 12, rtc.minute(), rtc.second());

      break;

    default:
      // if nothing else matches, do the default
      // default is optional

      break;
  }

  lcd.setCursor(0, 1);
  lcd.print(StringBuffer);


  // This code changes the RGB backlight based on the hour.
  int var = rtc.hour();
  switch (var) {
    case 0 ... 6:
      lcd.setRGB(255, 0, 0); //RED
      break;
    case 7 ... 8:
      lcd.setRGB(255, 255, 0); //YELLOW
      break;
    case 9 ... 21:
      lcd.setRGB(0, 255, 0); //GREEN
      break;
    case 22:
      lcd.setRGB(255, 255, 0); //YELLOW
      break;
    case 23:
      lcd.setRGB(255, 0, 0); //RED
      break;
    default:
      // if nothing else matches, do the default
      // default is optional
      break;
  }
}

void updateLCD(char *message)
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(message);
}

Credits

bigboystoys13

bigboystoys13

11 projects • 46 followers
Thanks to Spresense and Grove and My child.

Comments