LED displays - I'm stumped

I'm hoping someone will spot something I've missed to help me fix this issue, because I've tried for 2 weeks.

This relates to a couple of scoreboards I recently upgraded code to and built new remote transmitters (refer to cloning LINK and jumper wires failing LINK).

I'll be as brief and succinct as I can:

  1. I have built and installed 2 large scoreboards at our soccer club
  2. These are composed of 15 x large led displays (360's led's each), a 24V DC regulated supply, a circuit board with 15 small led digit displays (for testing) and a main circuit board that:
    a. Houses the 15 shift registers that drive the displays
    b. Houses a step down regulator
    c. Houses an Arduino mini that is "bolted on" with a shield ontop to connect to the board as well RF antenna, clock module, LDR.
  3. I have also made a 3rd set of the electronics for testing and programming purposes.

Now the problem...

I recently updated the code on the test Arduino setup as well as on the test mini pro remote RF setup. At home, the score changed, timer worked, time displayed worked and the temperature display XXc worked. Temperature display was 18c - nice and warm inside the house!

I removed this Arduino Uno (and shield) and replaced the existing one inside scoreboard 1 at the soccer club with this one. I also changed the remote with the new one (inc. new code). Works perfectly. Temperature display was 08c (a bit cold that morning).

I then used the Arduino Uno I removed from scoreboard 1, put it on my home test setup, a new shield as well, uploaded the new code, did the next remote and fantastic. Works 100%. Temperature again around 18c was displaying at home.

I removed this Arduino Uno (and shield) from the test one, and replaced the existing one inside scoreboard 2 at the soccer club. Again I also replaced the remote with the new one that had the new code. Everything except the temperature display worked. Temperature displayed 00c.

I have a test patterns that I can run on the scoreboards via their remotes. If I press the button number "8", it runs through a sequence displaying all all seven segments on each group of digits, with a 3 second delay between. I did this and all digits displayed all segments.

I also have button "2" that runs another test. It displays all digits first with 1, then 2, then 3, etc up to 9, 0 (again with a 3 second delay). All numbers, all digits displayed correctly.

So this is what I tried in fault finding (to no avail to date):

  1. The clock and temperature is controlled by a DS3231 module with a coin button cell battery. I changed the battery. Displayed "00c" still !
  2. I replaced the whole DS3231 module with the one I had on my test setup at home. Still 00c !!
  3. Rather than running the Vcc, Gnd, SDA and SCL lead from the DS3231 to the "push in fitting" on the main board, which jumpers to the arduino uno shield, I got 4 new "better" jumpers and connected them directly from the module to the relevant arduino uno pins as well as gnd and 5V directly to the Arduino Uno. Still 00c !!!
  4. I then uploaded the new code on the home test arduino that came out of scoreboard 2. It worked perfectly at home. So I swapped this one back at the soccer club in scoreboard 2. 00c !!!! Arrrrrrh.

So all 3 Arudino Uno's I tested were loaded with the same code and all 3 were able to display all numbers on all digits with the test.
Both DS3231's (with new batteries) displayed the temperature at home correctly but 00c on scoreboard 2.
Scoreboard 1 temperature (same code) displays correct temperature.
So I can't see it's a code problem, nor an

Arduino Uno faulty board problem, nor a DS3231 module fault, nor a wiring problem.

I'm stumped!


There are a few things you need to do to move forward. First, start removing parts from the large setup you have now to reproduce the problem with the fewest components and interconnections.

Once you have done that, draw the circuit by hand, looking at each wire and verifying what it is connected to. Label any non-obvious parts and provide links to non-common parts.

The next step is to put all the code in code tags and any relevant serial output also in code tags.

Is it possible to post an annotated schematic showing all hardware, power supplies etc. Along with that you need to post the code.

What is the voltage you measured when the large display was with all segments on '88888...'and what was the current draw?

Also an explanation of how it is should work and why the #8 button is a problem.

Could you clarify - are you using the DS3231 to provide the temperature? If so, are you reading it correctly? The temperature value is in two registers, and is signed BCD. And are all the DS3231s marked DS3231SN?

Well, it seems you have to get to the situation where you are running both scoreboards in the field, and one shows correct temp, but the other doesn't. Then you have to start interchanging parts to determine where the fault is. What part switch causes the problem to move from scoreboard 2 to scoreboard 1?

@sonofcy, this was another step I did do, but I just didn't mention it - thread was getting long. I disconnected all digit display (hence little load), disconnected the LDR, disconnected the RF antenna. So all that was left connected was the 24V supply to the main board, the arduino Uno, the step down regulator, the DS3231 module and the small digit display board to see if it would work. Same display 00c. As for the code, it's really long, so I didn't upload it. I will if it helps.

Main program on Arduino Uno:

/************************************************************************************************
Scoreboard
This program is used to display the current melbourne time, current ambient temperature, incrementing
and displaying the home and away scores, setting a game duration (up to 59 minutes), counting up to
this set half time duration and sounding a siren alert when the durationis reached.
This is operated remotely via a receiver on the control board and a transmitter.

This is run via a main circuit board that includes an Arduino Uno loaded with this code, an onboard 12VDC
supply, a transmitter, a temperature and clock circuit and an external 24V 15A switching supply.

This sketch below includes the following:

1.  A DS3231 real time clock module is used to monitor the current temperature and time.  This module is
    fed the Coordinated Universal Time (UTC) and the code adjusts to Melbourne time, also accounting for
    day light savings. This clock module uses the arduino I2C bus.  This is pin A4 to SDA(data) and A5 to
    SCL(clock) for an Arduino Uno.  If using an Arduino Mega, it would be A20 to SDA and A21 to SCL.
    This unit required between 2.3 to 5.5V - perfect for running via Arduino power.
    Suggestion - cut the link between the diode and "201" resistor as this module is not good to run with
    a rechargeable battery (not to mention the charge voltage is insufficient!)
    https://edwardmallon.wordpress.com/2014/05/21/using-a-cheap-3-ds3231-rtc-at24c32-eeprom-from-ebay/

2.  An LDR is used to control the brightness of the 7 segment displays.  One leg to ground, the other
    leg to 10K resistor to Arduino 5V.  Same resistor leg to analog pin A1.  Note, during the flood lights
    used at our club, I have the displays going dim at a set time of night pending month of the year,
    otherwise the LDR thinks the lights are the sun, and the displays end up shining too bright!

3.  A home and away score based on 2 x 7 segment LED digits for each score.
    These count from 00 to 99 with an increment increase via buttons on the remote.
    An increment decrease can be achieved also with the press of different buttons.s
    Each score can be reset back to 00 with a long press of 2 other buttons.

4.  The score / numbers are updated to TPIC6B595 shift registers which can handle the large 24V, 7 segment
    displays used here for this project.  These require a supply/signal of up to 7V.  This 7V is delivered
    by a DC-DC stop down module.  These registers have an output rating of 50V, 150mA with a max of 500mA.

5.  To get the colon blinking when the timer is running, spare outputss from the shift register that
    displays the centigrade "c", is used.  This data is shifted to the shift register which grounds
    to turn on and off the colon about every 0.5 seconds.  The second "change" is used to trigger
    the "on" signal.
    To activate the continuous blinking colon for the current time, again one of the outputs from
    the shift register are used (the one diplaying "c").  For the timer that requires
    blinking during operation and steady on when paused, another output from the same register is used

6.  Note, a variable called "offDelayTime" controls the displays turning off after 90 minutes inactivity on
    the timer.  The scores will also reset back to "00", the timer to "00:00" and the game duration
    to 45 minutes

NRF24L01's:
This code receives data from a remote that includes an nRF24L01.  The main control board also includes a
similar nRF24L01.  The remote runs on a 3 column x 4 row keyap.  Inputs are as follows:

     0 = Siren off
     1 = Increment home score by 1
     2 = Nil
     3 - Increment away score by 1
     4 = Decrease home score by 1
     5 = Start / Pause / Resume
     6 = Decrease away score by 1
     7 = Nil
     8 = Turn displays back on (if off)
     9 = Nil
     # = Nil

     *0 to *4 = 10's timer setting
     *5 & *6 = no such time for tens (over 45min not typical half time)
     *7# = Set timer to 20:00 minutes
     *8# = Set timer to 30:00 minutes
     *9# = Set timer to 45:00 minutes
     *x0# to *x9# = 1's timer setting and entry completion with # (where “x” is 0, 1, 2, 3 or 4 only)
       (where "x" above is a key entry from 0 to 9)
     *# = Reset scores to 00 and timer to 00:00 ready to start
     ** = cancel keypad entries

     0 (hold) = siren set to play when time reached
     1 (hold) = reset home score to 00
     2 (hold) = runs a test display of 8's on each "set" of digits
     3 (hold) = reset away score to 00
     5 (hold) = reset timer to 00:00 ready to start
     8 (hold) = turn off all the displays
     # (hold) = reset Date_Time (held down for 2 seconds)
     
     If the scoreboard is in Date_Time reset mode, the following keypad actions happen:
     2 = increment up the flashing digit value
     4 = move to the next digit left to set it
     6 = move to the next digit right to set it
     8 = increment down the flashing digit value
     Note:
       The month is displayed on the home score (bottom left of the board)
       The year is displayed in the timer (middle of the board)
       The date is displayed on the away score (bottom right of the board)
       The current time is displayed in the usual spot (top right of the board)
       The temperature digits are temporarily turned off
     To accept the date_time changes, again hold down "#" for 2 seconds

    nRF2401 setup:
    GND
    VCC  - to 3.3V !!! NOT 5V
    CE   - to Arduino pin 9
    CSN  - to Arduino pin 10
    SCK  - to Arduino pin 13
    MOSI - to Arduino pin 11
    MISO - to Arduino pin 12
    IRQ  - Not used

Created by Chris Job 2015/2017
************************************************************************************************/

