Ethernet Shield, RFID Scanner, PHP Server with MySql

Okay, here is the deal:

Working on an RFID scanner mod that will take the resulting RFID code, send it as a GET request to a PHP script that will process the RFID and the time the RFID was scanned (or roughly the time it is scanned), log it to the MySQL database, do some calculations, send back a few string-based values and display them on a 16x2 LCD module.

I have looked at a bunch of example code, and can get most of this working individually, but not exactly in tandem as i would like. These are...

  • Display information on the LCD
  • Read the code from an RFID and turn it into a String.
  • Send a GET HTTP request to an Apache2 web server running on a local Raspberry Pi AND get the web server to use the data as it needs
  • Read the returned data from the web server and, via substring, capture data that is enclosed within <> or {} or [] or ()

I do have a few issues, those being...

  • making the UNO wait within a function for a response from the web server
  • disconnecting and reconnecting to the web server only when i need to send and receive data

here is the code i am using on the arduino as of right now. not complete, obviously, but if anyone could point out in my code the best place to connect and reconnect that would be great.

i dont need help with the PHP side of things, i have been working with PHP and/or MySQL for about 5-10 years now so I can figure out any issues in that area, and as of right now I dont have any issues there.

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

boolean debugMode = true;

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x14, 0xE8 };
byte ip[] = { 10, 0, 1, 142 };
byte gateway[] = { 10, 0, 1, 1 };
byte dns[] = { 10, 0, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };
byte localServer[] = { 10, 0, 1, 175 };
EthernetClient client;

boolean waitingForResponse = false;

LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);

String readString, readString1;





void setup() {
  Ethernet.begin(mac,ip,dns,gateway,subnet);  // start up Ethernet
  Serial.begin(9600);                         // enable Serial
  if (debugMode) Serial.println("Starting Time Management System");
  if (debugMode) Serial.println();
  
  pinMode(A0,OUTPUT);
  pinMode(A1,OUTPUT);
  pinMode(A2,OUTPUT);
  pinMode(A3,OUTPUT);
  pinMode(A4,OUTPUT);
  pinMode(A5,OUTPUT);
  
  
  if (debugMode) Serial.println("Analog Pins set to OUTPUT");
  if (debugMode) Serial.println();
  
  
  lcd.begin(16,2);                            // start up 16x2 LCD Module
  if (debugMode) Serial.println("LCD Module Enabled");
  if (debugMode) Serial.println();
  
  
  // Attempt to make an Ethernet connection
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Testing Ethernet");
  if (debugMode) Serial.print("Testing Ethernet: ");
  lcd.setCursor(0,1);
  if (client.connect(localServer,80)) {
    lcd.print("Successful!");
    if (debugMode) Serial.println("Successful!");
    if (debugMode) Serial.println();
    client.stop();
    client.flush();
  } else {
    lcd.print("Failed!");
    if (debugMode) Serial.println("Failed!");
    if (debugMode) Serial.println();
  }
}





void loop() {
  checkScanner();
}



void checkScanner() {
  String txtMsg = "";
  
  if (Serial.available() == 16) {
    while (Serial.available() > 0) {
      char inChar = Serial.read();
      if (int(inChar) > 31) {
        txtMsg += inChar;
      }
    }
    Serial.println(txtMsg);
    Serial.println();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Card Scanned!");
    lcd.setCursor(0,1);
    lcd.print("Processing...");
    client.print("GET /monarch-time-tracker/test.php?rfid=");
    client.print(txtMsg);
    client.println(" HTTP/1.0");
    client.println();
    waitingForResponse = true;
    awaitScanResponse();
  }
}


void awaitScanResponse() {
  while (true) {
    if (client.available()) {
      char c = client.read();
      readString += c;
    }
    
    if (!client.connected()) {
      client.stop();
      client.flush();
      
      int d1 = readString.indexOf('<');
      int d2 = readString.indexOf('>');
      
      readString1 = (readString.substring(d1+1,d2));
      
    } 
    
  }
}

basically, in the setup() block I am connecting to the web server (10.0.1.175, 80) as most example scripts do, mainly to see if the connection works. What i haven't put in yet is a boolean or function that will prohibit the rest of the program from running if there is no ethernet connection. I then stop the connection (mainly because I have been unable to find any information about how long the connection can be kept alive). This device will be running relatively 24/7.

I am assuming it would be more reasonable to connect to the server ONLY when I need to make a request, as the server never will be sending data back to the Uno unless the Uno requests said data.

As i said before, the code right now is incomplete, since i am stopping the Ethernet connection in setup, and as of yet havent figured the best place in the code to reconnect.

Combined client and server test code with NPT time server GET code added by another. Open the serial monitor to see what the server is receiving, and use the serial monitor to get the current time via the client function.

//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 5 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


//NTP server implementation added by RobertJP

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.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; 

//////////////////////NTP declarations
IPAddress timeServer(77,245,91,218); // 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]; //buffer to hold incoming and outgoing packets 
EthernetUDP Udp; // A UDP instance to let us send and receive packets over UDP
unsigned int localPort = 8888; //Port to listen for UDP packets

void setup(){
  pinMode(5, OUTPUT); //pin selected to control
  Ethernet.begin(mac,ip,gateway,gateway,subnet);
  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
  Udp.begin(localPort);
  Serial.println("UDP started");
}

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 Robert");
            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(5, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
} 

void sendGET()
{
  Serial.println("Send GET");
  sendNTPpacket(timeServer); // send an NTP packet to a time server
   // wait to see if a reply is available
  delay(1000);  
  if ( Udp.parsePacket() ) { 
    Serial.println("Got it!"); 
    // 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);               

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;     
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;  
    // print Unix time:
    Serial.println(epoch);                               


    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print(1+(epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':'); 
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch %60); // print the second
  }
  Serial.println("Done!");
}

// 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(); 
}

Simple client/server test code using the DNS function.

//zoomkat 7-03-12, 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 5 high/low
//use the ' in html instead of " to prevent having to escape the "
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //assign arduino mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan assigned to arduino
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port arduino server will use
EthernetClient client;
char serverName[] = "web.comporium.net"; // zoomkat's test web page server
String readString; //used by server to capture GET request 

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

void setup(){

  pinMode(5, OUTPUT); //pin 5 selected to control
  Ethernet.begin(mac,ip,gateway,gateway,subnet); 
  server.begin();
  Serial.begin(9600); 
  Serial.println("server/client 1.0 test 7/03/12"); // 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 client 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 on browser request
            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 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(5, HIGH);    // set pin 5 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 5 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
} 

//////////////////////////
void sendGET() //client function to send and receive GET data from external server.
{
  if (client.connect(serverName, 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();

}