SparkFun Forums 

Where electronics enthusiasts find answers.

General project discussion / help
Did you make a robotic coffee pot which implements HTCPCP and decafs unauthorized users? Show it off here!
By ryemac3
#165221
I'm making a clock that is pulling the time in via Adafruit's Ultimate GPS module. It pulls in the time, then uses that to update a DS3231 RTC. I am using an Arduino Mega 2650. My code is based off Adafruit's Echo and Parsing sketches.

Image

Here's the problem: I'm also controlling the clock via an IR Remote. I'm using SparkFun's IR remote and SEN-08554 Receiver, along with the sketch and library by Ken Shirriff that they link to:
https://www.sparkfun.com/products/11759
https://www.sparkfun.com/products/8554

The clock has an alarm menu and a settings menu that I can bring up with the remote. I can then use the remote to set options like daylight savings, time zone, turn alarm on/off, etc.

The IR stuff works flawlessly on the Mega. The GPS stuff works flawlessly on the Mega. However, they do not work very well when both in the same sketch. Sometimes I have to press a button on my remote up to 10 times before it's picked up. Most of the time, it doesn't pick it up at all.

Any pointers with the GPS library or the IR sketch based off Ken Shirriff's code that causes some kind of complication when used together would be appreciated. Is there some kind of consideration I've missed? I even changed the GPS breakout to use another TX/RX (pins 18/19) (hardware) and the IR receiver to use TIMER5 (pin 46) per the library. Still no luck. I thought by using hardware serial instead of software serial, I'd eliminate any problems communicating with both devices.

Here's my code:
Code: Select all
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include "DS3231.h"
#include <Wire.h>
#include <glcd.h>
#include <fonts/SystemFont5x7.h>
#include <fonts/Arial14.h>             
#include <fonts/Arial_bold_14.h>       
#include <fonts/fixednums7x15.h>       
#include <fonts/fixednums8x16.h>
#include <fonts/fixednums15x31.h>
#include <IRremote.h>

DS3231 RTC; //Create the DS3231 object

// If you're using a GPS module:
// Connect the GPS Power pin to 5V
// Connect the GPS Ground pin to ground
// If using software serial (sketch example default):
//   Connect the GPS TX (transmit) pin to Digital 3
//   Connect the GPS RX (receive) pin to Digital 2
// If using hardware serial (e.g. Arduino Mega):
//   Connect the GPS TX (transmit) pin to Arduino RX1, RX2 or RX3
//   Connect the GPS RX (receive) pin to matching TX1, TX2 or TX3

// If you're using the Adafruit GPS shield, change 
// SoftwareSerial mySerial(3, 2); -> SoftwareSerial mySerial(8, 7);
// and make sure the switch is set to SoftSerial

// If using software serial, keep these lines enabled
// (you can change the pin numbers to match your wiring):
//SoftwareSerial mySerial(10, 11);

//Adafruit_GPS GPS(&mySerial);
// If using hardware serial (e.g. Arduino Mega), comment
// out the above six lines and enable this line instead:
Adafruit_GPS GPS(&Serial1);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO  true

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

// Select the font for the default text area
/*
SystemFont5x7       // system font
 Arial14             // proportional font
 Arial_bold_14       // Bold proportional font
 fixednums7x15       // fixed width font - numerals only 
 fixednums8x16       // fixed width font - numerals only 
 fixednums15x31      // fixed width font - numerals only 
 */

//remote
int RECV_PIN = 46; //pin 9 is for the Mega per Timer2 in the IR library
IRrecv irrecv(RECV_PIN);
decode_results results;
#define POWER 0x10EFD827 
#define A 0x10EFF807 
#define B 0x10EF7887
#define C 0x10EF58A7
#define UP 0x10EFA05F
#define DOWN 0x10EF00FF
#define LEFT 0x10EF10EF
#define RIGHT 0x10EF807F
#define SELECT 0x10EF20DF

//temp
int tempC;
int tempF;

