Go Down

Topic: NTP Schedule (Read 546 times) previous topic - next topic

ryanmcclure4

Hi everyone,

I wrote some code for an automated sprinkler system using an Arduino Uno, ethernet shield, and an 8 relay board.  I would like to be able to set a weekly schedule for it and am planning on using the timeAlarms library and NTP time.  I'm just wondering what the best way is to implement the NTP into my existing code (I'm using the example from http://arduino.cc/en/Tutorial/UdpNtpClient).  I'm trying to figure out when to send and read the packet from the time server...this is just confusing to me since I am already reading information from a client using the ethernet shield.  Should I send the NTP packet before I connect to the client, or after the client is available?

Aso, all of the output in the NTP example is done in an if() statement:

Code: [Select]

if ( Udp.parsePacket() ) {  
   // We've received a packet, read the data from it
   Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

   //the timestamp starts at byte 40 of the received packet and is four bytes,
   // or two words, long. First, esxtract the two words:

   unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
   unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
   // combine the four bytes (two words) into a long integer
   // this is NTP time (seconds since Jan 1 1900):
   unsigned long secsSince1900 = highWord << 16 | lowWord;  
   Serial.print("Seconds since Jan 1 1900 = " );
   Serial.println(secsSince1900);
...
...
...
}

(I will be using client.print in place of serial.print)

Do I need to put my existing void loop() code inside this if() statement?  Or should it be vice versa?


This is my existing code:
Code: [Select]

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <LiquidCrystal.h>
#include <Time.h>
#include <TimeAlarms.h>

// General
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x98, 0x26 };
IPAddress ip(192,168,1,134);
EthernetServer server(80);
int pin[8] = {2,3,4,5,6,7,8,9};
static char readString[30];
static char *state[8] = {"OFF","OFF","OFF","OFF","OFF","OFF","OFF","OFF"};
char trueFalse;
int val;
int cursorPin;

// NTP
unsigned int localPort = 8888;
IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer [NTP_PACKET_SIZE];
EthernetUDP Udp; // A UDP instanve to let us send and receibe packets over UDP

//LCD
LiquidCrystal lcd(14,15,16,17,18,19);
int backLight = 1;

void setup()
{
 // start the Ethernet connection and the server:
 Ethernet.begin(mac, ip);
 server.begin();
 
 //Sets the LEDpin as an output
 for(int i = 0; i < 8; i++){
   pinMode(pin[i],OUTPUT);
   digitalWrite(pin[i],HIGH);
}

  //LCD Setup
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(20,4);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("SprinkDuino");
  lcd.setCursor(0,1);
  lcd.print("Version 1.0");
  delay(5000);
  lcd.clear();
 
  //TIME Setup
  Udp.begin(localPort);
}

void loop()
{
 EthernetClient client = server.available();
 if (client) {
   // an http request ends with a blank line
   boolean currentLineIsBlank = true;
   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       int pos = strlen(readString);
       if(pos < 30){
        readString[pos++] = c;
        readString[pos] = '\0';
       }
       
       if (c == '\n' && currentLineIsBlank) {
         
         char *response = strtok(readString, "?");

         response = strtok(NULL, "=");
         if(strcmp (response, "A") == 0){
           val = 1;
         }
         else {
           val = atoi(response);
         }
         response = strtok(NULL, ";");
         if(strcmp (response, "T") == 0){
           trueFalse = 'T';
         }
         else {
           trueFalse = 'F';
         }
       
         client.println("<html>");
         //Refresh page every 5 seconds to keep page live
         client.print("<meta http-equiv=\"refresh\" content=\"5\">");
         client.println("<h1>SprinkDuino</h1>");
         client.println("<br><br>");
         client.print("<table border=1><tr>");
         client.print("<td><a href=\"./?A=T;\"><button>Turn All On</button></a>");
         client.print("<a href=\"./?A=F;\"><button>Turn All Off</button></a><br><br>");
         
         //Individual pin control
         for(int i = 0; i < 8; i++){
           if ((val == (i + 2)) && (trueFalse == 'T')) {
             digitalWrite(pin[i],LOW);
           }
           else if ((val == (i + 2)) && (trueFalse == 'F')) {
             digitalWrite(pin[i],HIGH);
           }
           
           //Turn all on or off
           else if ((val == 1) && (trueFalse == 'T')) {
             for(int i = 0; i < 8; i++){
               digitalWrite(pin[i],LOW);
             }
           }
           else if ((val == 1) && (trueFalse == 'F')) {
             for(int i = 0; i < 8; i++){
               digitalWrite(pin[i],HIGH);
             }
           }
           
           //Changes state[] depending on pin status            
           for(int h = 0; h < 8; h++){
            if(digitalRead(pin[h]) == LOW){
             state[h] = "ON";              
            }
            else{
             state[h] = "OFF";
            }
           }

           client.print("Sprinkler ");
           client.print(pin[i]);
           client.print(" is ");
           client.print(state[i]);
           
           if (state[i] == "ON") {
             client.print("<a href=\"./?");
             client.print(pin[i]);
             client.print("=F;\"><button>Turn Off</button><a>");
           }
           else {
             client.print("<a href=\"./?");
             client.print(pin[i]);
             client.print("=T;\"><button>Turn On</button><a>");
           }            
           client.print("<br>");
         }
         client.print("</td><td>");
         client.print("<h1>Schedule</h1>");
         client.print("</td></tr>");
         client.print("</table>");
         client.println("</html>");
         break;
       }
       if (c == '\n') {
         // you're starting a new line
         currentLineIsBlank = true;
       }
       else if (c != '\r') {
         // you've gotten a character on the current line
         currentLineIsBlank = false;
       }
     }
   }
   // give the web browser time to receive the data
   delay(1);
   readString[0] = '\0';
   // close the connection:
   client.stop();
 }
}


// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
 // set all bytes in the buffer to 0
 memset(packetBuffer, 0, NTP_PACKET_SIZE);
 // Initialize values needed to form NTP request
 // (see URL above for details on the packets)
 packetBuffer[0] = 0b11100011;   // LI, Version, Mode
 packetBuffer[1] = 0;     // Stratum, or type of clock
 packetBuffer[2] = 6;     // Polling Interval
 packetBuffer[3] = 0xEC;  // Peer Clock Precision
 // 8 bytes of zero for Root Delay & Root Dispersion
 packetBuffer[12]  = 49;
 packetBuffer[13]  = 0x4E;
 packetBuffer[14]  = 49;
 packetBuffer[15]  = 52;

 // all NTP fields have been given values, now
 // you can send a packet requesting a timestamp:        
 Udp.beginPacket(address, 123); //NTP requests are to port 123
 Udp.write(packetBuffer,NTP_PACKET_SIZE);
 Udp.endPacket();
}


Thanks for any help!

Cybernetician

Zoomkat code may help you how to run server and client on same machine

Code: [Select]

//zoomkat 12-08-11, combined client and server
//simple button GET with iframe code
//for use with IDE 1.0
//open serial monitor and send an g to test client and
//see what the arduino client/server receives
//web page buttons make pin 4 high/low
//use the \ slash to escape the " in the html
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
IPAddress ip(192,168,1,102); // ip in lan
IPAddress gateway(192,168,1,1); // internet access via router
IPAddress subnet(255,255,255,0); //subnet mask
IPAddress myserver(208,104,2,86); // zoomkat web page
EthernetServer server(84); //server port
EthernetClient client;
String readString;

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

void setup(){

  pinMode(4, OUTPUT); //pin selected to control
  Ethernet.begin(mac, ip, subnet, gateway);
  server.begin();
  Serial.begin(9600);
  Serial.println("server/client 1.0 test 12/08/11"); // keep track of what is loaded
  Serial.println("Send an g in serial monitor to test client"); // what to do to test client
}

void loop(){
  // check for serial input
  if (Serial.available() > 0)
  {
    byte inChar;
    inChar = Serial.read();
    if(inChar == 'g')
    {
      sendGET(); // call sendGET function
    }
  } 

  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging

            //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println("HTTP/1.1 204 Zoomkat");
            client.println();
            client.println(); 
          }
          else {
            client.println("HTTP/1.1 200 OK"); //send new page
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Arduino GET test page</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Zoomkat's simple Arduino 1.0 button</H1>");

            client.println("<a href=\"/?on\" target=\"inlineframe\">ON</a>");
            client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>");

            //client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">");
            client.println("<IFRAME name=inlineframe style=\"display:none\" >");         
            client.println("</IFRAME>");

            client.println("</BODY>");
            client.println("</HTML>");
          }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            digitalWrite(4, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(4, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

//////////////////////////
void sendGET() //client function to send/receie GET request data.
{
  if (client.connect(myserver, 80)) {
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0");
    client.println();
  }
  else {
    Serial.println("connection failed");
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read();
    Serial.print(c);
  }

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();
  client.stop();

}


http://arduino.cc/forum/index.php?topic=90210.0
From Idea To Invention

PaulS

Quote
and NTP time.

Just how accurate does your lawn watering need to be? A cheap RTC is far simpler than adding an ethernet shield so you can time from the internet.

ryanmcclure4

Thanks Cybernetician, I'll check that out.

PaulS - It doesn't need to be too accurate, it would probably be fine if it was up to an hour off.  Would an RTC need to be re-programmed every once in a while to keep its accuracy?

Cybernetician

After one time setting of RTC you can track the time even in cases of battery outrage, controller reprogramed etc.

Search on RTC arduino explains more.
From Idea To Invention

ryanmcclure4

I read up on it, and I think I'll give it a shot before trying to mess with client/server code!  Thanks for the help guys

Go Up