Go Down

Topic: Basic Analog Pin reporting using ENCENC28J60 EthernetShield (Read 2013 times) previous topic - next topic

binooetomo

Hi,
I'll share this to others who just start playing with ENC28J60 ethernetshield.
Reasons :
1. I received so many help/enlighment from others
2. This Shield is not Official , so there is no "standardize" Library for it.

Credits goes to :
1. Andy , http://blog.thiseldo.co.uk/?p=344 , For his ENC28J60 Arduino Library.
2. Trystan , http://openenergymonitor.org/emon/node/88.
3. PaulS, http://arduino.cc/forum/index.php?action=profile;u=16084 , Tonns of enlighment.
4. Gus , http://projectgus.com/2010/07/eeprom-access-with-arduino/

Ok , Here we go.

Important note : I made a small modification of Andy's library. It's a good library, but do not "end user" to make change of HOSTNAME (need to be hardcoded at sketch level). I don't want this, so I made small modification.
Here it is :

Code: [Select]

Modification to --> ip_arp_udp_tcp.c
1. Look for --> #if defined (WWW_client) , around line# 1310
2. Look for --> //GET , around line# 1316
3. Commen out all :
len=fill_tcp_data_p(bufptr,0,PSTR("GET "));
len=fill_tcp_data_p(bufptr,len,client_urlbuf);
if( client_urlbuf_var )
len=fill_tcp_data(bufptr,len,client_urlbuf_var);
// I would prefer http/1.0 but there is a funny
// bug in some apache webservers which causes
// them to send two packets (fragmented PDU)
// if we don't use HTTP/1.1 + Connection: close
len=fill_tcp_data_p(bufptr,len,PSTR(" HTTP/1.1\r\nHost: "));
len=fill_tcp_data_p(bufptr,len,client_hoststr);
len=fill_tcp_data_p(bufptr,len,PSTR("\r\nUser-Agent: EtherShield/1.6\r\nAccept: text/html\r\nConnection: close\r\n\r\n"));

4. Replace with :
len=fill_tcp_data(bufptr,0,client_urlbuf_var);



Arduino sketch.
A. Main Sketch
Code: [Select]
/*
WE USE MODIFIED VERSION OF Andy's Library ver 1.6
*/
#include <EtherShield.h>
//#include <EEPROM.h>
#include<string.h>

//Structured EEPROM--START
#include <avr/eeprom.h>

#define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block(dst_p, (void *)offsetof(__eeprom_data, eeprom_field), MIN(dst_size, sizeof((__eeprom_data*)0)->eeprom_field))
#define eeprom_read(dst, eeprom_field) eeprom_read_to(&dst, eeprom_field, sizeof(dst))
#define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block(src_p, (void *)offsetof(__eeprom_data, eeprom_field), MIN(src_size, sizeof((__eeprom_data*)0)->eeprom_field))
#define eeprom_write(src, eeprom_field) { typeof(src) x = src; eeprom_write_from(&x, eeprom_field, sizeof(x)); }
#define MIN(x,y) ( x > y ? y : x )

//const int buflen = 32;

/*
* __eeprom_data is the magic name that maps all of the data we are
* storing in our EEPROM
*/
struct __eeprom_data {
byte magic;
byte mac[6];
byte ip[4];
byte gw[4];
byte srv[4];
char host[40];
char callfile[20];
byte conflen[10];
char nodeid[10];
char nodepin[10];
};

//Structured EEPROM--STOP

//----ETH VARS-------------------------------
#define PORT 80                   // Ndak bisa di rubah
byte magic;
byte mac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
byte ip[4] = {192,168,10,231};
byte gw[4] = {192,168,10,1};
byte srv[4] = { 192,168,10,232 }; // Get pachube ip by DNS call
char host[40]="telemetry.bino.int";
char callfile[20]="/post.php?"  ;    // Set your own feed ID here
byte conflen[10]={0,0,0,0,0,0,0,0,0,0};
char nodeid[10]="mynodeid";
char nodepin[10]="mynodepin";
byte mymagic=0x0a;

