Pages: [1]   Go Down
Author Topic: Ethernet Shield Malfunction  (Read 675 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am having trouble with the Ethernet port sporadically returning gibberish when it receives a page call.

I have the Ethernet shield sitting atop an ArduinoMega 2560.  I connect to the Arduino with the typical http://192.168.0.42 page call.  I append the data to control the Arduino to the end of the URL and then extract that info in the Arduino, so http://192.168.0.42/LZR=000/MTR=0/DST=000/TST=0/ would be a typical page request.

The Arduino is supposed to reply to this request with a packet containing "arduino_pkg1<br />" and other strings as can be seen in the code.  My problem is that every so often, I get a packet back that is way too long and has statements that have been completely blended, like
arduiarduino_pkg2<br />
so I can't really process the data on the PC since the reply is garbled.  I've set up my PC code to only accept packets of the proper length (and therefore ungarbled), but I'd really prefer to fix the problem at the source.  Right now I believe it has something to do with the timing of the page calls.  The slower I poll the Ethernet port on the Arduino, the fewer errors I get, but I don't see why this would be the case since I don't send the next page call until I receive data back from the previous page call.  I find that making page calls any faster than about 2Hz has a high risk of running into sporadic garbled messages being returned.  I notice that if I comment out the "myservo.write(deg);" the code runs smoothly without generating errors.

Code:
#include <Servo.h>
#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0, 42 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);
Servo myservo;
int laserPos = 90;
int motorControl=0;
int motorDist=0;
int servoPin=9;
boolean testStandOn=false;
int testStandPin=2;

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  //Serial.begin(9600);
  //Serial.begin(115200);
  myservo.attach(servoPin);
  pinMode(testStandPin, OUTPUT);     
}

void zeroVars()
{
    laserPos = 0;
 motorControl=0;
 motorDist=0;
 //testStandOn=false;//need to retain state
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    zeroVars();
    int index=0;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        index++;
        if(index>=10&&index<=12)
        {
          int temp=c-48;//char to int
          //Serial.println(laserPos);
          laserPos+=temp*(index==10?100:index==11?10:1);
        }
        if(index==18)
        {
          motorControl=c-48;
        }
        if(index>=24&&index<=26)
        {
          int temp=c-48;//char to int
          motorDist+=temp*(index==24?100:index==25?10:1);
        }
        if(index==32)
        {
          int temp=c-48;//char to int
          if(temp==0) testStandOn=false;
          if(temp==1) testStandOn=true;
          //if some other value, do not change state
        }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
    laserServo(laserPos);
    setTestStnadState(testStandOn);
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
         
            client.println("arduino_pkg1<br />");
            client.println("arduino_pkg2<br />");
            client.println("arduino_end");
          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);
    // close the connection:
    client.stop();
   
    //Ethernet.begin(mac, ip);
  server.begin();
   
    /*Serial.print("Laser Position = ");
    Serial.println(laserPos);
    Serial.print("Motor Control = ");
    Serial.println(motorControl);
    Serial.print("Distance = ");
    Serial.println(motorDist);*/
  }
}

void laserServo(int deg)
{
  if(deg>=0&&deg<=180)
  {
    myservo.write(deg);
    delay(1);
  }
}

void setTestStnadState(boolean state)
{
    digitalWrite(testStandPin, state);
}
Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8908
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you leave out a ? in your typical page request? Not sure what you have going on on the pc side, but below is some simple test code you can try with a browser to see if there is a possible hardware issue. Open the serial monitor to see what is received by the arduino. This is for a regular arduino.

Code:
//zoomkat 9-5-11
//simple button GET with iframe code
//for use with IDE 0021
//open serial monitor to see what the arduino receives
//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
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
Server server(84); //server port

String readString;

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

void setup(){

  pinMode(4, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

  //enable serial data print
  Serial.begin(9600);
  Serial.println("servertest1"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  Client 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 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="";

        }
      }
    }
  }
}

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Did you leave out a ? in your typical page request?
This is true, I did not use any question marks in my page request.  I treated it as if I were accessing a sub directory/folder on a webpage and just separated everything with forward slashes.  Is the question mark required?  And if so why would that affect the code returned by the Arduino and not the actual page request that was originally sent to the Arduino?  I would think that a question mark would be treated the same as any other character and would only make a difference depending on the particular code I put on the Arduino.  I'll try the code later tonight, I suspect it would work fine since it's only doing simple digital output toggles - I find my code only has problems when I try to work with the servo.  I actually had a similar problem with my GPS over the summer though I didn't pursue it then - I suspect that there's some sort of conflict with the timers when doing Ethernet communications and servo control.

Code:
Not sure what you have going on on the pc side
I'm sending the packet as a basic browser query and I'm parsing the response verbatim as the Arduino sends it minus the header, so I see the two packages I have listed in my code appear on my PC most of the time, but every so often it fails



Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8908
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is the question mark required?

With most web servers using a ? in the url marks the start of a data string called a query_string that is set as an environmental varable for use by an application started by the server. This is usually called a GET request. It probably doesn't matter with the arduino. If the pc is making a request every 500ms without waiting for the previous request to complete, you may be overloading the arduino input capability and receiving fragmented data. Probably best to ensure the pc doesn't send a new request until the previous request has been completed.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Probably best to ensure the pc doesn't send a new request until the previous request has been completed
That's how I currently have it implemented, yes.  The only caveat is to prevent it from stalling on the PC side while it waits for a never0ending stream or the stream stops without finishing - in which case I have a timer restart/resend the page request.
Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8908
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

