Serial IN ---> Ethernet OUT

Hello people,

For a project I need to receive serial data from the UART, and send it out via the Ethernet-shield to a PHP script on my webserver.
The webserver (and the PHP script) are working good because if I use the etherShield_client (temperature) example everything works great.
Now I want to replace the temperature data with the data received from the serial port. The data looks like: “h21.87hi18.19ij11jk1kl21lm28mn50no77op7pq0qr24rs9st24tu9uv23vw46wx57x”

I have this code, but it doesn’t work:

void loop(){

int counter;   
   
  if (Serial.available() > 1) {
     counter = 0;
     for (int i=0; i <= Serial.available(); i++){
       sensorData[i] = Serial.read();
       counter = i;
     }
     sensorData[counter+1] = '\0';   
     
     if(client_data_ready==0){
       //delay(60000UL);                 // delay 60s
       //getCurrentTemp(sensorData);     //don't use this one now...
       client_data_ready = 1;
     }
  client_process();
  }
}

(and of course the rest from the "Temperature example, but that doesn’t matter here!)

“sensorData” is declared as:
char sensorData[50];

if I “hardcode” the sensorData it works also good:

sensorData[0] = 'a';
sensorData[1] = 'b';
sensorData[2] = '\0';

How is it possible that I can’t put the serial data to the Ethernet-shield?
I hope that someone can help me with this :slight_smile:

Thanks in advance, and have a nice day!!

Atmoz

your code is only a half sketch, please post the whole code ...

Good morning!!

Thanks Rob, for the quick reply.

The code I have is working sometimes… But there is a limit to 8 characters. But sometimes the limit is 1 or 2 chars… :0
If I send a whole string with 30 characters or so, then only 8 arrive at the PHP script (and thus in the database)

this is the whole sketch:

#include "etherShield.h"

static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 
static uint8_t myip[4] = {192,168,2,88};
static uint16_t my_port = 80;     // client port
static char client_ip[] = "192.168.2.88";

char inchar[50]="";

static uint8_t dest_ip[4]={192,168,2,53};
static uint8_t dest_mac[6];

enum CLIENT_STATE
{  
   IDLE, ARP_SENT, ARP_REPLY, SYNC_SENT
 };
 
static CLIENT_STATE client_state;
static uint8_t client_data_ready;
static uint8_t syn_ack_timeout = 0;

#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];

char sensorData[10];

EtherShield es=EtherShield();

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf);
int8_t analyse_cmd(char *str);
void client_process(void);

void setup(){
  
   Serial.begin(9600); 
   Serial.println("Begin!"); 

   es.ES_enc28j60Init(mymac);
   es.ES_enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
   delay(10);
        
	es.ES_enc28j60PhyWrite(PHLCON,0x880);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x990);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x880);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x990);
	delay(500);

        es.ES_enc28j60PhyWrite(PHLCON,0x476);
	delay(100);
        
  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip,80);
  
  // intialize varible;
  syn_ack_timeout =0;
  client_data_ready = 0;
  client_state = IDLE;

}

void loop(){

int counter;   
   
  if (Serial.available() > 0) {
    
    int i = 0;
    
    
    while (Serial.available()){
       char serchar = Serial.read();
       //Serial.print(serchar);
       inchar[i]=serchar;
       i++;
       counter = i;
     
       //sensorData[i] = Serial.read();
       //counter = i;
     }
     //sensorData[counter+1] = '\0';   
     
     inchar[counter] = '\0';   
     
     //Serial.print(inchar);
     
     //sensorData[0] = 'a'; 
     //sensorData[1] = 'a'; 
     //sensorData[2] = '\0'; 
     
     if(client_data_ready==0){
       //delay(5000UL);                 // delay 60s
       //getCurrentTemp(sensorData);     //don't use this one now...
       client_data_ready = 1;
     }
  
  }
  client_process();
}