uint8_t resend=0;
int8_t dns_state=0;
uint32_t timetosend=millis();
uint16_t dat_p;
long lastDnsRequest = 0L;
int plen = 0;

EtherShield es=EtherShield();

#define BUFFER_SIZE 550
uint8_t buf[BUFFER_SIZE+1];
//-------------VARS to SEND------------------------------
int sendvarlen = 6;
char sendvarname[6][5]={"s0","s1","s2","s3","s4","s5"};
char sendvarval[6][10]={"0","0","0","0","0","0"};
//-------------------------------------------------
//----FOR Menuing----
boolean inmenu = false;
boolean waitentry=false;

void setup(){
  Serial.begin(9600);
  eeprom_read(magic, magic);
  if (magic != mymagic)
  {
    delay(3000);
    Serial.print("FIRST BLOOD !!!");
    magic = mymagic;
    saveall();
  }
  readall();

  delay(100);
 
  es.ES_enc28j60Init(mac);

  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mac, ip, PORT);

  // init the web client:
  es.ES_client_set_gwip(gw);  // e.g internal IP of dsl router
  es.ES_client_set_wwwip(srv);
}


void loop()
{
  //Do this in any condition
  dns_state=2;
  // handle ping and wait for a tcp packet - calling this routine powers the sending and receiving of data
  // If we have IP address for server and its time then request data
  ethReady();
  //---------------------------

  if (!inmenu)
  {
    if (Serial.available())
    {
      if (Serial.read() == 'c')
      {
        printmenu();
      }
    }
    else
    {
      domainproc();
    }
  }
  else
  {
    if (Serial.available())
    {
      domenu();
    }   
  }
}

void domainproc()
{
  if(millis() - timetosend > 1000)  // every 10 seconds
  {
    timetosend = millis();
    readsensor();
    ethSend();
  }
}



void readsensor()
{
  for (int i = 0 ; i < sendvarlen ; i++)
  {

    itoa(analogRead(i),sendvarval[i],10);
  }
}


Oppss ... I need to post 2 other part seperately

binooetomo

B. Any Ethernet bussiness
Code: [Select]
void ethSetup()
{
  //Serial.println("Setup Ethernet");
  /*initialize enc28j60*/
  es.ES_enc28j60Init(mac);

  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mac, ip, PORT);

  // init the web client:
  es.ES_client_set_gwip(gw);  // e.g internal IP of dsl router
  es.ES_client_set_wwwip(srv);
  timetosend = millis();
}

void ethReady()
{
  plen=0;
  plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
  dat_p=es.ES_packetloop_icmp_tcp(buf,plen);
}

void ethSend()
{
      char HTTPCALL[chkvarlen() + 150];
      strcpy(HTTPCALL, "GET ");
      strcat(HTTPCALL, callfile);
      strcat(HTTPCALL, "nodeid=");
        strcat(HTTPCALL, nodeid);
        strcat(HTTPCALL, "&");
      strcat(HTTPCALL, "nodepin=");
        strcat(HTTPCALL, nodepin);
        strcat(HTTPCALL, "&");
      for (int z = 0 ; z < sendvarlen ; z++)
      {
        strcat(HTTPCALL,sendvarname[z]);
        strcat(HTTPCALL,"=");
        strcat(HTTPCALL,sendvarval[z]);
        if (z < sendvarlen-1)
        {
          strcat(HTTPCALL,"&");
        }
      }
      strcat(HTTPCALL, " HTTP/1.1\r\nHost: ");
      strcat(HTTPCALL, host);
      strcat(HTTPCALL, "\r\nUser-Agent: EtherShield/1.6\r\nAccept: text/html\r\nConnection: close\r\n\r\n");
      //-------END----Struct the HTTPCALL

      Serial.println("HTTP Data To Send");
     
      Serial.println(HTTPCALL);
     
      // note the use of PSTR - this puts the string into code space and is compulsory in this call
      // second parameter is a variable string to append to HTTPPATH, this string is NOT a PSTR
      //es.ES_client_browse_url(PSTR(HTTPPATH), NULL, PSTR(HOSTNAME), &browserresult_callback);
      //es.ES_client_browse_url(PSTR(HTTPPATH), strtimetosend, PSTR(HOSTNAME), &browserresult_callback);
      //es.ES_client_browse_url(PSTR(HTTPPATH), strtimetosend, PSTR(""), &browserresult_callback);
      es.ES_client_browse_url(callfile, HTTPCALL, host, &browserresult_callback);
}

