EtherShield: broadcast + webserver

Hi all,

I'm using the EtherShield library (https://github.com/thiseldo/EtherShield) for my arduino server project. I'm would like to have a webserver and broadcast functionality within the same program but I'm unable to accomplish this. If I put each functionality in a separate program it's working ok, but when I put this together, only broadcast is working and webserver is unreachable.

I'll post my code later, but it's based on a library examples (EtherShield_broadcast + EtherShield_webserver) - webserver is always receiving requests and broadcast data is sent every 15 seconds.

Did anyone used this type of functionality?

Thank you.

It seems the problem with that code is the "while(1)" loops in the loop(). You should be able to remove those without affecting the code. Try that with each script until both work without the "while(1)" loop.

The "void loop()" is the same as "while(1)".

My code is bellow.

Broadcast is working, but I don’t get response from the web server.
If I comment the line for broadcast (broadcastData()) then the web server is working.

// EtherShield webserver demo
#include "EtherShield.h"

// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x25}; 
  
static uint8_t myip[4] = {
  192,168,1,6};

#define MYWWWPORT 80
#define BUFFER_SIZE 550
static uint8_t buf[BUFFER_SIZE+1];

// The ethernet shield
EtherShield es=EtherShield();

static uint8_t broadcastip[4] = {
  192,168,1,255};
  
// Port 52240
#define DEST_PORT_L  0x10
#define DEST_PORT_H  0xCC

const char iphdr[] PROGMEM ={
  0x45,0,0,0x82,0,0,0x40,0,0x20}; // 0x82 is the total
  
struct UDPPayload {
  uint32_t time;            // Time
  uint16_t temperature;     // Temp in 1/10 degree
  uint16_t data[10];        //watts data
  uint16_t errorCount;      // count of errors in the XML.
  uint16_t timeout_count;   // count of all protocol lockups
};

UDPPayload udpPayload;
uint8_t  srcport = 11023;
uint32_t lastUpdate = 0;

int counter = 0;


uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")));
}

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
  uint16_t plen;
  plen=http200ok();
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<html><head><title>Arduino ENC28J60 Ethernet Shield V1.0</title></head><body>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><h1>Welcome to Arduino ENC28J60 Ethernet Shield V1.0</h1>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));

  return(plen);
}


void setup(){

  // Initialise data in the payload structure
  for( int i=0; i<10; i++ ) {
    udpPayload.data[i] = i;
  }
  udpPayload.time = millis();
  udpPayload.temperature = 0;
  
  // initialize enc28j60
  es.ES_enc28j60Init(mymac);

  // init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  
  lastUpdate = millis();

  delay(10000);
}

void loop(){
  uint16_t plen, dat_p;

  counter++;
    // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));

    /* dat_p will be unequal to zero if there is a valid 
     * http get */
    if(dat_p==0){
      if (counter > 150){
        udpPayload.time = millis();
        udpPayload.temperature++;
        for( int i=0; i<10; i++ ) {
          udpPayload.data[i]++;
        }
        broadcastData() ;
        lastUpdate = millis();
        counter = 0;
      }
    } else {
    // tcp port 80 begin
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
      goto SENDTCP;
    }
    // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      dat_p=print_webpage(buf);
      goto SENDTCP;
    }
    else{
      dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
      goto SENDTCP;
    }
SENDTCP:
    es.ES_www_server_reply(buf,dat_p); // send web page data
    // tcp port 80 end
    }
delay(10);
}

// Broadcast the data in the udpPayload structure
void broadcastData( void ) {
  uint8_t i=0;
  uint16_t ck;
  // Setup the MAC addresses for ethernet header
  while(i<6){
    buf[ETH_DST_MAC +i]= 0xff; // Broadcsat address
    buf[ETH_SRC_MAC +i]=mymac[i];
    i++;
  }
  buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  es.ES_fill_buf_p(&buf[IP_P],9,iphdr);

  // IP Header
  buf[IP_TOTLEN_L_P]=28+sizeof(UDPPayload);
  buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  i=0;
  while(i<4){
    buf[IP_DST_P+i]=broadcastip[i];
    buf[IP_SRC_P+i]=myip[i];
    i++;
  }
  es.ES_fill_ip_hdr_checksum(buf);
  buf[UDP_DST_PORT_H_P]=DEST_PORT_H;
  buf[UDP_DST_PORT_L_P]=DEST_PORT_L;
  buf[UDP_SRC_PORT_H_P]=10;
  buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  buf[UDP_LEN_H_P]=0;
  buf[UDP_LEN_L_P]=8+sizeof(UDPPayload); // fixed len
  // zero the checksum
  buf[UDP_CHECKSUM_H_P]=0;
  buf[UDP_CHECKSUM_L_P]=0;
  // copy the data:
  i=0;
  // most fields are zero, here we zero everything and fill later
  uint8_t* b = (uint8_t*)&udpPayload;
  while(i< sizeof( UDPPayload ) ){ 
    buf[UDP_DATA_P+i]=*b++;
    i++;
  }
  // Create correct checksum
  ck=es.ES_checksum(&buf[IP_SRC_P], 16 + sizeof( UDPPayload ),1);
  buf[UDP_CHECKSUM_H_P]=ck>>8;
  buf[UDP_CHECKSUM_L_P]=ck& 0xff;
  es.ES_enc28j60PacketSend(42 + sizeof( UDPPayload ), buf);
}

The reason why I’m using the broadcast is time consumption for the web server - it takes approximately 10ms for webserver response and < 2ms for broadcast data and I would like to have fresh data every 15 seconds. Also, I’m using 4 7-segment displays to show live data and when accessing web server I get a little flickering on the display (because of 10ms operation time for web server response). Maybe it would be better If I put a web server on the other side (PC) and on the arduino side implement web client which would send data to the web server. I’ll have to do more testing.