uint16_t gen_client_request(uint8_t *buf )
{
	uint16_t plen;
	byte i;
        
	plen= es.ES_fill_tcp_data_p(buf,0, PSTR ( "GET /ethershield_log/save.php?pwd=44&client=111" ) );
        for(i=0; client_ip[i]!='\0'; i++){
            buf[TCP_DATA_P+plen]=client_ip[i];
            plen++;
        }
        plen= es.ES_fill_tcp_data_p(buf,plen, PSTR ( "&status=" ) );
        for(i=0; inchar[i]!='\0'; i++){
        
                buf[TCP_DATA_P+plen]=inchar[i];
                plen++;
        }	
     
        
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( " HTTP/1.0\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Host: 192.168.2.53\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "User-Agent: AVR ethernet\r\n" ));
        plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Accept: text/html\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Keep-Alive: 300\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Connection: keep-alive\r\n\r\n" ));

	return plen;
}


void client_process ( void )
{
    uint16_t plen;
	uint8_t i;

    if (client_data_ready == 0)  return;     // nothing to send

	if(client_state == IDLE){   // initialize ARP
       es.ES_make_arp_request(buf, dest_ip);
	   
	   client_state = ARP_SENT;
	   return;
	}
     
		
	if(client_state == ARP_SENT){
        
        plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

		// destination ip address was found on network
        if ( plen!=0 )
        {
            if ( es.ES_arp_packet_is_myreply_arp ( buf ) ){
                client_state = ARP_REPLY;
				syn_ack_timeout=0;
				return;
            }
		
		}
	        delay(10);
		syn_ack_timeout++;
		
		
		if(syn_ack_timeout== 100) { 
			client_state = IDLE;
			client_data_ready =0;
			syn_ack_timeout=0;
			return;
		}	
    }

  
 // send SYN packet to initial connection
	if(client_state == ARP_REPLY){
		// save dest mac
		for(i=0; i<6; i++){
			dest_mac[i] = buf[ETH_SRC_MAC+i];
		}
	
        es.ES_tcp_client_send_packet (
                       buf,
                       80,
                       1200,
                       TCP_FLAG_SYN_V,   
                       1,  
                       1,     
                       0,        
                       0,               
		      dest_mac,
		      dest_ip
                       );
		
		client_state = SYNC_SENT;
	}

  if(client_state == SYNC_SENT){
    plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);


    if ( plen == 0 )
    {
        return;
    }

  
 
    if ( es.ES_eth_type_is_ip_and_my_ip(buf,plen)==0){
		return;
    }

 
    if ( buf [ TCP_FLAGS_P ] == ( TCP_FLAG_SYN_V | TCP_FLAG_ACK_V ) )
    {

               // send ACK to answer SYNACK

               es.ES_tcp_client_send_packet (
                       buf,
                       80,
                       1200,
                       TCP_FLAG_ACK_V,    
                       0,   
                       0, 
                       1,  
                       0,      
						dest_mac,
						dest_ip
                       );

               plen = gen_client_request( buf );

               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,      
                                       1200,           
                                       TCP_FLAG_ACK_V | TCP_FLAG_PUSH_V,  
                                       0,      
                                       0,     
                                       0,       
                                       plen, 
                                       dest_mac,
									   dest_ip
									   );
               return;
       }

       if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_PUSH_V) )
       {
               plen = es.ES_tcp_get_dlength( (uint8_t*)&buf );

               // send ACK to answer PSHACK from server
               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,       
                                       1200,     
                                       TCP_FLAG_ACK_V,    
                                       0,         
                                       0,          
                                       plen,               
                                       0,                 
				      dest_mac,
				      dest_ip
               );;
          

               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,                                             // destination port
                                       1200,                                   // source port
                                       TCP_FLAG_FIN_V|TCP_FLAG_ACK_V,                  // flag
                                       0,        
                                       0,     
                                       0,                        
                                       0,
										dest_mac,
										dest_ip
				);

               return;
               
       }
   
       if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_FIN_V) )
       {
  
               es.ES_tcp_client_send_packet(

                                       buf,
                                       80,             
                                       1200,                              
                                       TCP_FLAG_ACK_V,                 
                                       0,                                            
                                       0,                                             
                                       1,                                             
                                       0,
									   dest_mac,
									   dest_ip
				);
			client_state = IDLE;		// return to IDLE state
			client_data_ready =0;		// client data sent
		}
  }       
}

Thanks again for willing to help!!

With kind regards,

Atmoz

The data looks like: "h21.87hi18.19ij11jk1kl21lm28mn50no77op7pq0qr24rs9st24tu9uv23vw46wx57x"

How will you recognize what that entire packet has been received? The answer is that with that structure, you can not.

So, you can either add start and end of packet markers, or wait a whole bunch of time for the whole packet to arrive, and hope you've waited long enough.

If you don't add start and end markers, and still don't get complete packets, wait longer. Or longer still.

Be sure that you don't wait so long that another packet begins to arrive while you are twiddling your thumbs waiting for the previous packet to completely arrive.

If you get the impression that I think waiting is not a good idea, you are right. Start and end of packet markers are what you need.

Read everything available on every pass through loop. If the serial data includes a start marker, initialize the buffer and index. If it includes an end marker, send the data, and reinitialize. Add any other character to the array, if there is room.

Your Arduino can read the Serial buffer a whole lot faster than it can fill up, so it will often finish reading the first lets say 8 bytes of your 40 byte string for example and although there are more bytes on the way, the Serial.available function will return 0.

So as PaulS mention, you must either put an end marker and scan your incoming bits until you see it, or just pop a delay in to give ample time for your whole string to arrive. The former being the better choice.

Thank you both for the reply's!!

I indeed have troubles with receiving all the characters from the serial-port.
In the meanwhile I came with "xxx" at the beginning from the sting/stream and "yyy" at the end :slight_smile:

But I also have problems with sending all the data to the PHP script via the Ethernet-shield.

So I have to split the problems in 2.

First I want to send the complete string to the PHP script.
Therefore I do:

char inchar[]="";
String readString;

readString="";
readString = "123test_hoeveel_chars_kunnen_hier_in";
readString.toCharArray(inchar, 49);
inchar[sizeof(readString)+1] = '\0';