int chkvarlen()
{
  int retval=0;
  for (int i=0; i<sendvarlen; i++)
  {
    retval = retval + strlen(sendvarname[i]);
    retval = retval + strlen(sendvarval[i]);
  }
  retval = retval + (2 * sendvarlen);
   
  int ii = strlen(callfile) + strlen(host) + strlen(nodeid) + strlen(nodepin);

  retval = retval + ii;


  return retval;
}

void browserresult_callback(uint8_t statuscode,uint16_t datapos){
  if (datapos != 0)
  {
    /*
    // now search for the csv data - it follows the first blank line
    // I'm sure that there is an easier way to search for a blank line - but I threw this together quickly
    // and it works for me.
    uint16_t pos = datapos;
    while (buf[pos])    // loop until end of buffer (or we break out having found what we wanted)
    {
      while (buf[pos]) if (buf[pos++] == '\n') break;   // find the first line feed
      if (buf[pos] == 0) break; // run out of buffer
      if (buf[pos++] == '\r') break; // if it is followed by a carriage return then it is a blank line (\r\n\r\n)
    }
    if (buf[pos])  // we didn't run out of buffer
    {
      pos++;  //skip over the '\n' remaining
      Serial.println((char*)&buf[pos]);
    }
    */
  }
}




binooetomo

#2
Feb 05, 2011, 04:27 am Last Edit: Feb 05, 2011, 04:32 am by binooetomo Reason: 1
C. Configuration menu Bussiness.
Code: [Select]
void printmenu()
{
  Serial.println("Configuration");
  Serial.println("---------------");

  Serial.print("1. MAC Address ");
    Serial.print("[");
    for (int i=0; i<6; i++)
    {
      Serial.print(mac[i],HEX);
      if (i<5)
      {
        Serial.print(".");
      }
    }
    Serial.println("]");
   
  Serial.print("2. IP Address [");
    for (int i=0; i<4; i++)
    {
      Serial.print(ip[i],DEC);
      if (i<3)
      {
        Serial.print(".");
      }
    }
    Serial.println("]");

  Serial.print("3. Gateway [");
    for (int i=0; i<4; i++)
    {
      Serial.print(gw[i],DEC);
      if (i<3)
      {
        Serial.print(".");
      }
    }
    Serial.println("]");

  Serial.print("4. Server IP [");
    for (int i=0; i<4; i++)
    {
      Serial.print(srv[i],DEC);
      if (i<3)
      {
        Serial.print(".");
      }
    }
    Serial.println("]");

  Serial.print("5. Server Name [");
    Serial.print(host);
    Serial.println("]");

  Serial.print("6. File to Call[");
    Serial.print(callfile);
    Serial.println("]");

  Serial.print("7. Node ID [");
    Serial.print(nodeid);
    Serial.println("]");

  Serial.print("8. Node PIN [");
    Serial.print(nodepin);
    Serial.println("]");

  Serial.println("s. Save");

  Serial.println("x. Exit ");

  Serial.println("---------------");

  Serial.print("Option : ");
 
  inmenu = true;
}

