Browse code

minor revision

gandolf authored on 07/11/2022 04:25:57
Showing 2 changed files
... ...
@@ -2,14 +2,14 @@
2 2
  Background Radiation Monitor - Web Server
3 3
  
4 4
  A simple web server that makes available to clients over the Internet
5
- readings from a MightyOhm Geiger counter. The MightyOhm is connected to
6
- an Arduino Uno with attached Ethernet shield.  This software module
5
+ readings from a MightyOhm Geiger counter. The MightyOhm is connected
6
+ to an Arduino Uno with attached Ethernet shield.  This software module
7 7
  runs on the Arduino Uno an embedded HTTP server by which Internet
8 8
  applications can query the MightyOhm for Geiger counter readings.
9 9
  Also, this software runs a Network Time Protocol (NTP) client, that
10 10
  periodically synchronizes the local system clock to network time.
11
- Included is a simple command line interface that may be used to change the
12
- network interface IP address, NTP server address, or configure a
11
+ Included is a simple command line interface that may be used to change
12
+ the network interface IP address, NTP server address, or configure a
13 13
  verbose output mode.
14 14
  
15 15
  Copyright 2018 Jeff Owrey
... ...
@@ -47,7 +47,7 @@
47 47
  Revision History:  
48 48
    * v10 released 25 Feb 2014 by J L Owrey
49 49
    * v11 released 24 Jun 2014 by J L Owrey
50
-       - optimization of processRxByte function to conserve SRAM
50
+       - optimization of processByteFromMightyOhm function to conserve SRAM
51 51
        - removal of non-used function code
52 52
        - defaults to APIPA IP address in the event a DHCP address
53 53
          cannot be obtained
... ...
@@ -69,6 +69,21 @@
69 69
    * v16 released 16 Sep 2017 by J L Owrey
70 70
        - added capability of rebooting via network http request,
71 71
          i.e., "http://{device IP address}/reset"
72
+   * v17 released 29 Oct 2019 by J L Owrey
73
+       - modified NTP server address user setting to allow fully
74
+         qualified domain names as well as IP addresses.  Default
75
+         NTP address set to "pool.ntp.org" per ntp.org request to use
76
+         (in order to facilitate load balancing) the fully qualified
77
+         domain name instead of individual server IP addresses.
78
+   * v18 released 01 Nov 2019 by J L Owrey
79
+       - fixed a bug in NTP time synchronization whereby the network time
80
+         synchronization would only occur during boot up.  Thereafter NTP 
81
+         time synchronization would fail to happen, resulting in a large 
82
+         amount of clock drift.
83
+   * v19 released 10 Jul 2022 by J L Owrey
84
+       - improved processing of serial data from the MightyOhm Geiger counter
85
+
86
+12345678901234567890123456789012345678901234567890123456789012345678901234567890         
72 87
 */
73 88
 
74 89
 /***  PREPROCESSOR DEFINES  ***/
... ...
@@ -79,8 +94,8 @@
79 94
  Define the header and version number displayed at startup
80 95
  and also by the 'view settings' command.
81 96
 */
82
-#define STARTUP_HEADER "\n\rRadmon v1.6 (c) 2018\n"
83
-#define RADMON_VERSION "v1.6"
97
+#define STARTUP_HEADER "\n\rRadmon v1.9 (c) 2022"
98
+#define RADMON_VERSION "v1.9"
84 99
 /*
85 100
  The following define sets the MAC address of the device.  This
86 101
  address is a permanent attribute of the device's Ethernet interface,
... ...
@@ -110,18 +125,23 @@
110 125
 /*
111 126
  The following defines are for configuring a local NTP client
112 127
  for synchronizing the local system clock to network time.
113
- Note that the default setting is the IP address of the following
114
- time server:
115
-              time-c-b.nist.gov
128
+ Note that the ntp server address should be sent to the local
129
+ server pool of the country where the radmon will be used.  See
130
+ the web site 'ntp.org' for details. Users in the USA should set
131
+ the ntp server to 'us.pool.ntp.org'.
116 132
 */