Then, if "inchar" is filled completely I pass it to the Ethernet-shield with this piece of code:

uint16_t gen_client_request(uint8_t *buf )
{
	uint16_t plen;
	byte i;
        
	plen= es.ES_fill_tcp_data_p(buf,0, PSTR ( "GET /ethershield_log/save.php?pwd=44&client=111" ) );
        for(i=0; client_ip[i]!='\0'; i++){
            buf[TCP_DATA_P+plen]=client_ip[i];
            plen++;
        }
        plen= es.ES_fill_tcp_data_p(buf,plen, PSTR ( "&status=" ) );
        for(i=0; inchar[i]!='\0'; i++){
        
                buf[TCP_DATA_P+plen]=inchar[i];
                plen++;
        }	
     
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( " HTTP/1.0\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Host: 192.168.2.53\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "User-Agent: AVR ethernet\r\n" ));
        plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Accept: text/html\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Keep-Alive: 300\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Connection: keep-alive\r\n\r\n" ));

	return plen;
}

But then, nothing happens with this long "test" string.
If I make the string shorter it works well.
Is it in theory possible to pass that long string at once to the Ethernet-shield?
If I test this on my computers web browser it again works great!! (so PHP + webserver are working OKAY!!)

When it's working with sending (hard coded) long strings, then I go fix the problem with receiving from the Serial-port.

Thanks for helping me out!!

Atmoz

char inchar[]="";
String readString;

readString="";
readString = "123test_hoeveel_chars_kunnen_hier_in";
readString.toCharArray(inchar, 49);

This is declaring an array of size 1, then writing 36 (or so) characters into that array. Oops.

The inChar array needs to be a fixed, larger, size, and does not need to be initialized.

You are telling the toCharArray function that the array can hold 49 characters. This is not (currently) true.

Thanks PaulS,

If I do

char inchar[73]="";

It also doesn't work.
If the string is longer then +/- 25 characters, the Ethernet-shield don't "recognize" this!
Even if I declare lot more of "space" for inchar...

Very strange, and very frustrating you can imagine :wink:
( it's all (very) nice stuff these things, but If they don't work afters HOURS and HOURS then --> :frowning: )

Thanks!!!

Atmoz

If the string is longer then +/- 25 characters, the Ethernet-shield don't "recognize" this!

First, I think that it is important that you stop saying "the Ethernet shield". Instead, say "my Ethernet shield. This is important because there are at least two distinctly different ethernet shields. I think that this problem is unique to your ethernet shield.

char inchar[73]="";

It does not matter, in the slightest, what is currently in inChar when the (address of) the array is passed to toCharArray(). So, stop with the initialization.

Now, where inChar comes into play with respect to genClientRequest (the other code you posted) is not clear. It is also not clear which library you are using for your ethernet objects.

That library may have hard-coded array sizes that you need to change/respect.

Hi PaulS,

My Ethernet-shield is from "NuElectronics".
I use this version of etherShield.h: http://www.lumatronix.nl/etherShield.h (made by Xing Yu)

If it's better to take another library and/or shield then I'll be glad to hear :slight_smile:
I also got a Ethernet-shield from "Ekitzone.com" and if it's better to use that one, then is possible to switch. (but I think that doesn't fix my problem because they both use the ENC28J60 chip)