void domenu()
{
  switch (Serial.read())
  {
    case '1':
      domenu1();
      break;
    case '2':
      domenu2();
      break;
    case '3':
      domenu3();
      break;
    case '4':
      domenu4();
      break;
    case '5':
      domenu5();
      break;
    case '6':
      domenu6();
      break;
    case '7':
      domenu7();
      break;
    case '8':
      domenu8();
      break;
    case 's' :
      domenu_save();
      break;
    case 'x' :
      domenu_exit();
      break;
  }
  if (inmenu)
  {
    printmenu();
  }
}
void domenu1()
{
  Serial.println("1");
  Serial.print("Enter MAC Address : ");
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(10);
      for (int x=0 ; x<6; x++)
      {
        int i = 0;
        char inchar[3]="";
        while (Serial.available() && i<3)
        {
          char serchar = Serial.read();
          Serial.print(serchar);
          if (serchar == 13 || serchar == '.')
          {
            delay(10);
            break;
          }
          else
          {
            inchar[i]=serchar;
            i++;
          }
        }
        mac[x] = ( htoi(inchar[0]) * 16 ) + htoi(inchar[1]);
      }
      Serial.println();
      waitentry = false;
    }
  } 
}
int htoi (char c) {  //does not check that input is valid
/*
By : mspguy
at : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1292893820
*/
    if (c<='9')
        return c-'0';
    if (c<='F')
        return c-'A'+10;
    if (c<='f')
        return c-'a'+10;
    return 0;
}
void domenu2()
{
  Serial.println("2");
  Serial.print("Enter IP Address : ");
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(10);
      for (int x=0 ; x<4; x++)
      {
        int i = 0;
        char inchar[4]="";
        while (Serial.available() && i<4)
        {
          char serchar = Serial.read();
          Serial.print(serchar);
          if (serchar == 13 || serchar == '.')
          {
            delay(10);
            break;
          }
          else
          {
            inchar[i]=serchar;
            i++;
          }
        }
        ip[x] = atoi(inchar);
      }
      Serial.println();
      waitentry = false;
    }
  } 
}
void domenu3()
{
  Serial.println("3");
  Serial.print("Enter  Gateway IP Address : ");
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(10);
      for (int x=0 ; x<4; x++)
      {
        int i = 0;
        char inchar[4]="";
        while (Serial.available() && i<4)
        {
          char serchar = Serial.read();
          Serial.print(serchar);
          if (serchar == 13 || serchar == '.')
          {
            delay(10);
            break;
          }
          else
          {
            inchar[i]=serchar;
            i++;
          }
        }
        gw[x] = atoi(inchar);
      }
      Serial.println();
      waitentry = false;
    }
  } 
}
void domenu4()
{
  Serial.println("4");
  Serial.print("Enter Server IP Address : ");
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(10);
      for (int x=0 ; x<4; x++)
      {
        int i = 0;
        char inchar[4]="";
        while (Serial.available() && i<4)
        {
          char serchar = Serial.read();
          Serial.print(serchar);
          if (serchar == 13 || serchar == '.')
          {
            delay(10);
            break;
          }
          else
          {
            inchar[i]=serchar;
            i++;
          }
        }
        srv[x] = atoi(inchar);
      }
      Serial.println();
      waitentry = false;
    }
  } 
}