//--[libraries]---------------------------
#include <DS3232RTC.h>                    //http://github.com/JChristensen/DS3232RTC
#include <Streaming.h>                    //http://arduiniana.org/libraries/streaming/
#include <TimeLib.h>                         //http://playground.arduino.cc/Code/Time
#include <Timezone.h>                     //http://github.com/JChristensen/Timezone
#include <Wire.h>                         //http://arduino.cc/en/Reference/Wire
#include <SPI.h>                          // Comes with Arduino IDE
#include "RF24.h"                         // https://github.com/TMRh20/RF24

//--[Display variables]-------------------
// this is used to turn off the displays, run an "8"'s test display or segment startup display
enum displayState {
  display_off,                            // can be used to turn off displays at end of day
  display_on,                             // can be used to turn on displays at start of day if turned off
  display_test,                           // this can be used to test all 7 segment display LED work
  display_eights                          // this runs "8's" on each set of digit as a test
}; // end enum

int displayState = display_test;          // start up the board with the display test

// Below are numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, c with seg 2, c, c with seg 2&4, and nil.
// In order to get the same led intensity on both the clock colon (that continually blinks) and the timer colon (that only
// blinks when the timer is running), spare outputs from shift register used for the "c" (celsius) 7 segment digit are used.
// Hence below, 88+2, 88 and 89+1+2)
const int digit[14] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 97 + 2, 97, 97 + 4 + 2, 0};

// below are firstly each edge of the display, then 9, 8, 7, 6, 5, 4, 3, 2, 1 and 0
const int test[18] = {2, 4, 8, 16, 32, 1, 64, 0, 111, 127, 7, 125, 109, 102, 79, 91, 6, 63};

/* The above decimal value is used to display numbers 0 to 9 based on:
         1
     -----------
     |         |
32   |         | 2
     |   64    |
     |---------|
     |         |
16   |         | 4
     |   8     |
     |---------|

Using above, "0" is 1+2+4+8+16+32=63.  "1" is 2+4=6. Etc, etc.*/

byte colonBlinkConfig = 12;               // used for flashing colons via shift register 15.  See above for digit[10], [11] and [12]
int patternDelay = 200;                   // delay between segment test pattern display
int eightsDisplay = 2000;                 // delay between 8's being displayed in testing

//--[Timer flash variables]---------------
// used to alternate between the current timer time and 00:00 when 1/2 time reached
enum timerFlash {
  flashTimerEnabled,
  flashTimerDisabled
}; // end enum

int timerFlash = flashTimerDisabled;      // start off with timer digits not flashing


//--[Siren variables]---------------------
// used in indicating the siren has been requested
enum sirenState {
  inactive,                               // as well as allowing sounding it once
  active,
  completed
}; // end enum

int sirenState = inactive;                // start with siren not active

byte sirenPin = 16;                       // digital pin used to pass the "tone" to the siren
byte siren = 1;                           // used in turning the sound off after a set duration time
unsigned long sirenStartTime = millis();  // used to set the siren sounding length
int sirenDuration = 3000;                 // siren "sound on" duration


//--[Strobe variables]--------------------
// used to make the strobe active or inactive
enum strobeState {
  not_flashing,
  flashing
}; // end enum

byte strobePin = 17;
byte strobe = 1;                          // used for toggling the light on and off
int strobeState = not_flashing;
unsigned long strobeStartTime = millis(); // used to time the flashing of the strobe
int strobeOn = 200;                       // strobe on duration
int strobeOff = 2000;                     // strobe off duration


//--[LDR variables]-----------------------
const byte ldrIn = A1;                    // arduino pin A1 to leg 1 of the LDR as well as leg 1 of a 10K resistor
// LDR leg 2 to GND and leg 2 of the 10K to Arduino 5V
const byte dimPin = 6;                    // arduio pin 6 connected to the TPIC6B595 pin 9 (Output Enable)
// make sure not to use pin 3 or 11 here as it delays the program
int ldrVal = 0;                           // variable to store the value coming from the sensor


//--[Shift register variables]------------
const byte dataPin = 5;                  // arduino pin 5 to TPIC6B595 pin 3 serial in (SER IN)
const byte latchPin = 4;                 // arduino pin 4 to TPIC6B595 pin 12 latch signal (RCK)
const byte clockPin = 2;                 // arduino pin 2 to TPIC6B595 pin 13 clock (SRCK)


//--[Score variables]---------------------
byte onesHome = 0;                        // ones digit for home score
byte tensHome = 0;                        // tens digit for home score
byte onesAway = 0;                        // ones digit for away score
byte tensAway = 0;                        // tens digit for away score


//--[timer variables]---------------------
// used to start, pause and reset the timer
enum counter {
  waiting,
  start,
  paused
};

int counter = waiting;                    // start with the timer waiting for input to start

byte minTimerTens = 0;                    // Counting timer minute (tens)
byte minTimerOnes = 0;                    // Counting timer minute (ones)
byte secTimerTens = 0;                    // Counting timer seconds (tens)
byte secTimerOnes = 0;                    // Counting timer seconds (ones)


//--[clock & temperature]-----------------
//Australia Eastern Time Zone (Sydney, Melbourne)
TimeChangeRule aEDT = { "AEDT", First, Sun, Oct, 2, 660};    //UTC + 11 hours
TimeChangeRule aEST = { "AEST", First, Sun, Apr, 3, 600};    //UTC + 10 hours
Timezone ausET(aEDT, aEST);
TimeChangeRule* tcr;                      //pointer to the time change rule, use to get the TZ abbrev
time_t utc, local;
byte secondAdvance;                       // variable used in progressing display every second
int currentTemp;                          // variable to store the current


//--[blinking]-----------------------------
// This is used to blink the timer colon when "counting" is active.
// It is also used to blink the time colon
// It is also used to blink the "timer" when the 1/2 time is reached
enum blinkState {
  blink_on,
  blink_off
};

int blinkState = blink_on;
unsigned long blinkMillis = millis();     // timer setting used to "blink" timer colon
int blinkDelay = 500;                     // timer colon blink delay


//--[timed auto digit shut down]-----------
unsigned long autoShutDisplays = millis();
unsigned long offDelayTime = 5400000;     // 1.5 hour timer non activity - to shut down displays
unsigned long cancelTimerSetting = millis();
unsigned long cancelTimerDelay = 10000;   // 10 second time allowance for setting timer

//--[variables used for receiver]---------
byte FlagStart = 0;                       // variable used in progressing if statement
byte CmdChar = 0;                         // used in receiving ascii value from transmitter
byte asterix = 0;                         // variable used to check if an asterix has been pressed to change the timer

// (Create an instance of a radio, specifying the CE and CS pins. )
RF24 myRadio (9, 10); // "myRadio" is the identifier you will use in following methods
byte addresses[][6] = {"1Node"};          // Create address for 1 pipe.
int dataReceived;  // Data that will be received from the transmitter

byte timerPreset = 0;                     // used to flash the timer digits whilst setting
byte tempMinTimerTens = 0;                // used to record pre-set game duration minute (tens)
byte tempMinTimerOnes = 0;                // used to record pre-set game duration minute (oness)

// --[timed auto digit shut down]------------
// if someone doesn't setup the date_time within 20 seconds the function resets
unsigned long cancelTimeSetting = millis();
int cancelTimeDelay = 20000;              // 20 second time allowance for setting each key entry

//--[variables used keypad date_time set]---------
// In the array of variables below these are preset to the year 25th Dec 2017, 13:00 hours 00 seconds
int digitDate[14] = {2, 5, 1, 2, 2, 0, 1, 7, 1, 3, 0, 0, 0, 0};       // default date-time values during setting
int digitDateReset[14] = {2, 5, 1, 2, 2, 0, 1, 7, 1, 3, 0, 0, 0, 0};  // used in resetting to the above values
int cdn = 0;                              // Current digit number being changed = date tens
int tempDateTime = 0;                     // used to temporarily store an above value whilst flashing
int hash = 0;                             // flag used to check if hash has been held pressed to change date & time

int hh;                                   // hour variable when resetting the date/time via keypad
int mm;                                   // minute variable when resetting the date/time via keypad
int ss;                                   // second variable when resetting the date/time via keypad
int dd;                                   // date variable when resetting the date/time via keypad
int nn;                                   // month variable when resetting the date/time via keypad
int yy;                                   // year variable when resetting the date/time via keypad

////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup(void) {

  //--[general setup]---------------------
  Serial.begin(9600);                   // enable Serial
  secondAdvance = second(now());          // used to display once per second

  //--[define output pins]----------------
  pinMode(latchPin, OUTPUT);              // used for shift registers
  pinMode(clockPin, OUTPUT);              // used for shift registers
  pinMode(dataPin, OUTPUT);               // used for shift registers
  pinMode(dimPin, OUTPUT);                // used for shift registers - controlling LED intensity
  pinMode(sirenPin, OUTPUT);              // used to activate a siren for end of game sessions
  pinMode(strobePin, OUTPUT);             // used to indicate siren will sound (as noted above)
  digitalWrite(strobePin, LOW);           // set strobe off on startup
  setBrightness();                        // check LDR value to set LED brightness
  usage();                                // run the "usage function"


  //--[define setup for receiver----------
  Serial.println(F("RF24/Simple Receive data Test"));
  myRadio.begin();                        // Start up the physical nRF24L01 Radio
  myRadio.setPayloadSize(1);
  myRadio.setChannel(116);                // Above most Wifi Channels
  myRadio.setDataRate(RF24_250KBPS);      // Addition in 2026
  //(note 116 = remote 1 - upper pitch, 108 = remote 2-lower pitch)
  // When testing, set the PA Level low to prevent power supply related issues as it is likely that
  // you will have the devices close to each other. RF24_PA_MAX is default.
  // myRadio.setPALevel(RF24_PA_MIN);     // Uncomment for less power
  myRadio.setPALevel(RF24_PA_MAX);
  myRadio.openReadingPipe(1, addresses[0]); // Use the first entry in array 'addresses' (Only 1 right now)
  myRadio.startListening();

} // end void setup

////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop(void) {

  //--[shift values to shift registers]---
  // pass on the result to the 595s
  shiftDisplay();

  //--[brightness function]---------------
  // check LDR value and set the LED brightness
  setBrightness();

  //--[siren and strobe function]---------
  timerCheck();
  sirenCheck();
  strobeCheck();

  //--[time setting function]-------------
  // handle serial commands for setting date/time
  serialTimeSet();

  //--[timer advance function]------------
  if (secondAdvance != second(now())) {
    blinkMillis = millis();
    secondAdvance = second(now());        // used to progress time every second
    count();                              // this advances counter seconds every second
    serial_Output();                      // print to serial monitor for testing only
  } // end if

  //--[colons blink functions]------------
  blinkTimer();                           // used to blink the colons on off every second
  blinkColons();                          // used to flash the colon on when timer operating

  //--[receiver function]-----------------
  // read input tranmitted from transmitter to receiver
  keyRead();

  //--[flash digits during timer setting]-
  flashTimerDigits();

  //--[flash digit during date-time setting]-
  flashDateTime();

  //--[shut down digits check]------------
  shutDownDigitsCheck();

  //--[cancel timer setting check]--------
  timerSettingCheck();

  //--[cancel setting date-time]----------
  cancelDateTime();

} // end void loop

////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////

//--[for clock time check and setup]------
void usage (void) {

  // at startup, show some information about program usage and check RTC operational
  Serial.println(F("\nThe time on the RTC is to be set to UTC (Universal Coordinated Time)"));
  Serial.println(F("In melbourne, AEST (Australian Eastern Standard Time) is UTC + 10 hours"));
  Serial.println(F("In melbourne, AEDT (Australian Eastern Daylight saving Time) is UTC + 11 hours"));
  Serial.println(F("To set the UTC date & time via serial monitor:"));
  Serial.println(F("  a. Set carriage return and new line in the monitor"));
  Serial.println(F("  b. Set the appropriate baud rate (115200?)"));
  Serial.println(F("  c. Type in the following UTC time format:  yyyy,mm,dd,hh,mm,ss"));
  Serial.print(F("\nInitialize RTC ..."));
  //setSyncProvider() causes the Time library to synchronize with the
  //external RTC by calling RTC.get() every five minutes by default
  setSyncProvider(RTC.get);
  Serial << F("\nRTC Sync");
  if (timeStatus() != timeSet) Serial << F("Unable to sync with the RTC");
  Serial << endl;
  currentTemp = (RTC.temperature() / 4);
  delay(100);  // delay to allow user to read the above on first startup of serial monitor
} // end usage loop


//--[Time & date upload via Serial monitor]---
void serialTimeSet(void) {
  static time_t utcLast;
  time_t utc;
  tmElements_t tm;
  //check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
  if (Serial.available() >= 12) {
    //note that the tmElements_t Year member is an offset from 1970,
    //but the RTC wants the last two digits of the calendar year.
    //use the convenience macros from Time.h to do the conversions.
    int y = Serial.parseInt();
    if (y >= 100 && y < 1000)
      Serial << F("Error: Year must be two digits or four digits!") << endl;
    else {
      if (y >= 1000)
        tm.Year = CalendarYrToTm(y);
      else    //(y < 100)
        tm.Year = y2kYearToTm(y);
      tm.Month = Serial.parseInt();
      tm.Day = Serial.parseInt();
      tm.Hour = Serial.parseInt();
      tm.Minute = Serial.parseInt();
      tm.Second = Serial.parseInt();
      utc = makeTime(tm);
      RTC.set(utc);        //use the time_t value to ensure correct weekday is set
      setTime(utc);
      Serial << F("RTC set to: ");
      printDateTime(utc, "UTC");
      Serial << endl;
      //dump any extraneous input
      while (Serial.available() > 0) Serial.read();
    } // end if statement
  } // end if statement

  //get the current time
  utc = now();
  if (utc != utcLast) {          //display once per second
    utcLast = utc;
    //    printDateTime(utc, "UTC  ");                            // not sure what this is
    //    printDateTime(ausET.toLocal(utc, &tcr), tcr -> abbrev); // not sure about this either
    local = ausET.toLocal(utc, &tcr);

    if (second(utc) == 0) {  //display temperature once per minute
      float c = RTC.temperature() / 4.;
      float f = c * 9. / 5. + 32.;
      //      Serial << F("  ") << c << F(" C  ") << f << F(" F");  // dont need this in Aussie land!
      currentTemp = (RTC.temperature() / 4);
    } // end if statement
    Serial << endl;
  } // end if statement
} // end serialTimeSet loop


//--[Print date& time to Serial]----------
void printDateTime(time_t t, char* tz) {
  printDate(t);
  Serial << ' ';
  printTime(t);
  Serial << tz;
} // end printDateTime loop


//--[Print time to Serial]----------------
void printTime(time_t t) {
  printI00(hour(t), ':');
  printI00(minute(t), ':');
  printI00(second(t), ' ');
} // end printTime loop


//--[Print date to Serial]----------------
void printDate(time_t t) {
  //  printI00(day(t), 0);
  //  Serial << monthShortStr(month(t)) << _DEC(year(t));
} // end printDate loop


//--[add zero to if < 10}-----------------
void printI00(int val, char delim) {
  if (val < 10) Serial << '0';
  Serial << _DEC(val);
  if (delim > 0) Serial << delim;
  return;
} // end printI00 function


