@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 ---------------------------