I used "inChar" instead of "sensorData" (both Char array's) from the "temperature example".
Because that example is working great, I thought it was "easy" to change it to my requirements. (receive serial data, put it into "inChar" or "sensorData", and send it to the PHP script).
So I took this example and striped a few things out of it (get temp. from sensor, etc...)
And it's working very good with short and hard coded (static) strings. But I need long and dynamic strings filled by the serial port. 8)

The temperature example is here: http://www.codetorment.com/2009/10/24/arduino-goodness-ethernet-shield/ (the first code at webpage)

Thanks again!!

With kind regards,

Atmoz

Okay it's working now with larger strings.

I opened a new "fresh" example from the Temperature-Ethernet-Shield and modified the main loop from this:

void loop(){

        if(client_data_ready==0){
          delay(60000UL);             // delay 60s
          getCurrentTemp(sensorData);
          client_data_ready = 1;
         }
	client_process();
       
}

to this:

void loop(){

        if(client_data_ready==0){
          delay(5000UL);             // delay 60s
          //getCurrentTemp(sensorData);
          
          readString = "HH119ij11jk1kl21lm2ddddddddaaaaaa4eeeeeeeeeeeeeee44rrrrrraaaaadddeddddddddddddeddxGG";
          readString.toCharArray(sensorData, 99);
          sensorData[99] = '\0';
          
          client_data_ready = 1;
         }
	client_process();   
}

And also changed this:

char sensorData[10];

to:

char sensorData[100];
String readString;

(and further the correct IP and MAC address)

It's working with the large string above!! The only thing is that it don't except "." (points) in the string. If there is a "point" then my Ethernet-shield doesn't send the data to the script.
But for now it's okay, then I send the data without point in it :slight_smile:

Now I need to receive this large string from the Serial port.
If I also can get some help with this would be very GREAT!!

Thanks thanks thanks!!

Atmoz

[edit]

I made this code for receiving the large string, but unfortunately it doesn't work:

  byte inByte = '\0';
  
  
  if (Serial.available() > 0){
    delay(10);
    klaar = false;
    int i = 0;
    while (klaar==false){
      inByte = Serial.read();
      readString[i] = inByte;
      i++;
      if (inByte == 'a'){klaar = true;};      
    }
    
    Serial.println(readString);

I really can't see what I'm doing wrong here...

I made this code for receiving the large string, but unfortunately it doesn’t work:

You haven’t described what you expect it to do, or what it actually does, so it’s hard to determine why the code doesn’t do what you expect it to.

But, this is problematic:

    while (klaar==false){
      inByte = Serial.read();
      readString[i] = inByte;
      i++;
      if (inByte == 'a'){klaar = true;};      
    }

The while loop may execute millions of times before an a arrives. Each time, it will try to read a value from the serial port. Most of those attempts will fail, and inByte will be -1. That doesn’t seem to matter to you; you store it anyway. Oops.

That there is no more room in the array also doesn’t seem to matter to you. Oops.

This would probably work better:

    while (klaar==false)
    {
      if(Serial.available() > 0)
      {
        inByte = Serial.read();
        if(i < ??) // Whatever the size of the array
        {
          readString[i] = inByte;
          i++;
        }

        if (inByte == 'a')
        {
          klaar = true;
        }
      }
    }

By the way, inByte should be an int, not a byte, so that Serial.read() CAN return an error. And because that is the type returned by Serial.read().

The below discussion from a day or so ago might be of interest.

Thanks PaulS for the good explanation.
If you tell it this way it’s very good to understand for a noob as me :slight_smile:
So thank you for that!!

[edit]

The problem is that I don’t know the length of the array (if(i < ??) // Whatever the size of the array)
Because the string what is send to the Arduino (via serial) is each time different.
Or can I reserve (declare) 100 chars (is enough in each situation) and ‘\0’ terminate the 99st char in it?

[/edit]

@zoomkat also thanks for the link.
The serial receiving problems are out of the world for me.
Last night (yes it was very late again :grin: ) I found this peace of code: http://forums.adafruit.com/viewtopic.php?f=8&t=9918
It helped me very good. So I’m 99% sure that the serial receiving is working good!

BUT: I found a big problem regarding the calls to the PHP script.
As mentioned before I use a temperature example which I changed a little bit.
The problem is that the main-loop in this original example is very short.
It goes very quick trough the loop because getting temp. data doesn’t take that long:

void loop(){

        if(client_data_ready==0){
          delay(60000UL);             // delay 60s
          getCurrentTemp(sensorData);
          client_data_ready = 1;
         }
	client_process();
       
}

If I change this to my requirements and strip out “getCurrentTemp(sensorData);” and replace it with my serial receive stuff, then the loop takes to long for “client_process();” to work good.
Because if I make a “hard coded” string and put it into “sensorData” then it works great. And if I put a simple serial receive mechanism inside the loop then the PHP never get called.
Even if I don’t use the received string from serial (but use the hard coded string instaed)

So I think the (working) temperature example isn’t a good start for me. And besides that, it looks not very nice with all the code in it. The examples what I’ve seen here on the forum are a lot neater:

Ethernet.begin(mac, ip);

client.println(“GET /ethershield_log/save.php?pwd=44&client=111&status=temperature-”);
client.println(" HTTP/1.0\r\n");
client.println(“Host: 192.168.2.53”);

etc…

Not all the difficult code stuff what I had in my code…

So I think I have to find a new Ethernet-Shield library which I can “customize” a little bit to implement the serial receive stuff.

Finally then I’m where I want to be 8)

Can anyone point me to a VERY SIMPLE webclient example which sends data to a PHP script? (eventually with the corresponding library’s with it)
I’ve downloaded this: GitHub - turicas/Ethernet_ENC28J60: [NOT MAINTAINED, NOT COMPLETED] Implementation of an Arduino-compatible socket layer library that uses Microchip ENC28J60 Ethernet controller. but I don’t get is to work. It always says

connecting…
connection failed

disconnecting.

Thanks again people!!!

With regards,

Atmoz

FINALLY it’s working 8) 8) 8)

Thanks to all that helped me with this.
After days and nights ( my knees hurt because I sit way to long behind my desk :roll_eyes: ) it finally works. YES :smiley:

For people who are interested in the code, or maybe it can help other people in the future:

#include "etherShield.h"

static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 
static uint8_t myip[4] = {192,168,2,88};
static uint16_t my_port = 80;     // client port
static char client_ip[] = "192.168.2.88";
static uint8_t dest_ip[4]={192,168,2,53};
static uint8_t dest_mac[6];

enum CLIENT_STATE
{  
   IDLE, ARP_SENT, ARP_REPLY, SYNC_SENT
 };
 