//--[output to serial monitor]------------
void serial_Output(void) {
  //  Serial << "\nCurrent Melbourne time: ";
  //  printI00(hour(local), 0);
  //  Serial << ":";
  //  printI00(minute(local), 0);
  //  Serial << ":";
  //  printI00(second(local), 0);
  //  Serial << "  ";
  //  printI00(day(local), 0);
  //  Serial << "/";
  //  printI00(month(local), 0);
  //  Serial << "/";
  //  Serial.print(year(local));
  //  Serial << ".  Temperature: ";
  //  Serial.print(currentTemp);
  //  Serial << "\nCurrent UTC time:       ";
  //  printI00(hour(), 0);
  //  Serial << ":";
  //  printI00(minute(), 0);
  //  Serial << ":";
  //  printI00(second(), 0);
  //  Serial << "  ";
  //  printI00(day(), 0);
  //  Serial << "/";
  //  printI00(month(), 0);
  //  Serial << "/";
  //  Serial.print(year());
  //  Serial << ".  Temperature: ";
  //  Serial.println(currentTemp);

} // end serial_Output function


//--[update display to all shift registers]--------
// below are a number of display setting pending what
// display is called up
void shiftDisplay (void) {

  // This first setup runs on startup, then again if called
  if (displayState == display_test) {
    for (byte t = 0; t < 18; t++) {
      for (byte s = 0; s < 15; s++) {
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, MSBFIRST, test[t]);
        digitalWrite(latchPin, HIGH);
      } // end for statement
      delay(patternDelay);
      displayState = display_on;
    } // end for statement
  } // end if statement

  // This runs if someone holds down "2" on the keypad
  // it displays a set of eights firstly on the temperature,
  // then the clock, then the timer and then on each score
  if (displayState == display_eights) {
    // display 8's on temperature only...
    digitalWrite(latchPin, LOW);
    for (byte s = 0; s < 8; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    for (byte s = 0; s < 2; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    for (byte s = 0; s < 4; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    for (byte s = 0; s < 1; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    digitalWrite(latchPin, HIGH);
    delay(eightsDisplay);

    // display 8's on clock only...
    digitalWrite(latchPin, LOW);
    for (byte s = 0; s < 4; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    for (byte s = 0; s < 4; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    for (byte s = 0; s < 7; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    digitalWrite(latchPin, HIGH);
    delay(eightsDisplay);

    // display 8's on the timer only...
    digitalWrite(latchPin, LOW);
    for (byte s = 0; s < 4; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    for (byte s = 0; s < 11; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    digitalWrite(latchPin, HIGH);
    delay(eightsDisplay);

    // display 8's on home score only...
    digitalWrite(latchPin, LOW);
    for (byte s = 0; s < 10; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    for (byte s = 0; s < 2; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    for (byte s = 0; s < 3; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    digitalWrite(latchPin, HIGH);
    delay(eightsDisplay);

    // display 8's on away score only...
    digitalWrite(latchPin, LOW);
    for (byte s = 0; s < 12; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    for (byte s = 0; s < 2; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 127);
    } // end for statement
    for (byte s = 0; s < 1; s++) {
      shiftOut(dataPin, clockPin, MSBFIRST, 0);
    } // end for statement
    digitalWrite(latchPin, HIGH);
    delay(eightsDisplay);
    displayState = display_on;
  } // end if statement

  // The following display occurs only when the 1/2 time is reached
  // This blinks "00:00" on the timer and the next "if" statement blinks the current timer time
  if (displayState == display_on && timerFlash == flashTimerEnabled && blinkState == blink_off && hash == 0) {
    digitalWrite(latchPin, LOW);

    shiftOut(dataPin, clockPin, MSBFIRST, 0);                         // Timer - seconds ones (8)
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                         // Timer - seconds tens (7)
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                         // Timer - minutes ones (6)
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                         // Timer - minutes tens (5)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) / 10]);   // Current hour tens (1)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) % 10]);   // Current hour ones (2)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) / 10]); // Current minute tens (3)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) % 10]); // Current minute ones (4)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp % 10]);   // temperature 1s (15)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp / 10]);   // temperature 10s (14)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesHome]);           // Home score 1s digit (10)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensHome]);           // Home score 10s digit (9)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensAway]);           // Away score 10s digit (11)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesAway]);           // Away score 1s digit (12)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[colonBlinkConfig]);   // temperature - "c"

    digitalWrite(latchPin, HIGH);
  } // end if statement for timer score blink off

  // The following display occurs only when the 1/2 time is reached
  // This blinks the current timer time then the "if" statement above blinks "00:00"
  if (displayState == display_on && timerFlash == flashTimerEnabled && blinkState == blink_on && hash == 0) {
    digitalWrite(latchPin, LOW);

    shiftOut(dataPin, clockPin, MSBFIRST, digit[secTimerOnes]);        // Timer - seconds ones (8)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[secTimerTens]);        // Timer - seconds tens (7)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minTimerOnes]);        // Timer - minutes ones (6)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minTimerTens]);        // Timer - minutes tens (5)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) / 10]);   // Current hour tens (1)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) % 10]);   // Current hour ones (2)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) / 10]); // Current minute tens (3)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) % 10]); // Current minute ones (4)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp % 10]);   // temperature 1s (15)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp / 10]);   // temperature 10s (14)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesHome]);           // Home score 1s digit (10)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensHome]);           // Home score 10s digit (9)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensAway]);           // Away score 10s digit (11)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesAway]);           // Away score 1s digit (12)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[colonBlinkConfig]);   // temperature - "c"

    digitalWrite(latchPin, HIGH);
  } // end if statement for timer score blink on


  // The following display is shown during normal operation
  if (displayState == display_on  && timerFlash == flashTimerDisabled && hash == 0) {
    digitalWrite(latchPin, LOW);

    shiftOut(dataPin, clockPin, MSBFIRST, digit[secTimerOnes]);        // Timer - seconds ones (8)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[secTimerTens]);        // Timer - seconds tens (7)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minTimerOnes]);        // Timer - minutes ones (6)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minTimerTens]);        // Timer - minutes tens (5)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) / 10]);   // Current hour tens (1)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[hour(local) % 10]);   // Current hour ones (2)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) / 10]); // Current minute tens (3)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[minute(local) % 10]); // Current minute ones (4)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp % 10]);   // temperature 1s (15)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[currentTemp / 10]);   // temperature 10s (14)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesHome]);           // Home score 1s digit (10)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensHome]);           // Home score 10s digit (9)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[tensAway]);           // Away score 10s digit (11)
    shiftOut(dataPin, clockPin, MSBFIRST, digit[onesAway]);           // Away score 1s digit (12)

    shiftOut(dataPin, clockPin, MSBFIRST, digit[colonBlinkConfig]);   // temperature - "c"

    digitalWrite(latchPin, HIGH);
  } // end if statement


  // The following display is shown when setting the date-time
  if (displayState == display_on && hash == 1) {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[7]]);    // Year ones
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[6]]);    // Year tens
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[5]]);    // Year hundreds
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[4]]);    // Year thousands
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[8]]);    // Current hour tens
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[9]]);    // Current hour ones
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[10]]);   // Current minute tens
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[11]]);   // Current minute ones
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                      // blank
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                      // blank
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[1]]);    // Month - ones
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[0]]);    // Month - tens
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[2]]);    // Date - tens
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitDate[3]]);    // Date - ones
    shiftOut(dataPin, clockPin, MSBFIRST, 0);                      // blank
    digitalWrite(latchPin, HIGH);
  } // end if statement


  // The following is used to display "nothing" on the LEDs at the end of the day
  // or when there is about 1.5 hours inactivity on the remote keypad
  if (displayState == display_off) {
    for (byte s = 0; s < 15; s++) {
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, MSBFIRST, digit[14]); // this display a nothing digit
      digitalWrite(latchPin, HIGH);
    } // end for statement
  } // end if statement
} // end shiftDisplay function


//--[7 segment display brighness control]-
// This contols the brightness of the 7 segment displays (i.e. day to night)
void setBrightness(void) {
  ldrVal = analogRead(ldrIn);             // read the value from the light dependant resistor
  ldrVal = map(ldrVal, 0, 1024, 1, 250);  // map ldrVal of 0 to 1024 to 1 to 255.
  // Dimmer at night, increase 250.  Brighter during day 1 to be 0

  // After testing I've found that the floor lights on the pitch are read by the LDR to be daylight
  // so the easiest was to ensure the LEDs are not too bright, below I've over-ridden the brightness
  // for each month at nighttime (accounting for day light savings).  Comment out if not applicable
  if ((month(local) == 1) && (hour(local) > 19)
      || (month(local) == 2) && (hour(local) > 19)
      || (month(local) == 3) && (hour(local) > 19)
      || (month(local) == 4) && (hour(local) > 18)
      || (month(local) == 5) && (hour(local) > 16)
      || (month(local) == 6) && (hour(local) > 16)
      || (month(local) == 7) && (hour(local) > 16)
      || (month(local) == 8) && (hour(local) > 16)
      || (month(local) == 9) && (hour(local) > 17)
      || (month(local) == 10) && (hour(local) > 18)
      || (month(local) == 11) && (hour(local) > 18)
      || (month(local) == 12) && (hour(local) > 19)) {
    ldrVal = 240;                         // this is quite dim
  } // end if
  analogWrite(dimPin, ldrVal);            // set brightness on TPIC6B595s
} // end setBrightness function


//--[Increment the timer sec and mins]----
void count (void) {
  if (counter == start) {         // if counter is operating...
    if (secTimerOnes < 10) {
      secTimerOnes++; // if seconds is less than 10, add one
    }
    if (secTimerOnes > 9) {
      // if seconds is >9, make 0 and add one to tens of seconds
      secTimerOnes = 0;
      secTimerTens++;
    }
    if (secTimerTens > 5) {
      // if tens of seconds is > 5, set seconds to 00 and add one to minute ones
      secTimerOnes = 0;
      secTimerTens = 0;
      minTimerOnes++;
    }
    if (minTimerOnes > 9) {
      // if minute ones is >9, make 0 and add one to tens of minutes
      minTimerOnes = 0;
      minTimerTens++;
    }
    if (minTimerTens > 5) {
      // if tens of minutes is > 5, set all digits to zero 00:00
      minTimerTens = 0;
      minTimerOnes = 0;
      secTimerTens = 0;
      secTimerOnes = 0;
    } // end if statement
  } // end if statement
} // end count function


//--[Timing for blinking digits]-----------------
void blinkTimer (void) {
  if (millis() - blinkMillis < blinkDelay) {      // if blink delay (500ms) not reach, colon on
    blinkState = blink_on;
  } // end if
  if (millis() - blinkMillis >= blinkDelay) {     // if blink delay (500ms) reached, colon off
    blinkState = blink_off;
  } // end if
} // end blinkTimer function


//--[Strobe the colon during count]-------
void blinkColons (void) {
  if (counter == start && blinkState == blink_on) {                           // colon is in on position for both the timer and the clock
    colonBlinkConfig = 12;
  } // end if
  if (counter == start && blinkState == blink_off) {                          // colon is in off position for both the timer and the clock
    colonBlinkConfig = 11;
  } // end if
  if ((counter == waiting || counter == paused) && blinkState == blink_on) {  // colon is in on position when timer is waiting and on for the clock
    colonBlinkConfig = 12;
  } // end if
  if ((counter == waiting || counter == paused) && blinkState == blink_off) { // colon is in on position when timer is paused and off for the clock
    colonBlinkConfig = 10;
  } // end if
} // end blinkColons


//--[Used to check timer reached]---------
void timerCheck (void) {
  if (counter == start && minTimerTens == tempMinTimerTens && minTimerOnes == tempMinTimerOnes && secTimerTens < 1 && secTimerOnes < 1) {
    timerFlash = flashTimerEnabled;
  } // end if
} // end timerCheck function



//--[Used to sound a siren]---------------
void sirenCheck (void) {
  if (counter == start && siren == 1 && minTimerTens == tempMinTimerTens && minTimerOnes == tempMinTimerOnes && secTimerTens < 1 && secTimerOnes < 1 && sirenState == active) {
    sirenStartTime = millis();
    tone(sirenPin, 480);
    siren = 0;
  } // end if
  if (counter == start && siren == 0 && minTimerTens == tempMinTimerTens && minTimerOnes == tempMinTimerOnes && sirenState == active && millis() - sirenStartTime > sirenDuration) {
    sirenStartTime = millis();
    noTone(sirenPin);
    sirenState = completed;
    siren = 1;
  } // end if
} // end sirenCheck function


//--[Used to flash the strobe]------------
void strobeCheck (void) {
  if (strobeState == flashing && strobe == 1 && millis() - strobeStartTime > strobeOff) {
    strobeStartTime = millis();
    digitalWrite(strobePin, HIGH);
    strobe = 0;
    return;
  } // end if
  if (strobeState == flashing && strobe == 0 && millis() - strobeStartTime > strobeOn) {
    strobeStartTime - millis();
    digitalWrite(strobePin, LOW);
    strobe = 1;
  } // end if
  if (strobeState == not_flashing) {
    digitalWrite(strobePin, LOW);
    strobe = 1;
  } // end if
} // end strobeCheck function


//--[Used to check board usage]-----------
// This looks to see if the timer has been still (i.e. not counting) for 60 minutes
// If so, then everything get's reset and the displays all turn off
void shutDownDigitsCheck (void) {
  if (millis() - autoShutDisplays > offDelayTime) {
    onesHome = 0;            // these next 4 set the scores to 00
    tensHome = 0;
    onesAway = 0;
    tensAway = 0;
    counter = waiting;       // this stops the timer counting
    minTimerTens = 0;        // these next 4 set the timer to 00:00
    minTimerOnes = 0;
    secTimerTens = 0;
    secTimerOnes = 0;
    tempMinTimerTens = 4;    // next time it turns on, timer will be set to 45 minutes
    tempMinTimerOnes = 5;
    timerFlash = flashTimerDisabled;  // this stops the end of game timer flashing
    displayState = display_off;
  } // end if
} // end shutDownDigitCheck


//--[Used to set timer]-------------------
void timerSettingCheck (void) {
  // This is used when setting the 1/2 time duration.  If someone stops half way
  // (being confused), then in 10 seconds lack of action, the sub routine cancels
  if ((timerPreset == 2) && (millis() - cancelTimerSetting > cancelTimerDelay)) {
    resetAll();
    timerFlash = flashTimerDisabled;  // this is because the end of game time not set
  } // end if

  if ((timerPreset == 1) && (millis() - cancelTimerSetting > cancelTimerDelay)) {
    resetAll();
    timerFlash = flashTimerDisabled;  // this is because the end of game time not set
  } // end if
} // end timerSettingCheck


//--[Used with the above]-------------------
void resetAll (void) {
  cancelTimerSetting = millis();
  onesHome = 0;
  tensHome = 0;
  onesAway = 0;
  tensAway = 0;
  minTimerTens = 0;
  minTimerOnes = 0;
  secTimerTens = 0;
  secTimerOnes = 0;
  counter = waiting;
  sirenState = inactive;
  strobeState = not_flashing;
  asterix = 0;
  timerPreset = 0;
} // end resetAll


void flashTimerDigits (void) {
  // This flashes set digits on the timer during setting the 1/2 time value
  if (timerPreset == 2 && blinkState == blink_off) {
    // minTimerTens = 0;
    minTimerOnes = -1;  // this dummy number makes it blink "blank" with setting timer time
  }
  if (timerPreset == 2 && blinkState == blink_on) {
    minTimerTens = tempMinTimerTens;
    minTimerOnes = tempMinTimerOnes;
  }

  if (timerPreset == 1 && blinkState == blink_off) {
    minTimerTens = -1;
    minTimerOnes = -1;  // this dummy number makes it blink "blank" with setting timer time
  }
  if (timerPreset == 1 && blinkState == blink_on) {
    minTimerTens = tempMinTimerTens;
    minTimerOnes = tempMinTimerOnes;
  }
} // end void flashTimerDigits


void flashDateTime (void) {
  // This flashes one digit during setting the date-time
  if (hash == 1 && blinkState == blink_off) {
    digitDate[cdn] = 13;  // this dummy number makes it blink "blank" during setting the date-tim
  }
  if (hash == 1 && blinkState == blink_on) {
    digitDate[cdn] = tempDateTime;
  }
} // end void flashDateTime

void cancelDateTime (void) {
  // if setting the date-time is not done within the perscribed time, this operation cancels
  if (millis() - cancelTimeSetting > cancelTimeDelay) {
    for (int i = 0; i < 14; i++) {
      digitDate[i] = digitDateReset[i];
    } // end for
    tempDateTime = 0;
    hash = 0;
    cdn = 0;
  } // end if
} // end void cancelDateTime



//--[Used to display input from trasmitter]------
// This is the code that reads the keypad presses
void keyRead () {
  if ( myRadio.available()) {   // Check for incoming data from transmitter
    while (myRadio.available()) { // While there is data ready
      myRadio.read( &dataReceived, sizeof(dataReceived) ); // Get the data payload
      Serial.print("Data received = ");
      Serial.println(dataReceived);
      if ((asterix == 0) && (dataReceived == 33) && hash == 0) {
        switch (CmdChar) {

          case 65:
            // 0 pressed to turn off the siren if active
            if (sirenState == active) {    // check if the siren is active
              sirenState = inactive;       // if it is, make it inactive and the strobe as well
              strobeState = not_flashing;
              break;
            }

          case 66:
            // home score digit 1 pressed to increase score by 1.  Note 65 is ascii of "A"
            if (onesHome < 9) {
              onesHome++; // if home score ones < 9 add one to it
            }
            else if (onesHome == 9) {
              onesHome = 0;  // if home score ones is 9, change to 0 and add one to tens
              tensHome++;
            }
            else if (onesHome == 0 && tensHome == 10) {
              tensHome = 0; // if home score tens is 10, change tens to 0
            }
            break;

          case 68:
            // away score digit 3 pressed to increase score by 1.  Note 66 is ascii of "B"
            if (onesAway < 9) {
              onesAway++; // if away score ones < 9 add one to it
            }
            else if (onesAway == 9) {
              onesAway = 0;  // if away score ones is 9, change to 0 and add one to tens
              tensAway++;
            }
            else if (onesAway == 0 && tensAway == 10) {
              tensAway = 0; // if away score tens is 10, change tens to 0
            }
            break;

          case 69:
            // home score digit 4 pressed to decrease score by 1.  Note 67 is ascii of "C"
            if (onesHome > 0 && tensHome == 0) {
              onesHome--;
            }
            if (onesHome == 0 && tensHome > 0) {
              onesHome = 9;
              tensHome--;
            }
            if (onesHome > 0 && tensHome > 0) {
              onesHome--;
            }
            break;

          case 70:
            // 1st time button 5 is pressed, reset time to 00:00 then start the timer
            if (counter == waiting) {      // check if timer is not in operation
              minTimerTens = 0;            // reset all digits to 0
              minTimerOnes = 0;
              secTimerTens = 0;
              secTimerOnes = 0;
              autoShutDisplays = millis(); // start timing for button "5" inactivity
              counter = start;
              count();
              return;
            } // end if statement
            if (counter == start) {        // check if timer is in operation
              autoShutDisplays = millis(); // start timing for button "5" inactivity
              counter = paused;            // toggle to pause timer
              return;
            } // end if statement
            if (counter == paused) {       // check if timer is paused
              autoShutDisplays = millis(); // start timing for button "5" inactivity
              counter = start;             // toggle to start timer again
              count();
              return;
            } // end if statement

          case 71:
            // away score digit 6 pressed to decrease score by 1.  Note 68 is ascii of "D"
            if (onesAway > 0 && tensAway == 0) {
              onesAway--;
            }
            if (onesAway == 0 && tensAway > 0) {
              onesAway = 9;
              tensAway--;
            }
            if (onesAway > 0 && tensAway > 0) {
              onesAway--;
            }
            break;

          case 73:
            // 8 pressed to turn on the displays if they're off
            autoShutDisplays = millis();
            displayState = display_test;
            break;

          case 75:
            // this does nothing - ignore
            break;

          case 76:
            // asterix pressed
            asterix = 1;
            cancelTimerSetting = millis();
            timerPreset = 1; // used in flashing both timer digits
            break;

          case 77:  // hold 0 to activate siren
            sirenState = active;
            strobeState = flashing;
            break;

          case 78:
            // keypad 1 held down to reset home score to 00
            onesHome = 0;
            tensHome = 0;
            break;

          case 79:
            // keypad 3 held down to reset away score to 00
            onesAway = 0;
            tensAway = 0;
            break;

          case 80: // hold 8 to turn off displays
            // 8 hold pressed to turn on the displays if they're off
            displayState = display_off;
            break;

          case 81:
            // button no. 5 held down on remote to reset the timer to 00:00
            if (counter == start || counter == paused) {
              timerFlash = flashTimerDisabled; // this is used in flashing timer when set time reached
              minTimerTens = 0;                // reset timer to zero and put in standby mode
              minTimerOnes = 0;
              secTimerTens = 0;
              secTimerOnes = 0;
              counter = waiting;
              break;
            }

          case 82:
            // keypad 2 held down to test each set of digits
            displayState = display_eights;
            break;

          case 83:
            // keypad # held down to reset the date_time
            cancelTimeSetting = millis();  // set in case time_date single stage not set within 20 seconds
            cdn = 0;
            tempDateTime = digitDate[cdn];
            hash = 1;                      // flag to indicate that the hash key has been held down
            break;

        }// end switch
        dataReceived = 0; // as data has just been received
      }// end if


      // if the "*" key has been pressed do the following
      if ((asterix == 1) && (dataReceived == 33) && hash == 0) {
        if (timerPreset == 2) {  // used in flashing second timer digit only
          switch (CmdChar) {
            case 65:
              // *0 was pressed to set to x0:00 minutes on the timer
              tempMinTimerOnes = 0;
              break;

            case 66:
              // *1 was pressed to set to x1:00 minutes on the timer
              tempMinTimerOnes = 1; // just looks better adding 0 here
              break;

            case 67:
              // *2 was pressed to set to x2:00 minutes on the timer
              tempMinTimerOnes = 2; // just looks better adding 0 here
              break;

            case 68:
              // *3 was pressed to set to x3:00 minutes on the timer
              tempMinTimerOnes = 3; // just looks better adding 0 here
              break;

            case 69:
              // *4 was pressed to set to x4:00 minutes on the timer
              tempMinTimerOnes = 4; // just looks better adding 0 here
              break;

            case 70:
              // *5 was pressed to set to x5:00 minutes on the timer
              tempMinTimerOnes = 5; // just looks better adding 0 here
              break;

            case 71:
              // *6 was pressed to set to x6:00 minutes on the timer
              tempMinTimerOnes = 6; // just looks better adding 0 here
              break;

            case 72:
              // *7 was pressed to set to x7:00 minutes on the timer
              tempMinTimerOnes = 7; // just looks better adding 0 here
              break;

            case 73:
              // *8 was pressed to set to x8:00 minutes on the timer
              tempMinTimerOnes = 8; // just looks better adding 0 here
              break;

            case 74:
              // *9 was pressed to set to x9:00 minutes on the timer
              tempMinTimerOnes = 9; // just looks better adding 0 here
              break;

            case 76:
              // asterix was pressed followed by the "#" key to reset all
              resetAll ();
              break;

            case 75:
              // asterix was pressed followed by a second one to reset all
              resetAll ();
              break;

          }// end switch
          dataReceived = 0; // as data has just been received

          CmdChar = 0;
          minTimerTens = tempMinTimerTens;
          minTimerOnes = tempMinTimerOnes;
          timerPreset = 0;                  // stops flashing timer digits
          cancelTimerSetting = millis();    // reset timer
          asterix = 0;                      // reest asterix press
        }// end if


        switch (CmdChar) {

          case 65:
            // *0 was pressed to set to 0x:00 minutes on the timer
            tempMinTimerTens = 0;
            tempMinTimerOnes = 0; // just looks better adding 0 here
            timerPreset = 2; // used in flashing second timer digit only
            break;

          case 66:
            // *1 was pressed to set to 1x:00 minutes on the timer
            tempMinTimerTens = 1;
            tempMinTimerOnes = 0; // just looks better adding 0 here
            timerPreset = 2; // used in flashing second timer digit only
            break;

          case 67:
            // *2 was pressed to set to 2x:00 minutes on the timer
            tempMinTimerTens = 2;
            tempMinTimerOnes = 0; // just looks better adding 0 here
            timerPreset = 2; // used in flashing second timer digit only
            break;

          case 68:
            // *3 was pressed to set to 3x:00 minutes on the timer
            tempMinTimerTens = 3;
            tempMinTimerOnes = 0; // just looks better adding 0 here
            timerPreset = 2; // used in flashing second timer digit only
            break;

          case 69:
            // *4 was pressed to set to 4x:00 minutes on the timer
            tempMinTimerTens = 4;
            tempMinTimerOnes = 0; // just looks better adding 0 here
            timerPreset = 2; // used in flashing second timer digit only
            break;

          case 70:
            // ignore a 5 keypress at this point
            break;

          case 71:
            // ignore a 6 keypress at this point
            break;

          case 72:
            // asterix was pressed followed by the 7 key to set to 20 minutes on the timer
            tempMinTimerTens = 2;
            tempMinTimerOnes = 0;
            minTimerTens = tempMinTimerTens;
            minTimerOnes = tempMinTimerOnes;
            asterix = 0;
            timerPreset = 0; // turn off flashing of timer digits
            break;

          case 73:
            // asterix was pressed followed by the 8 key to set to 30 minutes on the timer
            tempMinTimerTens = 3;
            tempMinTimerOnes = 0;
            minTimerTens = tempMinTimerTens;
            minTimerOnes = tempMinTimerOnes;
            asterix = 0;
            timerPreset = 0; // turn off flashing of timer digits
            break;

          case 74:
            // asterix was pressed followed by the 9 key to set to 45 minutes on the timer
            tempMinTimerTens = 4;
            tempMinTimerOnes = 5;
            minTimerTens = tempMinTimerTens;
            minTimerOnes = tempMinTimerOnes;
            asterix = 0;
            timerPreset = 0; // turn off flashing of timer digits
            break;


          case 76:
            // asterix was pressed followed by the "#" key to reset all
            resetAll ();


          case 75:
            // asterix was pressed followed by a second one to reset all
            resetAll ();

        } // end switch
        dataReceived = 0; // as data has just been received

        cancelTimerSetting = millis();

        FlagStart = 0;
      } // end if


      if ((asterix == 0) && (dataReceived == 33) && hash == 1) {
        switch (CmdChar) {
          case 83:
            // keypad # held down
            // update time format with "setTime" (int hh,int min,int ss,int dd, int nn, int yy)
            digitDate[cdn] = tempDateTime; // this sets the digitDate value just in case it's blank during flashing

            static time_t utcLast;
            time_t utc;
            tmElements_t tm;

            // The keypad entry is LOCAL Melbourne time (AEST/AEDT).
            // Convert it to UTC before storing it in the RTC.
            // The Timezone library automatically applies the correct DST offset.
            hh = digitDate[8] * 10 + digitDate[9];
            mm = digitDate[10] * 10 + digitDate[11];
            ss = 00;
            dd = digitDate[0] * 10 + digitDate[1];
            nn = digitDate[2] * 10 + digitDate[3];
            yy = digitDate[4] * 1000 + digitDate[5] * 100 + digitDate[6] * 10 + digitDate[7];


            // the following is used to upload the date-time to the RTC from the keypad entry
            tm.Year = CalendarYrToTm(yy);
            tm.Month = nn;
            tm.Day = dd;
            tm.Hour = hh;
            tm.Minute = mm;
            tm.Second = ss;
            utc = ausET.toUTC(makeTime(tm));
            RTC.set(utc);        //use the time_t value to ensure correct weekday is set
            setTime(utc);


            cancelTimeSetting = millis();  // set in case time_date single stage not set within 20 seconds
            for (int i = 0; i < 14; i++) {
              digitDate[i] = digitDateReset[i];
            } // end for
            tempDateTime = 0;
            hash = 0;
            cdn = 0;
            break;

          case 67:
            // keypad 2 pressed to increment the date-time value
            cancelTimeSetting = millis();
            if (digitDate[cdn] = 13) {
              // it's in the middle of flashing, so set the value back correctly before continuing
              digitDate[cdn] = tempDateTime;
            } // end if

            if (cdn == 0) {
              // this is the tens on the date which ranges 0,1,2 or 3 only
              if (digitDate[cdn] > 2) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 0

            if (cdn == 2) {
              // this is the tens on the month which ranges 0 or 1 only
              if (digitDate[cdn] > 0) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 2

            if (cdn == 3 && digitDate[2] == 1) {
              // this is the ones on the month when tens is 1
              if (digitDate[cdn] > 1) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 3

            if (cdn == 8) {
              cdn = 8;
              // this is the tens hours which ranges 0,1 or 2 only
              if (digitDate[cdn] > 1) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 8

            if (cdn == 9 && digitDate[8] == 2) {
              // this is the ones hours which ranges 0,1,2 or 3 only
              if (digitDate[cdn] > 2) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 9

            if (cdn == 9 && digitDate[8] != 2) {
              // this is the ones hours which ranges 0 to 9
              if (digitDate[cdn] > 8) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 9

            if (cdn == 10) {
              // this is the ones hours which ranges 0 to 5 only
              if (digitDate[cdn] > 4) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 10

            if (cdn != 0 && cdn != 2 && cdn != 8 && cdn != 9 && cdn != 10) {
              if (digitDate[cdn] > 8) {
                digitDate[cdn] = 0;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]++;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
            } // end if cdn options


          case 73:
            // keypad 8 pressed to decrement the date-time value
            cancelTimeSetting = millis();
            if (digitDate[cdn] = 13) {
              // it's in the middle of flashing, so set the value back correctly before continuing
              digitDate[cdn] = tempDateTime;
            } // end if

            if (cdn == 0) {
              // this is the tens on the date which ranges 0,1,2 or 3 only
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 3;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 0

            if (cdn == 2) {
              // this is the tens on the month which ranges 0 or 1 only
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 1;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 2

            if (cdn == 3 && digitDate[2] == 1) {
              // this is the ones on the month when tens is 1
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 2;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 3

            if (cdn == 8) {
              cdn = 8;
              // this is the tens hours which ranges 0,1 or 2 only
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 2;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 8

            if (cdn == 9 && digitDate[8] == 2) {
              // this is the ones hours which ranges 0,1,2 or 3 only
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 2;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 9

            if (cdn == 9 && digitDate[8] != 2) {
              // this is the ones hours which ranges 0 to 9
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 9;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 9

            if (cdn == 10) {
              // this is the ones hours which ranges 0 to 5 only
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 5;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              }  // end else
              break;
            } // end if cnd = 10

            if (cdn != 0 && cdn != 2 && cdn != 8 && cdn != 9 && cdn != 10) {
              if (digitDate[cdn] < 1) {
                digitDate[cdn] = 9;
                tempDateTime = digitDate[cdn];
                break;
              } // end if
              else {
                digitDate[cdn]--;
                tempDateTime = digitDate[cdn];
                break;
              } // end else
            } // end if cdn options

          case 71:
            // keypad 6 pressed to go to next digit
            cancelTimeSetting = millis();
            if (digitDate[cdn] = 13) {
              // it's in the middle of flashing, so set the value back correctly before continuing
              digitDate[cdn] = tempDateTime;
            } // end if
            tempDateTime = digitDate[cdn + 1];
            if (cdn > 10) {
              cdn = 0;
              break;
            } // end if
            else {
              cdn++;
              break;
            } // end else

          case 69:
            // keypad 4 to go back to previous digit
            cancelTimeSetting = millis();
            if (digitDate[cdn] = 13) {
              // it's in the middle of flashing, so set the value back correctly before continuing
              digitDate[cdn] = tempDateTime;
            } // end if
            tempDateTime = digitDate[cdn - 1];
            if (cdn < 1) {
              cdn = 12;
              break;
            } // end if
            else {
              cdn--;
              break;
            } // end else
        } // end switch
        dataReceived = 0; // as data has just been received
      } // end if



      // This looks firstly for a "~" then the transmitted character, then an "!" so data is validated
      if ((dataReceived != 126) && (dataReceived != 33) && FlagStart == 1) {
        CmdChar = dataReceived;  // capture the received main data value (ascii)
        FlagStart = 0;
      } // end if

      // Looking for "~" mark to start command
      if (dataReceived == 126) {
        CmdChar = 0;
        FlagStart = 1;  // acknowledged that the "~" was received at the start of transmission
      } // end if

    } // end while myRadio.available
  } // end if myRadio.available
} // end void keyRead

// end program ---------------------------

The DS3231 is used for both checking the time periodically as well as checking the temperature periodically. The temperature is being read correctly as the same code is used on the 2 scoreboards and test board at home.

The modules however are not labelled DS3231, however I bought 5 from the one supplier together. Regardless, all the modules I've used work at home and on scoreboard 1, just not scoreboard 2.

The only part I haven't interchanged is the main board. But here's the thing. I've run the DS3231 directly of the Arduino Uno with short jumper wires. So I've bypassed the main board. But I still get the display error. It can't be the main board. It "feels" to me as their a problem with the Uno's. But all of them display correctly at home.

@gilshultz I don't have a great schematic - a bit of a novice with electronics. But below is a print I did some time back that showed the setup sort of. Code I've attached in reply elsewhere in this thread.
Not sure what the voltage and current draw is exactly - it's been some time since measured that. However the error also happened with all digits bar the temperature disconnected.
As for #8 key on the remote, it's simply a test to check that each LED digit works correctly - all LED lights up, i.e. not broken strings of LEDs. #2 button checks that the arduino can send out a signal to each digit from 1 to 9 and 0.

Your assembly looks fine, but this sentence could be a worry..!

What are the ‘push in fittings’, are they tested and reliable ?

Sorry, I think it's called a header. I have jumper wires connecting the DS3231 to a "header" on the board. Then a traces goes to a pair of thru holes that I then soldered a set of jumper wires that go to the arduino shield (A4 and A5). However, I by passed this (DS3231 connected straight to arduino), but same temperature display issue.

DS3231 might be overheating when enclosed.

@xfpd good thought. But it was around 8c on the day outside. If it works at home at 18c, it should work first thing at 8c onsite.

Code will not compile, are you sure you posted the correct sketch? RTC is not defined, there are a few if statements where "=" is used instead of "==", switch statement where a few cases have the "break" inside an if statement, etc.

@david_2018 , I should have said that since I wrote this code back in 2016 originally, I was using an older Arduino version. I did update only to 1.8.19 which does compile it correctly.

The libraries for DS3231 are called up under the library section, line 110 and the "wire.h" library in line 113:

//--[libraries]---------------------------
#include <DS3232RTC.h>                    //http://github.com/JChristensen/DS3232RTC
...
#include <Wire.h>                         //http://arduino.cc/en/Reference/Wire

The main code for the RTC are on line 393 to 466 :

//--[for clock time check and setup]------
void usage (void) {

  // at startup, show some information about program usage and check RTC operational
  Serial.println(F("\nThe time on the RTC is to be set to UTC (Universal Coordinated Time)"));
  Serial.println(F("In melbourne, AEST (Australian Eastern Standard Time) is UTC + 10 hours"));
  Serial.println(F("In melbourne, AEDT (Australian Eastern Daylight saving Time) is UTC + 11 hours"));
  Serial.println(F("To set the UTC date & time via serial monitor:"));
  Serial.println(F("  a. Set carriage return and new line in the monitor"));
  Serial.println(F("  b. Set the appropriate baud rate (115200?)"));
  Serial.println(F("  c. Type in the following UTC time format:  yyyy,mm,dd,hh,mm,ss"));
  Serial.print(F("\nInitialize RTC ..."));
  //setSyncProvider() causes the Time library to synchronize with the
  //external RTC by calling RTC.get() every five minutes by default
  setSyncProvider(RTC.get);
  Serial << F("\nRTC Sync");
  if (timeStatus() != timeSet) Serial << F("Unable to sync with the RTC");
  Serial << endl;
  currentTemp = (RTC.temperature() / 4);
  delay(100);  // delay to allow user to read the above on first startup of serial monitor
} // end usage loop


//--[Time & date upload via Serial monitor]---
void serialTimeSet(void) {
  static time_t utcLast;
  time_t utc;
  tmElements_t tm;
  //check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
  if (Serial.available() >= 12) {
    //note that the tmElements_t Year member is an offset from 1970,
    //but the RTC wants the last two digits of the calendar year.
    //use the convenience macros from Time.h to do the conversions.
    int y = Serial.parseInt();
    if (y >= 100 && y < 1000)
      Serial << F("Error: Year must be two digits or four digits!") << endl;
    else {
      if (y >= 1000)
        tm.Year = CalendarYrToTm(y);
      else    //(y < 100)
        tm.Year = y2kYearToTm(y);
      tm.Month = Serial.parseInt();
      tm.Day = Serial.parseInt();
      tm.Hour = Serial.parseInt();
      tm.Minute = Serial.parseInt();
      tm.Second = Serial.parseInt();
      utc = makeTime(tm);
      RTC.set(utc);        //use the time_t value to ensure correct weekday is set
      setTime(utc);
      Serial << F("RTC set to: ");
      printDateTime(utc, "UTC");
      Serial << endl;
      //dump any extraneous input
      while (Serial.available() > 0) Serial.read();
    } // end if statement
  } // end if statement

  //get the current time
  utc = now();
  if (utc != utcLast) {          //display once per second
    utcLast = utc;
    //    printDateTime(utc, "UTC  ");                            // not sure what this is
    //    printDateTime(ausET.toLocal(utc, &tcr), tcr -> abbrev); // not sure about this either
    local = ausET.toLocal(utc, &tcr);

    if (second(utc) == 0) {  //display temperature once per minute
      float c = RTC.temperature() / 4.;
      float f = c * 9. / 5. + 32.;
      //      Serial << F("  ") << c << F(" C  ") << f << F(" F");  // dont need this in Aussie land!
      currentTemp = (RTC.temperature() / 4);
    } // end if statement
    Serial << endl;
  } // end if statement
} // end serialTimeSet loop

The wire library communicates with the DS3231 over I²C. The wire library knows A4 as SDA and A5 as SCL. In regards to the where = is used instead of ==, not sure where you're referring to. There is one on line 999 which deals with a siren, however I didn't connect the siren so maybe that section doesn't work. But it shouldn't affect the temperature. PS. I'm only self taught with coding, hence there may be some "odd" things in my code.

@david_2018 such as this?

            if (digitDate[cdn] = 13) {
              // it's in the middle of flashing, so set the value back correctly before continuing
              digitDate[cdn] = tempDateTime;
            } // end if

Yeah. Don't touch it. It's not our OP's present problem, but it does indicate trouble ahead.

@cjcjcjcj these aren't "odd things". If you declare that the program works, then somewhere in all that code, you've managed to "climb over" this error (which, by the way, occurs four times, just for the value 13; I didn't look further; lines 1370, 1498, 1625, 1642, for what it's worth). That means there will be code in there that doesn't belong, papering over the problem it introduces. And, when you repair those four lines, it's quite likely that the problems introduced will be gnarly, and you'll wonder why we suggest you fix it.

However, as this isn't (I think) related to your present problem, you're free to ignore it.

I had to revert to version 1.3.0 of the DS3232RTC library to get the code to compile, later versions of that library made changes that are incompatible with your code.

@camsysca , yes as a purist, I should fix those errors that have been pointed out, but unfortunately it's a little out of my league. Also, I'm in the philosophy here, if it's not broke, don't touch it. I can't see the code is the issue. It's only on scoreboard 2 it doesn't work. But it does on scoreboard 1 and my equal setup at home.

Well in that case I will bid you adieu.

I would not be concerned with the problems that I posted, that was just to question if this was the correct sketch. Since this has been running properly for years, I would not worry about it now.

Are you able to connect a computer to the Arduino while it is installed in the scoreboard, to verify that the DS3231 is actually detected? If you have a multimeter verify that there is continuity between the A4 & A5 pins of the UNO and the DS3231 module SDA & SCL, and also for the GND and 5V connections. Its possible there is a break in the connection somewhere on your circuit board. The clock will run even if the DS3231 is not detected, but it will return a temperature of 0 degrees.

If it fails only on scoreboard two despite you moving parts around then that's a resonable indication that the problem is with the scoreboard2 hardware so I second the suggestion posted by @david_2018 . Check for a broken track or cracked solder joint on the reverse side of the PCB where the header is mounted that is the connection point for the I2C signals.

@david_2018 , I think your spot on. I didnt think about that. The DS3241 may infact not even be signalling the time. Initially I have to set the current date and time via a sequence on the keypad of my remote transmitter. Then from memory, the clock module simply updates the time ever so often in case the time runs out. So maybe "both" the temperature and time isnt transmitting to the Arduino somehow.

Continuity - I disconected the wires from the module to the board, then connected it directly to the Arduino with 4 new wires. 00c reading still.

Computer to the Arduin9 onsite is really akward, hence the reason I made all components removeable / replaceable. Maybe I have to bite the bullet and replace the main board as well and see the outcome.