void domenu5()
{
  Serial.println("5");
  Serial.print("Enter Server Hostname :");
  int i = 0;
  char commandbuffer[40];
  delay(30);
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(30);
      while (Serial.available() && i<40)
      {
        commandbuffer[i++] = Serial.read();
      }
      if (i>0)
      {
        memset(host, '\0', sizeof(host));

        commandbuffer[i++]='\0';
        strcpy(host, commandbuffer);
        Serial.println(host);
      }
      waitentry = false;
    }
  } 
}
void domenu6()
{
  Serial.println("6");
  Serial.print("Enter File to call :");
  int i = 0;
  char commandbuffer[20];
  delay(30);
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(30);
      while (Serial.available() && i<20)
      {
        commandbuffer[i++] = Serial.read();
      }
      if (i>0)
      {
        memset(callfile, '\0', sizeof(callfile));

        commandbuffer[i++]='\0';
        strcpy(callfile, commandbuffer);
        Serial.println(callfile);
      }
      waitentry = false;
    }
  } 
}
void domenu7()
{
  Serial.println("7");
  Serial.print("Enter Our Node ID : ");
  int i = 0;
  char commandbuffer[10];
  delay(30);
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(30);
      while (Serial.available() && i<10)
      {
        commandbuffer[i++] = Serial.read();
      }
      if (i>0)
      {
        memset(nodeid, '\0', sizeof(nodeid));

        commandbuffer[i++]='\0';
        strcpy(nodeid, commandbuffer);
        Serial.println(nodeid);
      }
      waitentry = false;
    }
  } 
}
void domenu8()
{
  Serial.println("8");
  Serial.print("Enter Our Node PIN : ");
  int i = 0;
  char commandbuffer[10];
  delay(30);
  waitentry=true;
  while (waitentry)
  {
    if (Serial.available()>0)
    {
      delay(30);
      while (Serial.available() && i<10)
      {
        commandbuffer[i++] = Serial.read();
      }
      if (i>0)
      {
        memset(nodepin, '\0', sizeof(nodepin));

        commandbuffer[i++]='\0';
        strcpy(nodepin, commandbuffer);
        Serial.println(nodepin);
      }
      waitentry = false;
    }
  } 
}



void domenu_save()
{
  Serial.println("SAVE");
  saveall();
}
void domenu_exit()
{
  Serial.println("EXIT !!");
  Serial.println();
  Serial.println();
  inmenu = false;
  Serial.flush();
}

void saveall()
{
  eeprom_write(magic, magic);
  eeprom_write_from(mac, mac,6);
  eeprom_write_from(ip, ip,4);
  eeprom_write_from(gw, gw,4);
  eeprom_write_from(srv, srv,4);
  eeprom_write_from(host, host,strlen(host)+1);
  conflen[0]=strlen(host);
  eeprom_write_from(callfile, callfile,strlen(callfile)+1);
  conflen[1]=strlen(callfile);
 
  eeprom_write_from(nodeid,nodeid,strlen(nodeid)+1);
  conflen[2]=strlen(nodeid);
 
  eeprom_write_from(nodepin,nodepin,strlen(nodepin)+1);
  conflen[3]=strlen(nodepin);



  eeprom_write_from(conflen, conflen,10);

}
void readall()
{
  eeprom_read_to(conflen, conflen,10);
  eeprom_read(magic, magic);
  eeprom_read_to(mac, mac,6);
  eeprom_read_to(ip, ip,4);
  eeprom_read_to(gw, gw,4);
  eeprom_read_to(srv, srv,4);
  memset(host, '\0', sizeof(host));
  eeprom_read_to(host, host,conflen[0]);
  memset(callfile, '\0', sizeof(callfile));
  eeprom_read_to(callfile, callfile,conflen[1]);
 
  memset(nodeid, '\0', sizeof(nodeid));
  eeprom_read_to(nodeid, nodeid,conflen[2]);

  memset(nodepin, '\0', sizeof(nodepin));
  eeprom_read_to(nodepin, nodepin,conflen[3]);

}


Thats all.

Now I need to learn on WebServer feature of Andy's library.
My USB port always dead when I Plug my EthernetShield.
So I think it'll be better if the configuration is using web based configuration form.
Hopefully I don't crack my lame brain down.

Sincerely
-bino-

teamgbc

Hey Bino,

Thanks for your post, but I'm trying to make a really simple example to show how to use the Arduino as a Client to post data to a database using PHP/MySQL leveraging your post by basically making it bare-bones.

I have run it trying to do a few things but I some Errors that I don't really know much about as I am not an full-fledge programmer.

I get one error:
  Invalid conversion from 'void(*)(uint8_t,uint16_t)' to 'void(*)(uint8_t,uint16_t,uint16_t)' when trying to compile.