static CLIENT_STATE client_state;
static uint8_t client_data_ready;
static uint8_t syn_ack_timeout = 0;

#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];

char sensorData[100];
String readString;
bool klaar = false;

#define INLENGTH 99
#define INTERMINATOR 48
char inString[INLENGTH+1];
int inCount;

EtherShield es=EtherShield();

uint16_t print_webpage(uint8_t *buf);
int8_t analyse_cmd(char *str);

#define TEMP_PIN  3
void getCurrentTemp( char *temperature);
void client_process(void);

void setup(){
  
  Serial.begin(9600); 
  Serial.println("Begin!"); 
  
	 es.ES_enc28j60Init(mymac);
   es.ES_enc28j60clkout(2); 
   delay(10);

	es.ES_enc28j60PhyWrite(PHLCON,0x880);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x990);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x880);
	delay(500);

	es.ES_enc28j60PhyWrite(PHLCON,0x990);
	delay(500);

  es.ES_enc28j60PhyWrite(PHLCON,0x476);
	delay(100);
        
  es.ES_init_ip_arp_udp_tcp(mymac,myip,80);
  
  syn_ack_timeout =0;
  client_data_ready = 0;
  client_state = IDLE;

    digitalWrite(TEMP_PIN, LOW);
    pinMode(TEMP_PIN, INPUT);  
}

void loop(){
        if(client_data_ready==0){
               
        inCount = 0;
  do 
  {
     while(!Serial.available());               // wait for input
    sensorData[inCount] = Serial.read();       // get it
    if (sensorData [inCount] == INTERMINATOR) break;
  }while (++inCount < INLENGTH);

  sensorData[inCount] = 0;                     // null terminate the string

  Serial.println(sensorData);
          
          delay(2000UL);                   // delay 60s
          sensorData[99] = '\0'; 
          client_data_ready = 1;
         }
	client_process();   
}


uint16_t gen_client_request(uint8_t *buf )
{
	uint16_t plen;
	byte i;
        
	plen= es.ES_fill_tcp_data_p(buf,0, PSTR ( "GET /ethershield_log/save.php?pwd=44&client=111" ) );
        for(i=0; client_ip[i]!='\0'; i++){
            buf[TCP_DATA_P+plen]=client_ip[i];
            plen++;
        }
        plen= es.ES_fill_tcp_data_p(buf,plen, PSTR ( "&status=temperature-" ) );
        for(i=0; sensorData[i]!='\0'; i++){
        
                buf[TCP_DATA_P+plen]=sensorData[i];
                plen++;
        }	
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( " HTTP/1.0\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Host: 192.168.2.53\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "User-Agent: AVR ethernet\r\n" ));
        plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Accept: text/html\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Keep-Alive: 300\r\n" ));
	plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Connection: keep-alive\r\n\r\n" ));

	return plen;
}

void client_process ( void )
{
    uint16_t plen;
	uint8_t i;

    if (client_data_ready == 0)  return;     // nothing to send

	if(client_state == IDLE){   // initialize ARP
       es.ES_make_arp_request(buf, dest_ip);
	   
	   client_state = ARP_SENT;
	   return;
	}
	
	if(client_state == ARP_SENT){
        
        plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
	
        if ( plen!=0 )
        {
            if ( es.ES_arp_packet_is_myreply_arp ( buf ) ){
                client_state = ARP_REPLY;
				syn_ack_timeout=0;
				return;
            }	
		}
	        delay(10);
		syn_ack_timeout++;
		
		
		if(syn_ack_timeout== 100) { 
			client_state = IDLE;
			client_data_ready =0;
			syn_ack_timeout=0;
			return;
		}	
    }

	if(client_state == ARP_REPLY){
		// save dest mac
		for(i=0; i<6; i++){
			dest_mac[i] = buf[ETH_SRC_MAC+i];
		}
	
        es.ES_tcp_client_send_packet (
                       buf,
                       80,
                       1200,
                       TCP_FLAG_SYN_V,   
                       1,      
                       1,        
                       0,                                              
                       0,     
		      dest_mac,
		      dest_ip
                       );
		
		client_state = SYNC_SENT;
	}

  if(client_state == SYNC_SENT){
    plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

       // no new packet incoming
    if ( plen == 0 )
    {
        return;
    }

 
    if ( es.ES_eth_type_is_ip_and_my_ip(buf,plen)==0){
		return;
    }

       // check SYNACK flag, after AVR send SYN server response by send SYNACK to AVR
    if ( buf [ TCP_FLAGS_P ] == ( TCP_FLAG_SYN_V | TCP_FLAG_ACK_V ) )
    {

               es.ES_tcp_client_send_packet (
                       buf,
                       80,
                       1200,
                       TCP_FLAG_ACK_V,
                       0,        
                       0,     
                       1,       
                       0,    
						dest_mac,
						dest_ip
                       );
     
               plen = gen_client_request( buf );
               // send http request packet
               // send packet with PSHACK
               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,      
                                       1200,  
                                       TCP_FLAG_ACK_V | TCP_FLAG_PUSH_V,  
                                       0,   
                                       0,  
                                       0,    
                                       plen,                           // tcp data length
                                       dest_mac,
									   dest_ip
									   );
               return;
       }
       // after AVR send http request to server, server response by send data with PSHACK to AVR
       // AVR answer by send ACK and FINACK to server
       if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_PUSH_V) )
       {
               plen = es.ES_tcp_get_dlength( (uint8_t*)&buf );

               // send ACK to answer PSHACK from server
               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,                                             // destination port
                                       1200,                                   // source port
                                       TCP_FLAG_ACK_V,                  // flag
                                       0,                                              // (bool)maximum segment size
                                       0,                                              // (bool)clear sequence ack number
                                       plen,                                           // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
                                       0,                              // tcp data length
				      dest_mac,
				      dest_ip
               );;
               // send finack to disconnect from web server

               es.ES_tcp_client_send_packet (
                                       buf,
                                       80,                                             // destination port
                                       1200,                                   // source port
                                       TCP_FLAG_FIN_V|TCP_FLAG_ACK_V,                  // flag
                                       0,                                              // (bool)maximum segment size
                                       0,                                              // (bool)clear sequence ack number
                                       0,                                           // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
                                       0,
										dest_mac,
										dest_ip
				);

               return;
               
       }
       // answer FINACK from web server by send ACK to web server
       if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_FIN_V) )
       {
               // send ACK with seqack = 1
               es.ES_tcp_client_send_packet(

                                       buf,
                                       80,    
                                       1200,  
                                       TCP_FLAG_ACK_V,  
                                       0,   
                                       0,  
                                       1,     
                                       0,
									   dest_mac,
									   dest_ip
				);
			client_state = IDLE;
			client_data_ready =0;
		}
  }       
}