//initial condition for menu display
boolean enterNormalMode = true;
boolean enterSettingsMode = false;
boolean enterAlarmMode = false;
boolean chimeOnHour = false;
boolean alarmIsActive = false;

//settings menu
int settingsModeButtonCount;
boolean gmtSelected = false;
boolean dlsSelected = false;
boolean chimeSelected = false;

//alarm menu
int alarmModeButtonCount;
boolean aTimeSelected = false;
boolean activeSelected = false;

//compensations
int TZAdjust; 
int newHours;
int DaylightSavings;
boolean DLSinEffect = false;

//year, month, date, hour, min, sec and week-day(starts from 0 and goes to 6)
//writing any non-existent time-data may interfere with normal operation of the RTC.
//Take care of week-day also.
//DateTime dt(2013, 11, 2, 22, 03, 00, 6);
DateTime dt(2015, 8, 12, 4, 15, 30, 6);

int hhRTC;
int hhAdj;
int mmRTC;
int ssRTC;
int dayRTC;
int dowRTC;
int monthRTC;
int yearRTC;

int hhGPS;
int mmGPS;
int ssGPS;
int dayGPS;
int monthGPS;
int yearGPS;
int linkStatus;

void setup()  {
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
 // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time

  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  //GPS.sendCommand(PGCMD_ANTENNA);

  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!
  useInterrupt(true);

   delay(1000);
  // Ask for firmware version
  //mySerial.println(PMTK_Q_RELEASE);
  Serial.println(PMTK_Q_RELEASE);

// Initialize the GLCD 
  GLCD.Init();
  Wire.begin();
  RTC.begin();
  //remote
  irrecv.enableIRIn(); // Start the receiver
  
  //unhide to force time setting of the RTC
  // RTC.adjust(dt); //Adjust date-time as defined 'dt' above 
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = false;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()                    
{

  ////////////////////////////////////////////////////////////////////////////////
  //remote
  if (irrecv.decode(&results)) {
    if (results.value == POWER) 
    {
      Serial.println("POWER");  
      syncGPSTime();  
    }
    if (results.value == A) 
    {
      Serial.println("A");  
      enterNormalMode = true;
      enterSettingsMode = false;
      enterAlarmMode = false;
      GLCD.ClearScreen();
    }
    if (results.value == B) 
    {
      Serial.println("B"); 
      //enter menu in default state so no options are highlighted
      settingsModeButtonCount = 3; 

      enterNormalMode = false;
      enterSettingsMode = true;
      enterAlarmMode = false;
      GLCD.ClearScreen();
    }
    if (results.value == C) 
    {
      Serial.println("C");
      //enter menu in default state so no options are highlighted
      alarmModeButtonCount = 2;

      enterNormalMode = false;
      enterSettingsMode = false;
      enterAlarmMode = true;
      GLCD.ClearScreen();
    }
    if (results.value == UP) 
    {
      Serial.println("UP");
      if(enterSettingsMode == true) {
        settingsModeButtonCount++;

        if(settingsModeButtonCount == 4) { 
          settingsModeButtonCount = 0;
        }
      }
      if(enterAlarmMode == true) {
        alarmModeButtonCount++;

        if(alarmModeButtonCount == 3) {
          alarmModeButtonCount = 0;
        }
      }
    }
    if (results.value == DOWN) 
    {
      Serial.println("DOWN");
      if(enterSettingsMode == true) {
        settingsModeButtonCount--;

        if(settingsModeButtonCount < 0) {
          settingsModeButtonCount = 3;
        }
      }
      if(enterAlarmMode == true) {
        alarmModeButtonCount--;

        if(alarmModeButtonCount < 0) {
          alarmModeButtonCount = 2;
        }
      }
    }
    if (results.value == LEFT) 
    {
      Serial.println("LEFT");
      if(gmtSelected == true) {
        TZAdjust--;
        //time zone changed - resync with GPS clock
        syncGPSTime();
      }

      if(dlsSelected == true) {
        DLSinEffect = !DLSinEffect;
      }

      if(chimeSelected == true) {
        chimeOnHour = !chimeOnHour;

      }

      if(aTimeSelected == true) {

      }

      if(activeSelected == true) {
        alarmIsActive = !alarmIsActive;
      }
    }
    if (results.value == RIGHT) 
    {
      Serial.println("RIGHT");
      if(gmtSelected == true) {
        TZAdjust++;
        //time zone changed - resync with GPS clock
        syncGPSTime();
      }

      if(dlsSelected == true) {
        DLSinEffect = !DLSinEffect;
      }

      if(chimeSelected == true) {
        chimeOnHour = !chimeOnHour;
      }

      if(aTimeSelected == true) {

      }

      if(activeSelected == true) {
        alarmIsActive = !alarmIsActive;
      }
    }
    if (results.value == SELECT) 
    {
      Serial.println("SELECT");  
      //set totally wrong date and time (so that a GPS sync can be tested)
      DateTime dt(2011, 1, 1, 1, 1, 0, 6);
      RTC.adjust(dt); 
      delay(10);
      GLCD.ClearScreen();
    }
    irrecv.resume();
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  //GPS
  // in case you are not using the interrupt above, you'll
  // need to 'hand query' the GPS, not suggested :(
  if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) Serial.print(c);
  }
  
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
  }

  // if millis() or timer wraps around, we'll just reset it
  //if (timer > millis())  timer = millis();

  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 10000) { 
    timer = millis(); // reset the timer
    
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", "); 
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
  }
  
  //////////////////////////////////////////////////////////////
  //RTC
  DateTime now = RTC.now();
  tempC = RTC.getTemperature();
  tempF = (tempC * 9.0)/ 5.0 + 32.0; // Convert C to F

  hhRTC = now.hour(); //used to check AM/PM status
  mmRTC = now.minute();
  ssRTC = now.second(); 

  dowRTC = now.dayOfWeek();
  dayRTC = now.date();
  monthRTC = now.month();
  yearRTC = now.year();

  //pass RTC values into a new variable -
  //this way one variable stores time in 24 hour mode and another that can be converted to 12 hour mode
  //time is monitored 'in the background' in 24 hour mode using the RTC, but is displayed in an adjusted 12-hr format
  hhAdj = hhRTC;

//need to add compensation for the date so the date doesn't roll over 4 hours early
  
  //convert to 12 hr mode for display
  if (hhRTC < 1) {
    hhAdj = 12;
  }

  if ((hhRTC > 12) && (hhRTC < 24)) {
    hhAdj = hhRTC - 12;
  }
  
//DLS compensation
  if (DLSinEffect == false) {
    DaylightSavings = 0; //DSL not in effect, don't add an additional hour
  } 
  else {
    DaylightSavings = 1; //DSL in effect, add an additional hour
  }

   newHours = ((hhAdj) + TZAdjust + DaylightSavings);
  
  ////////////////////////////////////////////////////////////////////////////////
  //not in menu mode
  //time from RTC
  if (enterNormalMode == true) {
    //hour
    GLCD.SelectFont(fixednums15x31);
    GLCD.CursorTo(0,0);
    if (newHours < 10) {
      GLCD.print("0"); 
    } 
    GLCD.print(newHours);

    //minute
    if (mmRTC < 10) {
      GLCD.print(":0"); 
    } 
    else {
      GLCD.print(":");
    }
    GLCD.print(mmRTC);

    //second
    GLCD.SelectFont(fixednums7x15);
    if (ssRTC < 10) {
      GLCD.print(":0"); 
    } 
    else {
      GLCD.print(":");
    }
    GLCD.print(ssRTC);

    // AM/PM indicator
    GLCD.SelectFont(SystemFont5x7);
    if ((hhRTC > 12) && (hhRTC < 22)) {
      //PM
      GLCD.print(" PM");
    } 
    else {
      //AM
      GLCD.print(" AM"); 
    }

    //second line
    //date
    GLCD.CursorTo(0,4);
    GLCD.SelectFont(Arial14);
    switch(dowRTC){
    case 0: 
      GLCD.print("Sun  ");
      break;
    case 1: 
      GLCD.print("Mon  ");
      break;
    case 2: 
      GLCD.print("Tue  ");
      break;
    case 3: 
      GLCD.print("Wed  ");
      break;
    case 4: 
      GLCD.print("Thu  ");
      break;
    case 5: 
      GLCD.print("Fri  ");
      break;
    case 6: 
      GLCD.print("Sat  ");
      break;
    }

    GLCD.SelectFont(fixednums7x15);
    GLCD.print(monthRTC);
    GLCD.print("/");
    GLCD.print(dayRTC);
    GLCD.print("/");
    GLCD.print(yearRTC - 2000);

    //temp
    GLCD.SelectFont(SystemFont5x7);
    GLCD.print("  ");
    GLCD.SelectFont(fixednums8x16);
    GLCD.print(tempF);
    GLCD.SelectFont(SystemFont5x7);
    GLCD.print("F"); 

    //draw line
    GLCD.DrawLine(0,51,128,51,BLACK);

    //GPS status
    linkStatus = (GPS.fixquality);
    GLCD.SelectFont(SystemFont5x7);
    GLCD.CursorTo(0,7);

    if (linkStatus < 1) {
      GLCD.print("GPS:NO ");
    } 
    else {
      GLCD.print("GPS:YES");
    }

    //alarm
    GLCD.print("  ALARM:");
    if (alarmIsActive == true) {
      GLCD.print("6:30AM");
    } 
    else {
      GLCD.print("OFF");
    }
  }

  ////////////////////////////////////////////////////////////////////////////////
  //display settings menu
  if (enterSettingsMode == true) {
    GLCD.ClearScreen();

    //settings menu header
    GLCD.SelectFont(SystemFont5x7);
    GLCD.CursorTo(0,0);
    GLCD.print("     "); 
    GLCD.SelectFont(Arial_bold_14);
    GLCD.print("SETTINGS"); 
    //draw line
    GLCD.DrawLine(0,12,128,12,BLACK);

    if (settingsModeButtonCount == 3) { //no option highlighted
      gmtSelected = false;
      dlsSelected = false;
      chimeSelected = false;

      GLCD.SelectFont(Arial14);

      //time zone
      GLCD.CursorTo(0,1);
      GLCD.print("GMT:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      GLCD.print(TZAdjust); 

      //daylight savings 
      GLCD.CursorTo(0,2);
      GLCD.print("DLS:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (DLSinEffect == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }

      //chime on hour
      GLCD.CursorTo(0,3);
      GLCD.print("CHIME:");
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (chimeOnHour == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    if (settingsModeButtonCount == 2) { //GMT highlighted
      gmtSelected = true;
      dlsSelected = false;
      chimeSelected = false;
      GLCD.SelectFont(Arial_bold_14);

      //time zone
      GLCD.CursorTo(0,1);
      GLCD.print("GMT:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial_bold_14);
      GLCD.print(TZAdjust); 

      GLCD.SelectFont(Arial14);
      //daylight savings 
      GLCD.CursorTo(0,2);
      GLCD.print("DLS:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (DLSinEffect == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      } 

      //chime on hour
      GLCD.CursorTo(0,3);
      GLCD.print("CHIME:");
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (chimeOnHour == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    if (settingsModeButtonCount == 1) { //DLS highlighted
      gmtSelected = false;
      dlsSelected = true;
      chimeSelected = false;
      GLCD.SelectFont(Arial14);

      //time zone
      GLCD.CursorTo(0,1);
      GLCD.print("GMT:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      GLCD.print(TZAdjust); 

      GLCD.SelectFont(Arial_bold_14);
      //daylight savings 
      GLCD.CursorTo(0,2);
      GLCD.print("DLS:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial_bold_14);
      if (DLSinEffect == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }

      //chime on hour
      GLCD.SelectFont(Arial14);
      GLCD.CursorTo(0,3);
      GLCD.print("CHIME:");
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (chimeOnHour == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    if (settingsModeButtonCount == 0) { //CHIME highlighted
      gmtSelected = false;
      dlsSelected = false;
      chimeSelected = true;
      GLCD.SelectFont(Arial14);

      //time zone
      GLCD.CursorTo(0,1);
      GLCD.print("GMT:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      GLCD.print(TZAdjust); 

      //daylight savings 
      GLCD.CursorTo(0,2);
      GLCD.print("DLS:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (DLSinEffect == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }

      //chime on hour
      GLCD.SelectFont(Arial_bold_14);
      GLCD.CursorTo(0,3);
      GLCD.print("CHIME:");
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial_bold_14);
      if (chimeOnHour == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    //add delay to lower refresh rate on the display (remove blink)
    delay(200);
  }

  ////////////////////////////////////////////////////////////////////////////////
  //display alarm menu
  if (enterAlarmMode == true) {
    GLCD.ClearScreen();

    //settings menu header
    GLCD.SelectFont(SystemFont5x7);
    GLCD.CursorTo(0,0);
    GLCD.print("     "); 
    GLCD.SelectFont(Arial_bold_14);
    GLCD.print("  ALARM"); 
    //draw line
    GLCD.DrawLine(0,12,128,12,BLACK);

    if (alarmModeButtonCount == 2) {//no option highlighted
      aTimeSelected = false;
      activeSelected = false;
      GLCD.SelectFont(Arial14);

      //alarm
      GLCD.CursorTo(0,1);
      GLCD.print("TIME:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      GLCD.print("6:30 AM"); 

      //alarm status
      GLCD.CursorTo(0,2);
      GLCD.print("ACTIVE:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (alarmIsActive == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    if (alarmModeButtonCount == 1) {//TIME option highlighted
      aTimeSelected = true;
      activeSelected = false;
      GLCD.SelectFont(Arial14);

      //alarm
      GLCD.CursorTo(0,1);
      GLCD.SelectFont(Arial_bold_14);
      GLCD.print("TIME:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial_bold_14);
      GLCD.print("6:30 AM"); 

      //alarm status
      GLCD.CursorTo(0,2);
      GLCD.SelectFont(Arial14);
      GLCD.print("ACTIVE:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      if (alarmIsActive == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    if (alarmModeButtonCount == 0) {//ALARM option highlighted
      aTimeSelected = false;
      activeSelected = true;
      GLCD.SelectFont(Arial14);

      //alarm
      GLCD.CursorTo(0,1);
      GLCD.SelectFont(Arial14);
      GLCD.print("TIME:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial14);
      GLCD.print("6:30 AM"); 

      //alarm status
      GLCD.CursorTo(0,2);
      GLCD.SelectFont(Arial_bold_14);
      GLCD.print("ACTIVE:"); 
      GLCD.SelectFont(SystemFont5x7);
      GLCD.print(" "); 
      GLCD.SelectFont(Arial_bold_14);
      if (alarmIsActive == true) {
        GLCD.print("YES");
      } 
      else {
        GLCD.print("NO");
      }
    }

    //add delay to lower refresh rate on the display (remove blink)
    delay(200);
  }  
} //end of loop

////////////////////////////////////////////////////////////////////////////////
//Get GPS time
void syncGPSTime() {

  //pass GPS time/date into the DS3231 RTC

  //for now the day of week is hard coded until an automatic calcutaion can be made
  hhGPS = (GPS.hour);
  mmGPS = (GPS.minute);
  ssGPS = (GPS.seconds);
  dayGPS = (GPS.day);
  monthGPS = (GPS.month);
  yearGPS = (GPS.year);
  // linkStatus;

  //year, month, date, hour, min, sec and week-day(starts from 0 and goes to 6)
  DateTime dt(yearGPS, monthGPS, dayGPS, hhGPS, mmGPS, ssGPS, dowRTC);

  RTC.adjust(dt); //Adjust date-time as defined 'dt' above 
  delay(10);
  GLCD.ClearScreen();
}
#165237
There's a lot of code there. I gave it a quick once over. When you copy paste a group of pretested code together it can very commonly cause some stepping on toes, or cluttering of the processor.

My first two spots to check were delays, and frequency of data going to and from the clock.

Commonly delays can wreck havoc on code structure when a loop is caught in a hidden delay during an incoming signal. That might have explained why your code works some times after say 10 button pushes. However this code seems pretty clean in that area.

Frequency of data being sent to and from the GPS and Clock module is my second thought. In a quick scan through that code I noticed a couple points where it looks like you are jamming the system with lots of updates at a high repeat rate.
Some notes I noticed that support the thought of a clogged processor

"Interrupt is called once a millisecond, looks for any new GPS data, and stores it"
// approximately every 2 seconds or so, print out the current stats (Seems you might have modified this to 10 seconds instead of 2)

You might want to ensure that you limit your time updates to the maximum acceptable gap that you feel fit.
By ryemac3
#165238
I stripped out all the GPS stuff and the IR library works well with the glcd library. So it has to be something with the GPS library.
Code: Select all
#include <glcd.h>
#include <IRremote.h>
#include <fonts/allFonts.h>

int RECV_PIN = 46;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {

  Serial.begin(115200);
  irrecv.enableIRIn(); // Start the receiver

  // Initialize the GLCD 
  GLCD.Init();

  // Select the font for the default text area
  GLCD.SelectFont(System5x7);

  GLCD.print("hello, world!");
}

void loop() {
  GLCD.CursorTo(0, 1);
  GLCD.print(millis()/1000);

  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}
#165239
"Interrupt is called once a millisecond, looks for any new GPS data, and stores it"
// approximately every 2 seconds or so, print out the current stats (Seems you might have modified this to 10 seconds instead of 2)
I also saw this in the code and thought that there isn't a need for the interrupt the run that often.
My guess is that the ISR is eating up too much time to allow the other processing to get done.
Try changing the interrupt rate to like every 100ms or even less.
By ryemac3
#165261
Actually, I eliminated the interrupt altogether and put all the GPS code in a function I can call with a button on the remote. Strangely enough, it still does it. I then began to wonder if it's the remote "irrecv.decode(&results" code.

As it turns out, I think I have way too much stuff going on in this section for the remote:
Code: Select all
if (irrecv.decode(&results)) {
    if (results.value == POWER) 
    {
      Serial.println("POWER");  
      syncGPSTime();  
    }
    if (results.value == A) 
    {
      Serial.println("A");  
      enterNormalMode = true;
      enterSettingsMode = false;
      enterAlarmMode = false;
      GLCD.ClearScreen();
    }
    if (results.value == B) 
    {
      Serial.println("B"); 
      //enter menu in default state so no options are highlighted
      settingsModeButtonCount = 3; 

      enterNormalMode = false;
      enterSettingsMode = true;
      enterAlarmMode = false;
      GLCD.ClearScreen();
    }
    if (results.value == C) 
    {
      Serial.println("C");
      //enter menu in default state so no options are highlighted
      alarmModeButtonCount = 2;

      enterNormalMode = false;
      enterSettingsMode = false;
      enterAlarmMode = true;
      GLCD.ClearScreen();
    }
    if (results.value == UP) 
    {
      Serial.println("UP");
      if(enterSettingsMode == true) {
        settingsModeButtonCount++;

        if(settingsModeButtonCount == 4) { 
          settingsModeButtonCount = 0;
        }
      }
      if(enterAlarmMode == true) {
        alarmModeButtonCount++;

        if(alarmModeButtonCount == 3) {
          alarmModeButtonCount = 0;
        }
      }
    }
    if (results.value == DOWN) 
    {
      Serial.println("DOWN");
      if(enterSettingsMode == true) {
        settingsModeButtonCount--;

        if(settingsModeButtonCount < 0) {
          settingsModeButtonCount = 3;
        }
      }
      if(enterAlarmMode == true) {
        alarmModeButtonCount--;

        if(alarmModeButtonCount < 0) {
          alarmModeButtonCount = 2;
        }
      }
    }
    if (results.value == LEFT) 
    {
      Serial.println("LEFT");
      if(gmtSelected == true) {
        TZAdjust--;
        //time zone changed - resync with GPS clock
        syncGPSTime();
      }

      if(dlsSelected == true) {
        DLSinEffect = !DLSinEffect;
      }

      if(chimeSelected == true) {
        chimeOnHour = !chimeOnHour;

      }

      if(aTimeSelected == true) {

      }

      if(activeSelected == true) {
        alarmIsActive = !alarmIsActive;
      }
    }
    if (results.value == RIGHT) 
    {
      Serial.println("RIGHT");
      if(gmtSelected == true) {
        TZAdjust++;
        //time zone changed - resync with GPS clock
        syncGPSTime();
      }

      if(dlsSelected == true) {
        DLSinEffect = !DLSinEffect;
      }

      if(chimeSelected == true) {
        chimeOnHour = !chimeOnHour;
      }

      if(aTimeSelected == true) {

      }

      if(activeSelected == true) {
        alarmIsActive = !alarmIsActive;
      }
    }
    if (results.value == SELECT) 
    {
      Serial.println("SELECT");  
      //set totally wrong date and time (so that a GPS sync can be tested)
      DateTime dt(2011, 1, 1, 1, 1, 0, 6);
      RTC.adjust(dt); 
      delay(10);
      GLCD.ClearScreen();
    }
    irrecv.resume();
  }
if I trim it back down to...
Code: Select all
if (irrecv.decode(&results)) {
    if (results.value == POWER) 
    {
      Serial.println("POWER");  
      syncGPSTime();  
    }
    if (results.value == A) 
    {
      Serial.println("A");  
     }
    if (results.value == B) 
    {
      Serial.println("B"); 
       }
    if (results.value == C) 
    {
      Serial.println("C");
      }
    if (results.value == UP) 
    {
      Serial.println("UP");
     }
    if (results.value == DOWN) 
    {
      Serial.println("DOWN");
     }
    if (results.value == LEFT) 
    {
      Serial.println("LEFT");
     
    if (results.value == RIGHT) 
    {
      Serial.println("RIGHT");
    }
    if (results.value == SELECT) 
    {
      Serial.println("SELECT");  
     
    }
    irrecv.resume();
  }
...it calls A, B, C, LEFT, etc no problem, and GPS works. It definitely has something to do with having all this stuff going on inside this switch. I think when I get home from work tonight, I'll have a go at pulling out this stuff and maybe calling each one as a separate function

Maybe something like:
Code: Select all
if (irrecv.decode(&results)) {
    if (results.value == POWER) 
    {
      syncGPSTime();  
    }
    if (results.value == A) 
    {
     buttonAPressed();  
     }
    irrecv.resume();
  }

void syncGPSTime() {
//sync GPS
}

void buttonAPressed() {
//do stuff for button A
} 
#165263
"I eliminated the interrupt altogether and put all the GPS code in a function I can call with a button"

Great solution. That would be an ideal work around to slim things down and make the code run smoother. Happy hacking
By ryemac3
#165266
TS-Tim wrote:"I eliminated the interrupt altogether and put all the GPS code in a function I can call with a button"

Great solution. That would be an ideal work around to slim things down and make the code run smoother. Happy hacking
Thanks. I also now make use of the EN pin. So with a press of a button on my remote, the GPS breakout is enabled, does it's thing, pulls the time down, sets the RTC, then shuts off. I can force it with the remote, but ideally, I'll put in a timer or something to fire that function at midnight.