117
-#define DEFAULT_NTP_SERVER_IP_ADDR "132.163.96.3"
133
+#define DEFAULT_NTP_SERVER_ADDR "us.pool.ntp.org"
118 134
 #define NTP_PORT 8888
119
-#define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message
135
+#define NTP_PACKET_SIZE 48 // NTP time in the first 48 bytes of the message
120 136
 /*
121 137
  The following defines how often the system clock gets synchronized
122 138
  to network time.
123 139
 */
124
-#define NET_SYNCH_INTERVAL 43200 //number in seconds
140
+#define NTP_SYNCH_INTERVAL 43200 // number in seconds - 2 times a day
141
+/*
142
+ Number of retries if first time server request fails.
143
+*/
144
+#define TIME_SERVER_REQUEST_RETRIES 3
125 145
 /*
126 146
  The following defines the size of the buffer space required for the
127 147
  serial data string from the Mighty Ohm Geiger counter.  The serial
... ...
@@ -178,9 +198,9 @@ SoftwareSerial MightyOhmTxOut(5, 6);
178 198
  Create global variables to store the MightOhm data, next heartbeat
179 199
  time, and next synchronization time.
180 200
 */
181
-char mightOhmData[MIGHTYOHM_DATA_STRING_LENGTH + 1];
182
-unsigned long lastSerialUpdateTime;
183
-time_t nextClockSynchTime;
201
+char mightyOhmData[MIGHTYOHM_DATA_STRING_LENGTH + 1];
202
+unsigned long nextSerialUpdateTime = 0;
203
+unsigned long nextClockSynchTime = 0;
184 204
 /*
185 205
  Create global variables to store the verbose mode state (ON or OFF)
186 206
  and the IP address mode state (static or DHCP).
... ...
@@ -189,10 +209,10 @@ boolean bVerbose;
189 209
 boolean bUseStaticIP;
190 210
 /*
191 211
  Create and initialize global arrays to hold the current IP address
192
- and the NTP server IP address.
212
+ and the NTP server address.
193 213
 */
194 214
 byte ipAddr[4];
195
-byte ntpIpAddr[4];
215
+char timeServer[32];
196 216
 
197 217
 /*** SYSTEM STARTUP  ***/
198 218
 
... ...
@@ -215,11 +235,13 @@ void setup()
215 235
    Start up the Ethernet interface using either a static or
216 236
    DHCP supplied address (depending on stored system configuration).
217 237
   */
218
-  if(bUseStaticIP)
238
+  if (bUseStaticIP)
219 239
   {
220 240
     Ethernet.begin(mac, ipAddr);
221
-  } else {
222
-    if ( Ethernet.begin(mac) == 0 )
241
+  }
242
+  else
243
+  {
244
+    if (Ethernet.begin(mac) == 0)
223 245
     {
224 246
       /* DHCP not responding so use APIPA address */
225 247
       parseIpAddress(ipAddr, DEFAULT_APIPA_IP_ADDRESS);
... ...
@@ -228,14 +250,11 @@ void setup()
228 250
     }
229 251
   }
230 252
   Serial.print(F("IP address: ")); Serial.println(Ethernet.localIP());
231
-  /*
232
-   Start up NTP client service.
233
-  */
234
-  Udp.begin(NTP_PORT);
235 253
   /*
236 254
     Synchronize the system clock to network time.
237 255
   */
238 256
   synchronizeSystemClock();
257
+  nextClockSynchTime = now() + NTP_SYNCH_INTERVAL;
239 258
   /*
240 259
    Start up the HTTP server.
241 260
   */
... ...
@@ -245,33 +264,23 @@ void setup()
245 264
     Open serial communications to the MightyOhm device.
246 265
   */  
247 266
   MightyOhmTxOut.begin(9600);
248
-   /*
249
-    Initialize initial time for sending out the hearbeat string. Normally
250
-    the system clock will be at approx 3200 msec at this point. So allow
251
-    some additional time for data to accumulate in MightyOhm data buffer.
252
-  */
253
-  lastSerialUpdateTime = -1;
254 267
   /*
255 268
    Initialize MightyOhm data string to empty.
256 269
   */
257
-  mightOhmData[0] = 0;
270
+  mightyOhmData[0] = 0;
258 271
   return;
259 272
 }