Hello,

As my last post says the project works good.
Therefore I am still happy, but unfortunately there is a “small” problem:

After the Arduino is powered on for a couple of hours, and uploads the data received by the UART via my Ethershield to the PHP script, the PHP script isn’t triggered anymore.
It looks like my Ethershield “hangs”. If I test/trigger the PHP script manually (via Internet Explorer), then it works good. So therefore the PHP script (and MySQL server) is good!
Sometimes is hangs after 1 hour, sometimes after 3 or 4 hours.

What I discovered is that if my Ethershield has to send a “.” or a " " or some other “strange” character then it hangs, and does need a reset to work again.
Therefore, in my datastream (what I receive with the UART), I don’t send these characters at all. But what if there is a glitch (or a bad temperature reading which results in for example “34.#4” instead of “34.34”) ?
Then the serialport receives this, and sends it to my Ethershield what is going to hang then…

Can I make something that sends ONLY 0…9 and a…z to my Ethershield, or should I look for some other solution??

Maybe someone can help me with this.

Thanks again for your time!!

With kind regards,

Atmoz

Can I make something that sends ONLY 0..9 and a..z to my Ethershield

You can, but I think that that is not the best solution. I find it hard to believe that the ethernet library causes the ethernet shield to lock up when you send a period.

But, you are collecting data, using Serial.read(), and sending it using client.print() (presumably, need to see your code). Call a function prior to the client.print() call to remove "invalid" characters from the string. There are a number of str* functions that might be of interest - strcspn comes to mind.

Thanks PaulS,

The (part of the) code what I’m using is:

void loop(){
 
  if(client_data_ready==0){
        
  inCount = 0;

    
  do 
  {
    while(!Serial.available());               // wait for input
    
    check = Serial.read();       // get it
    
    if ((check > 46) && (check < 123) || (check == 42)) {   // only 'good' characters, otherwise Ethershield won't send it/hangs
    
      sensorData[inCount] = check;   //Serial.read();       // get it
    
    }
    
    else{
      
      sensorData[inCount] = '[';
      
    }
    
    
    
    
    if (sensorData[inCount] == '*'){
      sensorData[0] = '*';
      inCount = 0;
    }      
    
    if (sensorData[inCount] == '.'){sensorData[inCount] = '_';};
    
    if (sensorData [inCount] == INTERMINATOR) break;
  }while (++inCount < INLENGTH);

  sensorData[inCount] = 0;                     // null terminate the string

  Serial.println(sensorData);
          

          
          delay(2000UL);                   // delay 60s
          //sensorData[99] = '\0'; 
          if (sensorData[0] == BEGINNER){
            client_data_ready = 1;
          }
         }
              
	client_process();      
}

(client_process() does the sending to my Ethershield)

The only thing I want to do is:

Receive data from the UART beginning with ‘*’ end ending with ‘/’
All characters between * and / must be send to the PHP script.

In the PHP script I wrote a peace of code that sends me the string received from the Arduino to my email.
Wen I receive an email, then I now my Ethershield at least has triggered the PHP script. That is the case right now!
The string is terminated in the middle., which is not good. At that spot there strangely appears a * so my code thinks that that is the start point of a new datastream.
So in the first place I was thinking wrong that my Ethersield hangs, instead of that, the PHP script didn’t put the data in the MySQL database, because it was not complete XD :blush:

But what is the reason that the * appears at the wrong spot? It only has to be in the beginning of the string.
I think it has to do with a temp sensor. They not always spit out correct data. So in 1 from 1000 times there is a “glitch” and it sends a * out…

[edit]

And now it doesn’t even trigger the PHP script anymore.
I don’t receive emails, so my Ethershield is stopped with it (till I reset it!)
How it this possible?

It is indeed very strange that I can’t send " " or “.” with it!!!

What Ethernet library do you recommend for use with the Nuelectronics Ethershield?

    if ((check > 46) && (check < 123) || (check == 42)) {   // only 'good' characters, otherwise Ethershield won't send it/hangs

No clue what the significance of these magic numbers is.

    if ((check >= '/') && (check <= 'z') || (check == '*'))

makes a lot more sense to me.

          delay(2000UL);                   // delay 60s

If you are going to have useless comments, at least they should be right.

The random indenting does not make for readable code. Putting each { on a new line, deleting unnecessary blank lines, and using Tools + Autoformat would make for much more readable code.

Thanks again PaulS, for clearing this up!!

Yesterday I took another Ethershield (from Ekitzone) and upload this code to the Arduino:

#include "etherShield.h"

// serial info gewoon ontvangen via normale (pin 0) RX port op Arduino (rechtsbovenin)
// op het einde van de serial string "/" sturen i.v.m. terminate char! 
// aan het begin "*" sturen i.v.m. andere serial data wat verstuurd wordt via de BT module (ARF32)

static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x24}; 
static uint8_t myip[4] = {
  192,168,2,88};
static uint16_t my_port = 80;     // client port
static char client_ip[] = "192.168.2.88";
static uint8_t dest_ip[4]={
  192,168,2,53};
static uint8_t dest_mac[6];

enum CLIENT_STATE
{  
  IDLE, ARP_SENT, ARP_REPLY, SYNC_SENT
};

static CLIENT_STATE client_state;
static uint8_t client_data_ready;
static uint8_t syn_ack_timeout = 0;

#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];

boolean eerste = true;

byte lezen;

byte check;

char sensorData[150];
String readString;
bool klaar = false;

#define INLENGTH 150
#define INTERMINATOR 47 //eerst was het 0 oftewel 48 nu is het /
#define BEGINNER 42

char inString[INLENGTH+1];
int inCount;

EtherShield es=EtherShield();

uint16_t print_webpage(uint8_t *buf);
int8_t analyse_cmd(char *str);
// get current temperature
#define TEMP_PIN  3
void getCurrentTemp( char *temperature);
void client_process(void);

void setup(){

  //mySerial.begin(9600);

  Serial.begin(9600); 
  Serial.println("Begin!"); 

  /*initialize enc28j60*/
  es.ES_enc28j60Init(mymac);
  es.ES_enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
  delay(10);

  es.ES_enc28j60PhyWrite(PHLCON,0x880);
  delay(500);

  es.ES_enc28j60PhyWrite(PHLCON,0x990);
  delay(500);

  es.ES_enc28j60PhyWrite(PHLCON,0x880);
  delay(500);

  es.ES_enc28j60PhyWrite(PHLCON,0x990);
  delay(500);

  es.ES_enc28j60PhyWrite(PHLCON,0x476);
  delay(100);

  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip,80);

  // intialize varible;
  syn_ack_timeout =0;
  client_data_ready = 0;
  client_state = IDLE;
  // initialize DS18B20 datapin
  digitalWrite(TEMP_PIN, LOW);
  pinMode(TEMP_PIN, INPUT);  

  delay (3000);
}

void loop(){

  if (eerste == true){   //test email 1x

    sensorData[0] = '*';
    sensorData[1] = 'e';
    sensorData[2] = 'e';
    sensorData[3] = 0;

    client_data_ready = 1;
    client_process();
    eerste = false; 
  }

  if(client_data_ready==0){

    inCount = 0;

    do 
    {
      while(!Serial.available());

      sensorData[inCount] = Serial.read();

      if (sensorData[inCount] == '*'){
        sensorData[0] = '*';
        inCount = 0;
      }      

      if (sensorData[inCount] == '.'){
        sensorData[inCount] = '_';
      };

      if (sensorData [inCount] == INTERMINATOR) break;
    }
    while (++inCount < INLENGTH);

    sensorData[inCount] = 0;                     // null terminate the string

    Serial.println(sensorData);

    delay(2000UL);                   // delay 2s
    //sensorData[99] = '\0'; 
    if (sensorData[0] == BEGINNER){

      client_data_ready = 1;
    }
  }

  client_process();      
}


uint16_t gen_client_request(uint8_t *buf )
{
  uint16_t plen;
  byte i;

  plen= es.ES_fill_tcp_data_p(buf,0, PSTR ( "GET /ethershield_log/save.php?pwd=44&client=111" ) );
  for(i=0; client_ip[i]!='\0'; i++){
    buf[TCP_DATA_P+plen]=client_ip[i];
    plen++;
  }
  plen= es.ES_fill_tcp_data_p(buf,plen, PSTR ( "&status=" ) );
  for(i=0; sensorData[i]!='\0'; i++){

    buf[TCP_DATA_P+plen]=sensorData[i];
    plen++;
  }	


  //sensorData[0] = '\0';    // 12-10-2011 erbij gemaakt


  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( " HTTP/1.0\r\n" ));
  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Host: 192.168.2.53\r\n" ));
  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "User-Agent: AVR ethernet\r\n" ));
  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Accept: text/html\r\n" ));
  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Keep-Alive: 300\r\n" ));
  plen= es.ES_fill_tcp_data_p(buf, plen, PSTR ( "Connection: keep-alive\r\n\r\n" ));

  return plen;
}