On the pc side, I think most browsers have a timeout incorporated to deal with non respondant sites. Just for tinkering I made the below meta refresh code to test my arduino ethernet setup. It ran for several days returning ~150,000 page refreshes using the 2 sec refresh interval. Reducing the refresh rate to 1 sec didn't seem to have any bad impact. You can set the refresh rate to 0 to see it refresh as fast as it can.

Code:
// for W5100 ethernet shield
// the IP address will be dependent on your local network/router
// port 80 is default for HTTP, but can be changed as needed
// use IP address like http://192.168.1.102:84/ in your brouser
// or http://zoomkat.no-ip.com:84 with dynamic IP service
// use the \ slash to escape the " in the html

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

int x=0;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 102 };
Server server(84);

void setup()
{
  // start the server
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client) {
     while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // see if HTTP request has ended with blank line
        if (c == '\n') {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
         
          //meta-refresh page every 2 seconds
          x=x+1;
          client.println("<HTML>");
          client.print("<HEAD>");
          client.print("<meta http-equiv=\"refresh\" content=\"0\">");
          client.print("<TITLE />Zoomkat's meta-refresh test</title>");
          client.print("</head>");
          client.println("<BODY>");
          client.print("Zoomkat's meta-refresh test");
          client.println("<br />");
                   
          client.print("page refresh number ");
          client.println(x);
          client.println("<br />");
          client.println("<br />");
         
          client.print("Zoomkat's arduino analog input values:");
          client.println("<br />");
          client.println("<br />");
         
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(analogRead(analogChannel));
            client.println("<br />");
            }
           break;
          client.println("</BODY>");
          client.println("</HTML>");
         }
        }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you add the code
Code:
myservo.write(deg);
to your project so that every time the page call is received on the Arduino, it also tries to move the servo?  The interaction between the servo and the Ethernet port is what is causing me problems.
Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8908
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Controlling a servo via a web page is pretty simple. Below is some test code for controlling continious rotation servos and the associated web control page. I just used the page on my desktop and did not include it in the arduino code. I set the page up so I could include some streaming video later. 

server code:
Code:
//zoomkat 11/12/11
//routerbot code
//for use with IDE 0022
//open serial monitor to see what the arduino receives
//

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
Server server(84); //server port

String readString, servo1, servo2;
 
Servo myservo1;  // create servo object to control a servo
Servo myservo2;
 //////////////////////

void setup(){

//start Ethernet
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();

//enable serial data print
Serial.begin(9600);
myservo1.attach(7);
myservo2.attach(6);
Serial.println("bot22"); // so I can keep track of what is loaded
}

void loop(){
// Create a client connection
Client 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;
}

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

///////////////
Serial.println(readString);

//readString looks like "GET /?-1500-1500 HTTP/1.1"

      if (readString.length() >0) {
      Serial.println(readString);
           
      servo1 = readString.substring(7, 11);
      servo2 = readString.substring(12, 16);
     
      Serial.println(servo1);
      Serial.println(servo2);
     
      int n1 = servo1.toInt();
      int n2 = servo2.toInt();
     
      myservo1.writeMicroseconds(n1);
      myservo2.writeMicroseconds(n2);
     
      readString="";
      }
  ///////////////////
 
  //now output HTML data header
  client.println("HTTP/1.1 204 Zoomkat");
  client.println();
  client.println();
  delay(1);
  //stopping client
client.stop();

/////////////////////
//clearing string for next read
readString="";
 
}}}}}

web page (copy/paste in notepad and save as test.htm):
Code:
<HTML>
<HEAD>
<H3>Zoomkat's Routerbot<BR> Web Control Page</H3>
<TITLE>Zoomkat's Routerbot Control Page</TITLE>
</HEAD>
<BODY>

Foward-*Stop*-Reverse
<BR>

<a href="http://192.168.1.102:84/?-1000-2000" target="inlineframe">F-F</a>|
<a href="http://192.168.1.102:84/?-1450-1550" target="inlineframe">S-F</a>|
<a href="http://192.168.1.102:84/?-1500-1500" target="inlineframe">*-Stop-*</a>|
<a href="http://192.168.1.102:84/?-1550-1450" target="inlineframe">S-R</a>|
<a href="http://192.168.1.102:84/?-2000-1000" target="inlineframe">F-R</a>|
<BR>
<BR>
Turn-L-*Stop*-Turn-R
<BR>
<a href="http://192.168.1.102:84/?-1000-1000" target="inlineframe">F-L</a>|
<a href="http://192.168.1.102:84/?-1450-1450" target="inlineframe">S-L</a>|
<a href="http://192.168.1.102:84/?-1500-1500" target="inlineframe">*-Stop-*</a>|
<a href="http://192.168.1.102:84/?-1550-1550" target="inlineframe">S-R</a>|
<a href="http://192.168.1.102:84/?-2000-2000" target="inlineframe">F-R</a>|
<BR>
<IFRAME name=inlineframe
src="res://D:\WINDOWS\System32\shdoclc.dll/dnserror.htm" width=1
height=1> this will hold the html answer of the moves
</IFRAME>

</body>
</html>
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8908
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You might try just sending a dummy packet without the arduino doing any packet generation to see if it gets jumbled. If this works do the same sending a dummy packet with the arduino doing the packet generation and see if there is jumbling.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Pages: [1]   Go Up
Jump to: