Thursday, November 28, 2013

39. YRTa - Version 'a' of the Yacht Race Timer

6000 page views!!
So I finally got my real time clock (RTC) - all the way from China, at £2.78 including battery and P&P!  And it works!  Reading around these on the web I got the impression that some of them don't work, but mine works a treat (I haven't tested how good the time-keeping is, but I'll need a few weeks to do that).  I did have some trouble getting the software libraries going, but when I deleted all previous attempts and re-downloaded them from scratch, this seemed to do the trick.  You have to solder on a header for the breadboard, but that's no problem.  Here's mine:



The dimensions are approximately 1 inch by 1 inch.  The other side looks like this:


There's a 3.6V rechargeable LIR2032 lithium battery inserted underneath for which a full charge lasts for about a year, although it trickle-charges from the Arduino power supply.  You can see where I have soldered a 4-pin header (this can be seen on the left hand side of the upper image, and along the bottom of the lower image) for insertion into the breadboard.  

Apart from VCC (5V) and GND, only the serial data line (SDA) and serial clock (SCL) connections of the I²C system are necessary.  These connections are repeated along with some other connections, on the right hand side of the upper image.  When you first connect this up to the Arduino, you need to run the SetTime example sketch to set the time to the PC's time, and running the ReadTest sketch verifies that the RTC's date and time has been set.

Here is the latest configuration of the Yacht Race Timer, named YRTa:


You can see that I have re-arranged the layout on the LCD display.  The photo above shows, on the first line, that an "A plus B" - ie a 1-fleet sequence with all boats starting together, has already been started.  On the top left, the first symbol indicates that a flag - the AP (postponement) flag - is flying and that the time of day is 09:05.  The second line displays the time in hours, minutes and seconds, of the sequence to or from the start.

In the middle of the display is a large numeral showing the count-down seconds to the next critical point. The 3rd line shows the current date.  The bottom line shows the next flag to move - the AP flag will come down in 4 seconds.

Here is a snapshot of another situation:


This shows that there has already been an "A then B" ie a 2-fleet, sequence start.  The 8 symbols on the top left show that the flags have been raised and lowered for the first fleet, then for the second fleet.  The second line shows that the race has been started (for the second fleet) more than 3 hours.  (The first fleet will have started exactly 5 minutes before this). The 3rd line shows the finishing time for the first boat and the 4th line shows the finishing time of, in this case, the 4th boat followed by a warning that this finishing time is more than 30 minutes after the first finishing time.

As before, the first button when pressed, records the finishing time of each boat passing through the finish line.  The second button allows you to step back, at any time, through finishing times as far as the 2nd boat, and the 3rd (red) button is for setting the starting sequence time in minutes.  If not pressed within a few seconds of an Arduino reset (using the "RESET" button on the Arduino, or simply powering up the Arduino), the start sequence defaults to an "A plus B" (ie one-fleet) sequence, at a few seconds before 6 minutes.

Extra attributes which have been added to this version include:
  • Current date and time (from the RTC) displayed
  • Numerals 9 to 0 for the large-character count-down warning (previously 5 to 0)
  • Indication of the next flag change to be made after the 9-second countdown.  eg for the "A then B" sequence:
    • "Next flag = AP DOWN "              
      Postponement over (only used if the start is delayed)  T0-11
    • "Next flag = CLASS UP"                                          
                                                                          A-fleet flag  T0-10
    • "Next flag = PREP UP "                                     
                                                          4-minute preparatory  T0-9
    • "Next flag=PREP DOWN "                                
                                                          4-minute preparatory  T0-6
    • "Next = CLASS DN + UP"        &      
                                                                    A-fleet starts       T0-5  
    • "Next flag = PREP UP "                                     
                                                          4-minute preparatory  T0-4
    • "Next flag=PREP DOWN "                                
                                                         4-minute preparatory   T0-1
    • "Next flag=CLASS DOWN"     
                                                                       B-fleet starts  
      T0   
There are other flags flying, but above are the ones involved in the starting sequence at our Club.  When there is a 1-fleet start, the A-fleet flag and the B-fleet flag are raised and lowered together at T0-5 mins and Trespectively.

The YRTa contains all the attributes needed to control the flags and horn sounds for not only one, but 2 different starting sequences, and carries out an automatic count-down/count-up sequence allowing a single button to be pressed to record the finishing time of each boat passing through the finish line.  It even alerts the Race Officer if any finishing time is outside the time limit - currently set at 30 minutes after the first boat.  It not only prompts the Race Officer to get ready to lower or raise the next appropriate flag, but it tells him which flag it is!  

After the race, it allows all the finishing times to be inspected for calculation using a different system - ie writing down on a sheet for later PC entry.  Fancy downloading to a PC is possible, but the finishing times have to be written down anyway, so downloading is un-necessary.

Because the display space is limited, only essential information is displayed at any one time, so after use, information is removed or replaced, keeping the display uncluttered, but indicating exactly at what stage the proceedings are.

All this while displaying the time of day and the date - very useful!  

Note that the timing part still makes use of the millis() function of the Arduino (modified by a tweaking factor to maximise accuracy) and not the RTC - it is used only for the date and time display.  Maybe it would be worth trying to use the seconds from the RTC's tmElements_t.Second function from the Time library in case more accuracy can be obtained.  Further accuracy could be got from a slightly more expensive RTC: The ChronoDot (ref http://www.amazon.co.uk/ChronoDot-Ultra-precise-Real-Time-Clock/dp/B007XEV79O/ref=wl_it_dp_o_pC_nS_nC?ie=UTF8&colid=2CD3HRH1RXYAP&coliid=I35FS3VXMIP2A6#productDescription) based on the DS3231 temperature compensated RTC is said to be ultra-accurate because it has built-in temperature compensation.

Because the Arduino can always be brought back to the PC for programming, things can be changed (eg the 30 minute warning, or the time accuracy adjustment factor).

Here is the complete circuit diagram:



Here is the full code listing:
1:  /*  
2:   KCTiming  
3:   Arduino Yacht Race Timer using the LiquidCrystal Library  
4:   Demonstrates the use of a 20 column x 4 row LCD display. The LiquidCrystal library works with all   
5:   LCD displays that are compatible with the Hitachi HD44780 driver.   
6:   This sketch prints count-down / count-up times to the LCD - and more!.  
7:   The circuit:  
8:   * LCD RS pin to digital pin 12  
9:   * LCD Enable pin to digital pin 11  
10:   * LCD D4 pin to digital pin 5  
11:   * LCD D5 pin to digital pin 4  
12:   * LCD D6 pin to digital pin 3  
13:   * LCD D7 pin to digital pin 2  
14:   * LCD R/W pin to ground  
15:   * Variable (eg 10K) resistor:  
16:     - ends to +5V and ground   
17:     - wiper to LCD VO pin (LCD pin 3)  
18:   Library originally added 18 Apr 2008 by David A. Mellis. Library modified 5 Jul 2009 by Limor Fried  
19:   Example added 9 Jul 2009 by Tom Igoe. Modified 22 Nov 2010 by Tom Igoe. Adopted and adapted by KC Oct 2013  
20:  */  
21:  // Include the library code:  
22:  #include <LiquidCrystal.h>  
23:  // Include libraries for the Real Time Clock  
24:  #include <DS1307RTC.h>  
25:  #include <Time.h>  
26:  #include <Wire.h>  
27:  // Make a new LiquidCrystal object and call it lcd with the numbers of the interface pins  
28:  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  
29:  // Array of bits defining pixels for 4 custom characters  
30:  // ...pixel=1 : on and pixel=0 : off  
31:  // See Custom Character Generator at http://omerk.github.io/lcdchargen/  
32:   byte oneflagdown[8] =   
33:    {0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01100, 0b01100};  // 1 flag down  
34:   byte twoflagsup[8]  =    
35:    {0b11011, 0b11011, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010};  // 2 flags up  
36:   byte oneflagup[8]  =   
37:    {0b01100, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100};  // 1 flag up  
38:   byte twoflagsdown[8] =   
39:    {0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b11011, 0b11011};  // 2 flags down  
40:  // see Arduino Cookbook 2nd ed by Michael Margolis (only 4 glyphs are needed)  
41:   byte glyphs[4][8] = {  
42:    {0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000},  
43:    {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111},  
44:    {0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111},  
45:    {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}};  
46:   const int digitWidth = 3;              // the width in characters of a big digit  
47:                                          // (excludes the space between characters)  
48:   // Here are arrays to index into custom characters that will make up the big numbers:  
49:   // ...(ASCII code 32 represents the space, or null (blank) character):  
50:   // Digits 0 - 4  (top halves)      0   1     2   3    4  
51:   const char bigDigitsTop[10][digitWidth]={3,0,3, 0,3,32,  2,2,3, 0,2,3,  3,1,3,  
52:   // Digits 5 - 9  (top halves)      5   6     7   8    9  
53:                        3,2,2, 3,2,2,  0,0,3, 3,2,3,  3,2,3};  
54:   // Digits 0 - 4  (bottom halves)     0   1     2   3    4  
55:   const char bigDigitsBot[10][digitWidth]={3,1,3, 1,3,1,  3,1,1, 1,1,3, 32,32,3,  
56:   // Digits 5 - 9  (bottom halves)     5   6     7   8    9  
57:                        1,1,3, 3,1,3, 32,32,3, 3,1,3,  1,1,3};  
58:   int button1 = 6;  
59:   int button2 = 7;  
60:   int button3 = 8;  
61:   int outPin = 13;                        // the number of the output pin (LED)  
62:   int reading1, reading2, reading3;  
63:   long debounce = 200;                    // debounce delay in milliseconds  
64:   int i = 2;                              // which LCD row to print resul  
65:   int sec00 = 0;  
66:   int j;  
67:   int timeset = 371;  // default countdown seconds (a few secs longer than are displayed)  
68:   int countdownMinutes = 0;  
69:   int loopCounter = 0;  
70:   const int BOAT_COUNT = 99;              // maximum number of boats accommodated  
71:   int finish_time[BOAT_COUNT];            // array of finish times  
72:  void setup() {  
73:   // Set up the LCD's number of columns and rows:   
74:   lcd.begin(20, 4);                       // 20 columns & 4 rows  
75:   lcd.createChar(4, oneflagdown);         // create first custom character  
76:   lcd.createChar(5, twoflagsup);          // create second custom character  
77:   lcd.createChar(6, oneflagup);           // create third custom character  
78:   lcd.createChar(7, twoflagsdown);        // create fourth custom character  
79:   for(int i=0; i < 4; i++)  
80:    lcd.createChar(i, glyphs[i]);  
81:   lcd.clear();   
82:   // Print the header on the LCD  
83:   lcd.setCursor(10,0);  
84:   lcd.print("YRTa");                      // for "Yacht Race Timer - version a"  
85:   pinMode(button1, INPUT);  
86:   pinMode(button2, INPUT);  
87:   pinMode(button3, INPUT);  
88:   //Set up for the RTC  
89:   //Serial.begin(9600);  
90:   //while (!Serial); //wait for serial  
91:   //delay(200);  
92:   lcd.setCursor(0,1);  
93:   lcd.print("Set c/d");  
94:  }  
95:  void loop() {  
96:   tmElements_t tm;  
97:   if (RTC.read(tm)) {  
98:    lcd.setCursor(15,0);  
99:    print2digits(tm.Hour);lcd.print(":");  
100:    print2digits(tm.Minute);  
101:    lcd.setCursor(12,2);  
102:    print2digits(tm.Day);lcd.print("-");  
103:    print2digits(tm.Month);lcd.print("-");  
104:    print2digits(tmYearToCalendar(tm.Year));    
105:   }  
106:   /* else {  
107:   if(RTC.chipPresent()){  
108:    Serial.println("The DS1307 has stopped. Please run the SetTime example");  
109:    Serial.println("sketch to initialise the time and begin running.");  
110:    Serial.println();  
111:   }  
112:   else{  
113:    Serial.println("DS1307 read error! Please check the circuitry.");  
114:    Serial.println();  
115:    }  
116:   }*/  
117:   loopCounter++;  
118:   if (loopCounter == 1)  
119:   {   
120:    for(int l=0; l<60; l++)  
121:    { delay(100);  
122:     reading3 = digitalRead(button3);  
123:     if (reading3 == HIGH)  
124:     { delay(debounce);                          // in case the button bounces  
125:      countdownMinutes++;  
126:      timeset = countdownMinutes*60;  
127:      lcd.setCursor(9,1);  
128:      lcd.print(countdownMinutes); } } }  
129:   int time = -timeset;                          // countdown seconds before time zero  
130:   long sec0 = millis()*1.0000/998.750991;       // correction for milli-seconds slow/fast  
131:   //long sec0 = millis()/1000;                  // alternative with no correction  
132:   long secs = sec0 + time;  
133:  // Call the routine for the preferred sequence  
134:   if (timeset < 660)  
135:    {twoFleetsTogether(secs);  
136:   }  
137:   else  
138:    {A_then_B(secs);  
139:    lcd.setCursor(11,1);  
140:    lcd.print(" A then B");}   
141:   clockDisplay(0, 1, secs);                    // display the running time before/after time zero   
142:   reading1 = digitalRead(button1);             // listen for button press  
143:   if (reading1 == HIGH)                        // if the button is pressed  
144:   { delay(debounce);                           // in case the button bounces  
145:    button1pressed(secs); i++;                  // move on to next line for next time  
146:    j = i-1; }                                  // new counter for button2pressed()  
147:   reading2 = digitalRead(button2);             // listen for button press  
148:   if (reading2 == HIGH)                        // if the button is pressed  
149:   {delay(debounce);                            // in case the button bounces  
150:    button2pressed(j);  
151:    j--;}                                       // scroll back through finish times  
152:  }  
153:  void twoFleetsTogether (long s){              // single start (bothe fleets together)  
154:   if (s < -360){lcd.setCursor(0, 0);lcd.write(6);lcd.setCursor(0,3);lcd.print("Next flag = AP DOWN ");}   // postponement flag up  
155:   if (s == -369 || s == -309 || s == -249 || s == -69 || s == -9) showDigit(9, 5);                        // big number countdown  
156:   if (s == -368 || s == -308 || s == -248 || s == -68 || s == -8) showDigit(8, 5);  
157:   if (s == -367 || s == -307 || s == -247 || s == -67 || s == -7) showDigit(7, 5);  
158:   if (s == -366 || s == -306 || s == -246 || s == -66 || s == -6) showDigit(6, 5);  
159:   if (s == -365 || s == -305 || s == -245 || s == -65 || s == -5) showDigit(5, 5);                        // big number countdown  
160:   if (s == -364 || s == -304 || s == -244 || s == -64 || s == -4) showDigit(4, 5);  
161:   if (s == -363 || s == -303 || s == -243 || s == -63 || s == -3) showDigit(3, 5);  
162:   if (s == -362 || s == -302 || s == -242 || s == -62 || s == -2) showDigit(2, 5);  
163:   if (s == -361 || s == -301 || s == -241 || s == -61 || s == -1) showDigit(1, 5);  
164:   if (s == -360 || s == -300 || s == -240 || s == -60 || s == 0) showDigit(0, 5);  
165:   if (s == -359 || s == -299 || s == -239 || s == -59 || s == +1)  
166:    {lcd.setCursor(8, 1);lcd.print("  "); lcd.setCursor(8, 2);lcd.print("  ");}                            // clear big digit  
167:   if (s == -360){lcd.setCursor(0, 0);lcd.write(4);lcd.setCursor(0,3);lcd.print("Next flag = CLASS UP");}  // display first character at 6 minutes (1 flag down)  
168:   if (s == -300){lcd.setCursor(0, 0);lcd.write(5);lcd.setCursor(0,3);lcd.print("Next flag = PREP UP ");}  // display second character at 5 minutes (2 flags up)  
169:   if (s == -240){lcd.setCursor(1, 0);lcd.write(6);lcd.setCursor(0,3);lcd.print("Next flag=PREP DOWN ");}  // display third character (1 flag up)  
170:   if (s ==  -60){lcd.setCursor(2, 0);lcd.write(4);lcd.setCursor(0,3);lcd.print("Next flag=CLASS DOWN");}   // display first character (1 flag down)  
171:   if (s ==    0){lcd.setCursor(3, 0);lcd.write(7);lcd.setCursor(0,3);lcd.print("          ");}  // display fourth character (2 flags down)   
172:  }  
173:  void A_then_B (long s){                                           // two separate fleet starts  
174:   if (s < -660){lcd.setCursor(0, 0);lcd.write(6);lcd.setCursor(0,3);lcd.print("Next flag = AP DOWN ");}   // postponement flag up  
175:   if (s == -669 || s == -609 || s == -549 || s == -369 || s == -309) showDigit(9, 5);                     // big number countdown  
176:   if (s == -668 || s == -608 || s == -548 || s == -368 || s == -308) showDigit(8, 5);  
177:   if (s == -667 || s == -607 || s == -547 || s == -367 || s == -307) showDigit(7, 5);  
178:   if (s == -666 || s == -606 || s == -546 || s == -366 || s == -306) showDigit(6, 5);   
179:   if (s == -665 || s == -605 || s == -545 || s == -365 || s == -305) showDigit(5, 5);                     // big number countdown  
180:   if (s == -664 || s == -604 || s == -544 || s == -364 || s == -304) showDigit(4, 5);  
181:   if (s == -663 || s == -603 || s == -543 || s == -363 || s == -303) showDigit(3, 5);  
182:   if (s == -662 || s == -602 || s == -542 || s == -362 || s == -302) showDigit(2, 5);  
183:   if (s == -661 || s == -601 || s == -541 || s == -361 || s == -301) showDigit(1, 5);  
184:   if (s == -660 || s == -600 || s == -540 || s == -360 || s == 300) showDigit(0, 5);  
185:   if (s == -659 || s == -599 || s == -539 || s == -359 || s == +301)  
186:    {lcd.setCursor(8, 1);lcd.print("  "); lcd.setCursor(8, 2);lcd.print("  ");}                            // clear big digit  
187:   if (s == -369 || s == -309 || s == -249 || s == -69 || s ==  -9) showDigit(9, 5);                       // big number countdown  
188:   if (s == -368 || s == -308 || s == -248 || s == -68 || s ==  -8) showDigit(8, 5);  
189:   if (s == -367 || s == -307 || s == -247 || s == -67 || s ==  -7) showDigit(7, 5);  
190:   if (s == -366 || s == -306 || s == -246 || s == -66 || s ==  -6) showDigit(6, 5);    
191:   if (s == -365 || s == -305 || s == -245 || s == -65 || s ==  -5) showDigit(5, 5);                       // big number countdown  
192:   if (s == -364 || s == -304 || s == -244 || s == -64 || s ==  -4) showDigit(4, 5);  
193:   if (s == -363 || s == -303 || s == -243 || s == -63 || s ==  -3) showDigit(3, 5);  
194:   if (s == -362 || s == -302 || s == -242 || s == -62 || s ==  -2) showDigit(2, 5);  
195:   if (s == -361 || s == -301 || s == -241 || s == -61 || s ==  -1) showDigit(1, 5);  
196:   if (s == -360 || s == -300 || s == -240 || s == -60 || s ==  0) showDigit(0, 5);  
197:   if (s == -359 || s == -299 || s == -239 || s == -59 || s ==  +1)  
198:    {lcd.setCursor(8, 1);lcd.print("  "); lcd.setCursor(8, 2);lcd.print("  ");}                            // clear big digit  
199:   if (s == -660){lcd.setCursor(0, 0);lcd.write(4);lcd.setCursor(0,3);lcd.print("Next flag = CLASS UP");}  // display first character at 11 minutes (1 flag down)  
200:   if (s == -600){lcd.setCursor(0, 0);lcd.write(5);lcd.setCursor(0,3);lcd.print("Next flag = PREP UP ");}  // display second character at 10 minutes (2 flags up)  
201:   if (s == -540){lcd.setCursor(1, 0);lcd.write(6);lcd.setCursor(0,3);lcd.print("Next flag=PREP DOWN ");}  // display third character (1 flag up)  
202:   if (s == -360){lcd.setCursor(2, 0);lcd.write(4);lcd.setCursor(0,3);lcd.print("Next = CLASS DN + UP");}  // display first character (1 flag down)  
203:   if (s == -300){lcd.setCursor(3, 0);lcd.write(7);}                             // display fourth character (A-Fleet flag down)   
204:   if (s == -300){lcd.setCursor(5, 0);lcd.write(5);lcd.setCursor(0,3);lcd.print("Next flag = PREP UP ");}  // display second character (B-Fleet flag up)  
205:   if (s == -240){lcd.setCursor(6, 0);lcd.write(6);lcd.setCursor(0,3);lcd.print("Next flag=PREP DOWN ");}  // display third character (1 flag up)  
206:   if (s ==  -60){lcd.setCursor(7, 0);lcd.write(4);lcd.setCursor(0,3);lcd.print("Next flag=CLASS DOWN");}   // display first character (1 flag down)  
207:   if (s ==    0){lcd.setCursor(8, 0);lcd.write(7);lcd.setCursor(0,3);lcd.print("          ");}              // display fourth character (2 flags down)   
208:  }  
209:  void clockDisplay(int x, int y, long s){  
210:   // Display hours, mins, secs from time zero, at required position  
211:   int mins = s/60;  
212:   int hrs = mins/60;  
213:   long secs = s - (mins*60);  
214:   mins = mins - (hrs*60);  
215:   lcd.setCursor(x,y);  
216:   if (s > 0)  
217:    lcd.print("+");  
218:   else if (s < 0)  
219:    lcd.print ("-");  
220:   else  
221:    lcd.print (" ");                            // .. THEY'RE OFF!!  
222:   lcd.setCursor(x+1, y);lcd.print(abs(hrs));lcd.print (":"); // trailing colon  
223:   lcd.setCursor(x+3, y);  
224:   if (abs(mins)<10)                            // include a leading zero if less than 10  
225:    lcd.print("0" + String(abs(mins)));  
226:   else   
227:    lcd.print(abs(mins));  
228:   lcd.print (":");                             // trailing colon  
229:   lcd.setCursor(x+6, y);  
230:   if (abs(secs)<10)                            // include a leading zero if less than 10  
231:    lcd.print("0" + String(abs(secs)));  
232:   else   
233:    lcd.print(abs(secs));  
234:   //lcd.print(" ");  
235:  }  
236:  void button1pressed(long s){                  // press button to capture finishing times  
237:   lcd.setCursor(0, i);  
238:   if ((i-1) < 10)  
239:    lcd.write(" ");                             // tidy up spacing if number less than 10  
240:   lcd.print(i-1);  
241:   clockDisplay(3, i, s);  
242:   finish_time[i-2] = s;                        // put first, 2nd, etc finish times into the array  
243:   if (i == 2)  
244:    sec00 = s;                                  // remember first boat's time  
245:   else if ((s-sec00) > (30*60))                // compare this one with first boat's time  
246:    lcd.write(" >30 min!");                     // and give a warning if it's out of time  
247:   else  
248:    lcd.write("     ");                         // otherwise clear this part of the display  
249:  }  
250:  void button2pressed(int ii){                  // scroll back through finish times  
251:   if((ii-2)>1)  
252:   {lcd.setCursor(0, 3);  
253:    if ((ii-2) < 10)  
254:     lcd.write(" ");                            // tidy up spacing if number less than 10  
255:    lcd.print(ii-2);  
256:    clockDisplay(3, 4, finish_time[ii-3]);  
257:    lcd.write(" *    ");}                       // mark with an asterisk to indicate an old finish time  
258:  }  
259:  void showDigit(int digit, int posn){          // display the big digits at desired position  
260:  // lcd.setCursor(posn * (digitWidth + 1), 0);  
261:   lcd.setCursor(8, 1);  
262:   for(int i=0; i < digitWidth; i++)  
263:    lcd.write(bigDigitsTop[digit][i]);          // top half of big digit  
264:  // lcd.setCursor(posn * (digitWidth + 1), 1);  
265:   lcd.setCursor(8, 2);  
266:   for(int i=0; i < digitWidth; i++)  
267:    lcd.write(bigDigitsBot[digit][i]);          // bottom half of big digit  
268:  }  
269:  void print2digits(int number){  
270:   if (number>=0 && number <10){  
271:    lcd.write("0");  
272:   }  
273:   if (number>99){  
274:    number = number-2000;                      // years after the year 2000 (ie a 2-digit year)  
275:   }  
276:   lcd.print(number);  
277:  }  





No comments:

Post a Comment