void client_process ( void )
{
  uint16_t plen;
  uint8_t i;

  if (client_data_ready == 0)  return;   

  if(client_state == IDLE){   // initialize ARP
    es.ES_make_arp_request(buf, dest_ip);

    client_state = ARP_SENT;
    return;
  }


  if(client_state == ARP_SENT){

    plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

    if ( plen!=0 )
    {
      if ( es.ES_arp_packet_is_myreply_arp ( buf ) ){
        client_state = ARP_REPLY;
        syn_ack_timeout=0;
        return;
      }

    }
    delay(10);
    syn_ack_timeout++;


    if(syn_ack_timeout== 100) {
      client_state = IDLE;
      client_data_ready =0;
      syn_ack_timeout=0;
      return;
    }	
  }

  if(client_state == ARP_REPLY){

    for(i=0; i<6; i++){
      dest_mac[i] = buf[ETH_SRC_MAC+i];
    }

    es.ES_tcp_client_send_packet (
    buf,
    80,
    1200,
    TCP_FLAG_SYN_V,   
    1,   
    1, 
    0,      
    0,    
    dest_mac,
    dest_ip
      );

    client_state = SYNC_SENT;
  }

  if(client_state == SYNC_SENT){
    plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

    // no new packet incoming
    if ( plen == 0 )
    {
      return;
    }


    if ( es.ES_eth_type_is_ip_and_my_ip(buf,plen)==0){
      return;
    }


    if ( buf [ TCP_FLAGS_P ] == ( TCP_FLAG_SYN_V | TCP_FLAG_ACK_V ) )
    {

      // send ACK to answer SYNACK

      es.ES_tcp_client_send_packet (
      buf,
      80,
      1200,
      TCP_FLAG_ACK_V,   
      0, 
      0,   
      1,  
      0, 
      dest_mac,
      dest_ip
        );
 
      plen = gen_client_request( buf );

      es.ES_tcp_client_send_packet (
      buf,
      80,  
      1200, 
      TCP_FLAG_ACK_V | TCP_FLAG_PUSH_V,   
      0,  
      0,   
      0,  
      plen,   
      dest_mac,
      dest_ip
        );
      return;
    }

    if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_PUSH_V) )
    {
      plen = es.ES_tcp_get_dlength( (uint8_t*)&buf );


      es.ES_tcp_client_send_packet (
      buf,
      80,   
      1200, 
      TCP_FLAG_ACK_V,
      0,  
      0,  
      plen,   
      0,    
      dest_mac,
      dest_ip
        );
      ;
      // send finack to disconnect from web server

      es.ES_tcp_client_send_packet (
      buf,
      80,  
      1200,  
      TCP_FLAG_FIN_V|TCP_FLAG_ACK_V, 
      0,   
      0, 
      0,   
      0,
      dest_mac,
      dest_ip
        );

      return;

    }
    
    if ( buf [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_FIN_V) )
    {
      
      es.ES_tcp_client_send_packet(

      buf,
      80,  
      1200,  
      TCP_FLAG_ACK_V,
      0,   
      0,  
      1,   
      0,
      dest_mac,
      dest_ip
        );
      client_state = IDLE;
      client_data_ready =0;	
    }
  }       
}

This code works good for a couple of hours. After that it hangs and doesn’t send data to the PHP script anymore.
If I press the reset switch on the Ekitzone Ethershield (I think the Arduino is also getting reset then) it works good again.
I’m looking for an explanation, but I don’t get anywhere… how is this possible? A memory leak or something?

Normally the other (sending) Arduino is spitting out the serial string once a minute. The string looks like:

*yya1ab1bc0cd65.34de23.99ef23.09fg6666gh34.33hi13.85ij17jk11kl12lm30mn45no56op2pq1qr23rs10st22tu8uv12vw59wx11x[87]zzz/

The Arduino what were talking about has to receive this via UART, and pass it to my Ethershield.

For hours this goes very well… the MySQL database inserts a couple of hundred rows, and then again it all hangs and the script isn’t being triggered anymore…
So there is something terrible wrong with the code above, or the hardware (2 ethershields). I think the (my) code above :wink: but WHAT?

Anyone suggestions?

Thanks in advance,

Atmoz