260 273
 
261 274
 /*** MAIN LOOP ***/
262 275
 
263 276
 void loop() {
264
-  long currentTime;
265
-
266
-  currentTime = millis();
267
-  
268 277
   /*
269 278
    Check for user keyboard 'c' pressed.  This character switches
270 279
    to command mode.
271 280
   */   
272
-  if ( Serial.available() ) {
281
+  if (Serial.available()) {
273 282
     // get incoming byte
274
-    if(Serial.read() == 'c') {
283
+    if (Serial.read() == 'c') {
275 284
       commandMode();
276 285
     }
277 286
   }
... ...
@@ -280,8 +289,8 @@ void loop() {
280 289
     Poll serial input buffer from MightyOhm for new data and 
281 290
     process received bytes to form a complete data string.
282 291
   */
283
-  while ( MightyOhmTxOut.available() ) {
284
-    processRxByte( MightyOhmTxOut.read() );
292
+  while (MightyOhmTxOut.available()) {
293
+    processByteFromMightyOhm(MightyOhmTxOut.read());
285 294
   }
286 295
   
287 296
   /*
... ...
@@ -289,9 +298,12 @@ void loop() {
289 298
     serial port at regular intervals.
290 299
   */
291 300
   if (bVerbose) {
292
-    if (abs(millis() - lastSerialUpdateTime) > SERIAL_UPDATE_INTERVAL) {
293
-      lastSerialUpdateTime = millis();
294
-      Serial.println( mightOhmData );
301
+    if (millis() > nextSerialUpdateTime) {
302
+      Serial.println(mightyOhmData);
303
+      /* 
304
+       Set the time for the next serial update to occur.
305
+      */
306
+      nextSerialUpdateTime = millis() + SERIAL_UPDATE_INTERVAL;
295 307
     }
296 308
   }
297 309
   
... ...
@@ -299,54 +311,29 @@ void loop() {
299 311
    Periodically synchronize local system clock to time
300 312
    provided by NTP time server.
301 313
   */
302
-  if ( now() > nextClockSynchTime ) {
314
+  if (now() > nextClockSynchTime) {
303 315
     synchronizeSystemClock();
316
+    /* 
317
+     Set the time for the next network NTP
318
+     time synchronization to occur.
319
+    */
320
+    nextClockSynchTime = now() + NTP_SYNCH_INTERVAL;
304 321
   }
305 322
   
306 323
   /*
307 324
    Listen for and and process requests from HTTP clients.
308 325
   */  
309
-  listenForEthernetClients();
326
+  listenForNetworkClients();
310 327
 
311 328
   #ifdef DEBUG
312 329
     Serial.print("lp time: "); Serial.println(millis() - currentTime);
313 330
   #endif
314 331
 }
315 332
 
316
-/*
317
- Synchronize the local system clock to
318
- network time provided by NTP time server.
319
-*/
320
-void synchronizeSystemClock()
321
-{
322
-  byte count;
323
-  
324
-  Serial.println(F("Synchronizing with network time server..."));
325
-    
326
-  for(count = 0; count < 3; count++)  // Attempt to synchronize 3 times
327
-  {
328
-    if(syncToNetworkTime() == 1)
329
-    {
330
-      //  Synchronization successful
331
-      break;
332
-    }
333
-    delay(1000);
334
-  } /* end for */ 
335
-  if(count == 3) {
336
-    Serial.println(F("synch failed"));
337
-  }
338
-  /* 
339
-   Set the time for the next network NTP
340
-   time synchronization to occur.
341
-  */
342
-  nextClockSynchTime = now() + NET_SYNCH_INTERVAL;
343
-  return;
344
-}
345
-
346 333
 /*
347 334
   Handle HTTP GET requests from an HTTP client.
348 335
 */  
349
-void listenForEthernetClients()
336
+void listenForNetworkClients()
350 337
 {
351 338
   // listen for incoming clients
352 339
   EthernetClient client = httpServer.available();
... ...
@@ -366,12 +353,12 @@ void listenForEthernetClients()
366 353
     firstLineFound = false;
367 354
   
368 355
     /*
369
-     * The beginning and end of an HTTP client request is always signaled
370
-     * by a blank line, that is, by two consecutive line feed and carriage 
371
-     * return characters "\r\n\r\n".  The following lines of code 
372
-     * look for this condition, as well as the url extension (following
373
-     * "GET").
374
-     */
356
+     The beginning and end of an HTTP client request is always signaled
357
+     by a blank line, that is, by two consecutive line feed and carriage 
358
+     return characters "\r\n\r\n".  The following lines of code 
359
+     look for this condition, as well as the url extension (following
360
+     "GET").
361
+    */
375 362
     
376 363
     while (client.connected())  {
377 364
       if (client.available()) {
... ...
@@ -407,7 +394,9 @@ void listenForEthernetClients()
407 394
             i = 1;
408 395
           }
409 396
 
410
-          if (firstLineFound && (c == '\n' || i > REQUEST_STRING_BUFFER_LENGTH - 2)) {
397
+          if (firstLineFound && (c == '\n' || i >
398
+              REQUEST_STRING_BUFFER_LENGTH - 2))
399
+          {
411 400
             processedCommand = true;
412 401
           }
413 402
         }
... ...
@@ -422,11 +411,14 @@ void listenForEthernetClients()
422 411
     transmitHttpHeader(client);
423 412
     
424 413
     char * pStr = strtok(sBuf, " ");
425
-    if (pStr != NULL) {
426
-      if (strcmp(pStr, "/rdata") == 0)
414
+    if (pStr != NULL)
415
+    {
416
+      if (strcmp(pStr, "/rdata") == 0) {
427 417
         transmitRawData(client);
428
-      else if (strcmp(pStr, "/") == 0)
418
+      }
419
+      else if (strcmp(pStr, "/") == 0) {
429 420
         transmitWebPage(client);
421
+      }
430 422
       else if(strcmp(pStr, "/reset") == 0) {
431 423
         client.print(F("ok"));
432 424
         delay(10);
... ...
@@ -434,13 +426,18 @@ void listenForEthernetClients()
434 426
         client.stop();
435 427
         software_Reset();
436 428
       }
437
-      else 
429
+      else {
438 430
         transmitErrorPage(client);
431
+      }
439 432
     }
433
+    client.println();
440 434
 
441
-    //Serial.println(mightOhmData);
435
+    #ifdef DEBUG
436
+      Serial.println(mightyOhmData);  //debug
437
+    #endif
438
+    
442 439
     // give the web browser time to receive the data
443
-    delay(10);
440
+    delay(20);
444 441
     // close the connection:
445 442
     client.stop();
446 443
   }
... ...
@@ -466,19 +463,19 @@ void transmitHttpHeader(EthernetClient client) {
466 463
 void transmitWebPage(EthernetClient client) {
467 464
   char strBuffer[MIGHTYOHM_DATA_STRING_LENGTH];
468 465
 
469
-  strcpy(strBuffer, mightOhmData);
466
+  strcpy(strBuffer, mightyOhmData);
470 467
   /*
471
-   * Send the actual HTML page the user will see in their web
472
-   * browser.
468
+   Send the actual HTML page the user will see in their web
469
+   browser.
473 470
   */
474
-  client.print(F("<!DOCTYPE HTML>" \
471
+  client.print(F("<!DOCTYPE HTML>"                               \
475 472
                  "<html><head><title>Radiation Monitor</title>"  \
476
-                 "<style>pre {font: 16px arial, sans-serif;}" \
477
-                 "p {font: 16px arial, sans-serif;}"
478
-                 "h2 {font: 24px arial, sans-serif;}</style>" \
479
-                 "</head><body><h2>Radiation Monitor</h2>" \
480
-                 "<p><a href=\"http://intravisions.com/radmon/\">" \
481
-                 "<i>intravisions.com/radmon</i></a></p>" \
473
+                 "<style>pre {font: 16px arial, sans-serif;}"    \
474
+                 "p {font: 16px arial, sans-serif;}"             \
475
+                 "h2 {font: 24px arial, sans-serif;}</style>"    \
476
+                 "</head><body><h2>Radiation Monitor</h2>"       \
477
+                 "<p><a href=\"http://intravisions.com/\">"      \
478
+                 "<i>IntraVisions.com</i></a></p>"               \
482 479
                  "<hr>"));
483 480
   /* Data Items */             
484 481
   client.print(F("<pre>UTC &#9;"));
... ...
@@ -508,10 +505,10 @@ void transmitWebPage(EthernetClient client) {
508 505
 void transmitRawData(EthernetClient client) {
509 506
   char strBuffer[MIGHTYOHM_DATA_STRING_LENGTH];
510 507
 
511
-  strcpy(strBuffer, mightOhmData);
508
+  strcpy(strBuffer, mightyOhmData);
512 509
   /*
513
-   * Format and transmit a JSON compatible data string.
514
-   */
510
+   Format and transmit a JSON compatible data string.
511
+  */
515 512
   client.print(F("$,UTC="));
516 513
   client.print(strtok(strBuffer, " "));
517 514
   client.print(F(" "));
... ...
@@ -535,16 +532,13 @@ void transmitRawData(EthernetClient client) {
535 532
 }
536 533
 
537 534
 /*
538
- * Send an error message web page back to the requesting
539
- * client when the client provides an invalid url extension.
540
- */
535
+ Send an error message web page back to the requesting
536
+ client when the client provides an invalid url extension.
537
+*/
541 538
 void transmitErrorPage(EthernetClient client) {
542
-  client.print(F("<!DOCTYPE HTML>" \
539
+  client.print(F("<!DOCTYPE HTML>"                                      \
543 540
                  "<html><head><title>Radiation Monitor</title></head>"  \
544
-                 "<body><h2>Invalid Url</h2>"  \
545
-                 "<p>You have requested a service at an unknown " \
546
-                 "url.</p><p>If you think you made this request in error, " \
547
-                 "please disconnect and try your request again.</p>" \
541
+                 "<body><h2>404 Not Found</h2>"                         \
548 542
                  "</body></html>"
549 543
                  ));
550 544
 }
... ...
@@ -553,10 +547,11 @@ void transmitErrorPage(EthernetClient client) {
553 547
  Process bytes received from the MightyOhm Geiger counter,
554 548
  one at a time, to create a well formed string.
555 549
 */
556
-void processRxByte( char RxByte )
550
+void processByteFromMightyOhm( char RxByte )
557 551
 {
558 552
   static char readBuffer[MIGHTYOHM_DATA_STRING_LENGTH];
559 553
   static byte cIndex = 0;
554
+  int headerPos = 0;
560 555
   
561 556
   /*
562 557
      Discard carriage return characters.
... ...
@@ -573,18 +568,25 @@ void processRxByte( char RxByte )
573 568
   else if (RxByte == '\n')
574 569
   {
575 570
     /*
576
-     First copy the timestamp to the MightyOhm data buffer. The "CPS"
577
-     characters are not preserved in the temporary read buffer, so
578
-     restore them to the MightyOhm data buffer, as well.
571
+     If a complete line of data has been received from the MightyOhm
572
+     Geiger counter, then add a timestamp and copy the line to the
573
+     MightyOhm data buffer.  A line is complete if the line
574
+     begins with a proper header and ends with a newline character.
579 575
     */
580
-    sprintf( mightOhmData, "%d:%02d:%02d %d/%d/%d, %s",       \
581
-          hour(), minute(), second(), month(), day(), year(),  \
582
-          MIGHTYOHM_DATA_STRING_HEADER );
583
-    /*
584
-     Now copy the rest of the data in the temporary read buffer to the
585
-     MightyOhm data buffer.
586
-    */ 
587
-    strcat(mightOhmData, readBuffer);
576
+    headerPos = strstr(readBuffer, MIGHTYOHM_DATA_STRING_HEADER) - readBuffer;
577
+    if( headerPos == 0 )
578
+    {
579
+      /*
580
+       Insert a timestamp at the beginning of the MightyOhm data buffer.
581
+       */
582
+      sprintf( mightyOhmData, "%d:%02d:%02d %d/%d/%d, ",       \
583
+            hour(), minute(), second(), month(), day(), year() );
584
+      /*
585
+       Now copy the rest of the data in the temporary read buffer to the
586
+       MightyOhm data buffer.
587
+      */ 
588
+      strcat(mightyOhmData, readBuffer);
589
+    }
588 590
     /*
589 591
      Flush the temporary read buffer.
590 592
     */
... ...
@@ -592,18 +594,6 @@ void processRxByte( char RxByte )
592 594
     readBuffer[0] = 0;
593 595
     return;
594 596
   }
595
-  /* 
596
-   A new line of data will always have "CPS" as the first
597
-   three characters.  Therefore, when these characters occur in
598
-   sequence, the read buffer should begin collecting characters.
599
-   This is a kluge to deal with an inherent problem in the Software
600
-   Serial library implementation that results in characters dropped
601
-   from the software serial stream buffer.
602
-  */
603
-  if( strstr(readBuffer, MIGHTYOHM_DATA_STRING_HEADER) > 0 ) 
604
-  {
605
-    cIndex = 0;
606
-  }
607 597
   /*
608 598
    Read characters into a temporary buffer until
609 599
    the line of data is complete or the buffer is full.
... ...
@@ -617,6 +607,48 @@ void processRxByte( char RxByte )
617 607
   return;
618 608
 } 
619 609
 
610
+/*
611
+ Synchronize the local system clock to
612
+ network time provided by NTP time server.
613
+*/
614
+void synchronizeSystemClock()
615
+{
616
+  byte count;
617
+
618
+  Serial.print(F("Synchronizing with NTP server: "));
619
+  Serial.print(timeServer);Serial.println(F("..."));
620
+
621
+  /*
622
+   * NOTICE!!!    NOTICE!!!   NOTICE!!!
623
+   * Due to a bug in the Ethernet library, it is necessary to reinitialize 
624
+   * the ethernet UDP library everytime after an  after an EthernetClient 
625
+   * class object has been instantiated.  Also, the Udp stop() function 
626
+   * must be called at the end of each session.
627
+   */
628
+  Udp.begin(NTP_PORT);  // see above comment
629
+
630
+  count = 1;
631
+  while (true)  // Attempt to synchronize 3 times
632
+  {
633
+    if (syncToNetworkTime() == 1) {
634
+      //  Synchronization successful
635
+      break;
636
+    }
637
+    if (count == TIME_SERVER_REQUEST_RETRIES) {
638
+      Serial.print(F("synch failed: "));
639
+      break;
640
+    }
641
+    count++;
642
+    delay(2000);
643
+  }
644
+  if (count > 1) {
645
+    Serial.print(count);Serial.println(F(" retries"));
646
+  }
647
+  
648
+  Udp.stop(); // see above comment
649
+  return;
650
+}
651
+
620 652
 /* 
621 653
   Send a UDP request packet to an NTP time server and listen for a reply.
622 654
   When the reply arrives, parse the received UPD packet and compute unix
... ...
@@ -625,19 +657,20 @@ void processRxByte( char RxByte )
625 657
 int syncToNetworkTime()
626 658
 {
627 659
   /*
628
-   Send a request to the NTP time server.
660
+   Send a request to the NTP time server.  Define a buffer to hold outgoing
661
+   and incoming packets.
629 662
   */
630
-  byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold outgoing and incoming packets 
663
+  byte packetBuffer[ NTP_PACKET_SIZE]; // buffer to hold packets
631 664
   /*
632 665
    Send an NTP packet to the time server and allow for network lag
633 666
    before checking if a reply is available.
634 667
   */
635
-  sendNTPpacket(packetBuffer);
636
-  delay(2000);  // allow 2000 milli-seconds for network lag
637
-
668
+  sendNTPpacket(timeServer, packetBuffer);
638 669
   /*
639 670
    Wait for response from NTP time server.
640 671
   */
672
+  delay(1000);  // allow 1000 milli-seconds for network lag
673
+
641 674
   if ( Udp.parsePacket() )
642 675
   {  
643 676
     /*
... ...
@@ -645,8 +678,8 @@ int syncToNetworkTime()
645 678
     */
646 679
     Udp.read( packetBuffer, NTP_PACKET_SIZE );
647 680
     /*
648
-     The timestamp starts at byte 40 of the received packet and is four bytes,
649
-     or two words, long. First, esxtract the two words.
681
+     The timestamp starts at byte 40 of the received packet and is four
682
+     bytes, or two words, long. First, esxtract the two words.
650 683
     */
651 684
     unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
652 685
     unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
... ...
@@ -674,9 +707,9 @@ int syncToNetworkTime()
674 707
 }
675 708
 
676 709
 /*
677
-  Send an NTP request to the NTP time server.
710
+ Send an NTP request to the NTP time server.
678 711
 */
679
-void sendNTPpacket( byte* packetBuffer )
712
+void sendNTPpacket( char * serverAddress, byte * packetBuffer )
680 713
 {
681 714
   /*
682 715
    Set all bytes in the buffer to 0.
... ...
@@ -699,8 +732,8 @@ void sendNTPpacket( byte* packetBuffer )
699 732
   /*
700 733
    All NTP fields have been given values, so now
701 734
    send a packet requesting a timestamp.
702
-  */ 		
703
-  Udp.beginPacket( ntpIpAddr, 123 ); //NTP requests are to port 123
735
+  */
736
+  Udp.beginPacket( serverAddress, 123 ); // NTP requests are to port 123
704 737
   Udp.write( packetBuffer, NTP_PACKET_SIZE );
705 738
   Udp.endPacket();
706 739
   return;
... ...
@@ -717,31 +750,27 @@ void commandMode()
717 750
 {
718 751
   char sCmdBuf[2];
719 752
   
720
-  getCurrentIP();  //used for display of settings
753
+  getCurrentIP();  // used for display of settings
754
+
755
+  Serial.println();
756
+  displayMenu(); // display the menu
721 757
   
722 758
   while(true)
723 759
   {
724
-    /*
725
-     Print the menu.
726
-    */
727
-    Serial.print( F("\n"                         \
728
-                  "1 - view settings\r\n"        \
729
-                  "2 - set IP address\r\n"       \
730
-                  "3 - set NTP server\r\n"       \
731
-                  "4 - toggle verbose\r\n"       \
732
-                  "5 - exit without saving\r\n"  \
733
-                  "6 - save & restart\r\n"       \
734
-                  ">"));
735 760
     /*
736 761
      Get the command from the user.
737 762
     */
763
+    Serial.print(F(">"));
738 764
     getSerialLine(sCmdBuf, 2);
739
-    Serial.print(F("\n\n\r"));
765
+    Serial.print(F("\n\r"));
740 766
     /* 
741 767
      Execute the command.
742 768
     */
743 769
     switch (sCmdBuf[0])
744 770
     {
771
+      case '0':
772
+        displayMenu();
773
+        break;
745 774
       case '1':
746 775
         displaySettings();
747 776
         break;
... ...
@@ -749,7 +778,7 @@ void commandMode()
749 778
         setIP();
750 779
         break;
751 780
       case '3':
752
-        setNTPIP();
781
+        setNTPServer();
753 782
         break;
754 783
       case '4':
755 784
         toggleVerbose();
... ...
@@ -765,6 +794,7 @@ void commandMode()
765 794
          server or to initialize the Ethernet interface
766 795
          with a static IP address.
767 796
         */
797
+        delay(100);
768 798
         software_Reset();
769 799
         return;
770 800
       default:
... ...
@@ -774,6 +804,25 @@ void commandMode()
774 804
   return;
775 805
 }
776 806
 
807
+/*
808
+ Displays the menu.
809
+*/
810
+void displayMenu()
811
+{
812
+  /*
813
+   Print the menu.
814
+  */
815
+  Serial.print( F("Available commands (type a number):\r\n" \
816
+                  "  0 - display this menu\r\n"    \
817
+                  "  1 - view settings\r\n"        \
818
+                  "  2 - set IP address\r\n"       \
819
+                  "  3 - set NTP server\r\n"       \
820
+                  "  4 - toggle verbose\r\n"       \
821
+                  "  5 - exit without saving\r\n"  \
822
+                  "  6 - save & restart\r\n"       \
823
+              ));  
824
+}
825
+
777 826
 /*
778 827
  Displays the current system settings.  Displays
779 828
  RadMon software version, local IP address, NTP server
... ...
@@ -801,9 +850,8 @@ void displaySettings()
801 850
   Serial.println(sBuf);
802 851
   
803 852
   // Display NTP server IP address
804
-  sprintf(sBuf, "%d.%d.%d.%d", ntpIpAddr[0], ntpIpAddr[1], ntpIpAddr[2], ntpIpAddr[3]);
805 853
   Serial.print(F("NTP server: ")); 
806
-  Serial.println(sBuf);
854
+  Serial.println(timeServer);
807 855
 
808 856
   // Display verbose mode setting
809 857
   printVerboseMode();
... ...
@@ -842,21 +890,20 @@ void setIP()
842 890
  carriage return as the first character, then use the
843 891
  default IP address for the NTP server.
844 892
 */
845
-void setNTPIP()
893
+void setNTPServer()
846 894
 {
847
-  char sBuf[16];
848
-  
849
-  Serial.print(F("enter IP (<CR> for default): "));
850
-  getSerialLine(sBuf, 16);
895
+  char sBuf[32];
851 896
   
897
+  Serial.print(F("enter NTP server (<CR> for default): "));
898
+  getSerialLine(sBuf, 32);
899
+
852 900
   if (strlen(sBuf) == 0)
853 901
   {
854
-    strcpy(sBuf, DEFAULT_NTP_SERVER_IP_ADDR);
855
-    parseIpAddress(ntpIpAddr, sBuf);
902
+    strcpy(timeServer, DEFAULT_NTP_SERVER_ADDR);
856 903
   }
857 904
   else
858 905
   {
859
-    parseIpAddress(ntpIpAddr, sBuf);
906
+    strcpy(timeServer, sBuf);
860 907
   }
861 908
   Serial.println();
862 909
   return;
... ...
@@ -991,13 +1038,20 @@ char* getSerialLine(char* sBuffer, int bufferLength)
991 1038
 void writeSettingsToEEPROM()
992 1039
 {
993 1040
   byte ix;
1041
+  char c;
994 1042
   for (ix = 0; ix < 4; ix++)
995 1043
   {
996 1044
     EEPROM.write(ix, ipAddr[ix]);
997
-    EEPROM.write(ix + 4, ntpIpAddr[ix]);
998 1045
   }
999
-  EEPROM.write(8, bVerbose);
1000
-  EEPROM.write(9, bUseStaticIP);
1046
+  EEPROM.write(4, bVerbose);
1047
+  EEPROM.write(5, bUseStaticIP);
1048
+  ix = 0;
1049
+  while(1) {
1050
+    c = timeServer[ix];
1051
+    EEPROM.write(6 + ix, c);
1052
+    if (c == 0 || ix > 31) break;
1053
+    ix++;
1054
+  }
1001 1055
   return;
1002 1056
 }
1003 1057
 
... ...
@@ -1010,13 +1064,20 @@ void writeSettingsToEEPROM()
1010 1064
 void readSettingsFromEEPROM()
1011 1065
 {
1012 1066
   byte ix;
1067
+  char c;
1013 1068
   for (ix = 0; ix < 4; ix++)
1014 1069
   {
1015 1070
     ipAddr[ix] = EEPROM.read(ix);
1016
-    ntpIpAddr[ix] = EEPROM.read(ix + 4);
1017 1071
   }
1018
-  bVerbose = EEPROM.read(8);
1019
-  bUseStaticIP = EEPROM.read(9);
1072
+  bVerbose = EEPROM.read(4);
1073
+  bUseStaticIP = EEPROM.read(5);
1074
+  ix = 0;
1075
+  while(1) {
1076
+    c = EEPROM.read(6 + ix);
1077
+    timeServer[ix] = c;
1078
+    if (c == 0 || ix > 31) break;
1079
+    ix++;
1080
+  }
1020 1081
   return;
1021 1082
 }
1022 1083
 
... ...
@@ -1046,4 +1107,3 @@ void software_Reset()
1046 1107
   asm volatile ("  jmp 0");
1047 1108
   return; 
1048 1109
 }  
1049
-
1050 1110
Binary files a/docs/DIY Radmon Project Description.pdf and b/docs/DIY Radmon Project Description.pdf differ