So for fun, I added a blank uint16_t in the callback function, just to make it compile.  In anycase, when I upload to the Arduino, I can see that the HTTPCALL does function, but I have no idea whether I am actually connecting or sending data to my PHP script. (I check the db to see if it arrives, to no avail).

How can I make the below code work? What am I missing? Did I take out too much?

How can I see whether it is connecting to my PHP script?  Why did I get that error?

SO MANY QUESTIONS! hahah....

Anyway, your help and guidance would be greatly appreciated! 

CHEERS!

Code: [Select]

/*
WE USE MODIFIED VERSION OF Andy's Library ver 1.6
*/

#include <etherShield.h>

#include <string.h>


//----ETH VARS-------------------------------


#define PORT 80           // Ndak bisa di rubah

byte magic;
byte mac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
byte ip[4] = {192,168,1,203}; // ip of arduino
byte gw[4] = {192,168,1,245};  //ip of router
byte srv[4] = { 192,168,1,66 }; // ip of server
char host[13]="192.168.1.66";   // server name?
char callfile[21]="/ethernet_to_db.php?"  ;    // place to put crap
byte mymagic=0x0a;

int8_t dns_state=0;
uint32_t timetosend=millis();
uint16_t dat_p;
//long lastDnsRequest = 0L;
int plen = 0;

EtherShield es= EtherShield();

#define BUFFER_SIZE 550
uint8_t buf[BUFFER_SIZE+1];
//--------------------------------------------

void setup(){
  Serial.begin(9600);

 
  es.ES_enc28j60Init(mac);

  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mac, ip, PORT);
o a
  // init the web client:
  es.ES_client_set_gwip(gw);  // e.g internal IP of dsl router
  es.ES_client_set_wwwip(srv);
 
 
  timetosend = millis();
   
 
}


void loop()
{
  //Do this in any condition
  dns_state=2;
  // handle ping and wait for a tcp packet - calling this routine powers the sending and receiving of data
  // If we have IP address for server and its time then request data
  ethReady();
  //---------------------------


  if(millis() - timetosend > 1000)  // every 10 seconds
  {
    timetosend = millis();

    ethSend();
  }
}



void ethReady()
{
  plen=0;
  plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
  dat_p=es.ES_packetloop_icmp_tcp(buf,plen);

}

void ethSend()
{
      char HTTPCALL[150];
      strcpy(HTTPCALL, "GET ");
      strcat(HTTPCALL, callfile);
      strcat(HTTPCALL, "value=HELLO");
        //strcat(HTTPCALL, nodeid);
        //strcat(HTTPCALL, "&");
      //strcat(HTTPCALL, "nodepin=");
        //strcat(HTTPCALL, nodepin);
       // strcat(HTTPCALL, "&");

      strcat(HTTPCALL, " HTTP/1.0\r\nHost: ");
      strcat(HTTPCALL, host);
      strcat(HTTPCALL, "\r\nUser-Agent: EtherShield/1.6\r\nAccept: text/html\r\nConnection: close\r\n\r\n");
      //-------END----Struct the HTTPCALL

      Serial.println("HTTP Data To Send");
     
      Serial.println(HTTPCALL);
     
      // note the use of PSTR - this puts the string into code space and is compulsory in this call
      // second parameter is a variable string to append to HTTPPATH, this string is NOT a PSTR
      //es.ES_client_browse_url(PSTR(HTTPPATH), NULL, PSTR(HOSTNAME), &browserresult_callback);
      //es.ES_client_browse_url(PSTR(HTTPPATH), strtimetosend, PSTR(HOSTNAME), &browserresult_callback);
      //es.ES_client_browse_url(PSTR(HTTPPATH), strtimetosend, PSTR(""), &browserresult_callback);

//The actual code to send data to PHP script:
      es.ES_client_browse_url(callfile, HTTPCALL, host, &browserresult_callback);
       
}

void browserresult_callback(uint8_t statuscode,uint16_t datapos){
  if (datapos != 0)
  {
   //removed since all was commented out anyway
   
  }
}




Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy