ethershield + LCD

Hi All

I'm using a couple of maxim DS18B20's and an ethershield to create a basic xml page showing the current temperature from the two sensors. I decided to add an LCD unit (16x2, supported by the LiquidCrystal lib) to show the temperature as well, but I just can't get it to work.

I've stripped out all the code that changes what the LCD is showing and am just having it display a string on each line during setup (working) and then changing this to be a different string in the loop (not working, no update happens). I then went back to basics and created a new prog which uses just the lcd code, everything else pulled out. This works, so the LCD unit itself is ok.

Even stranger, when I visit the web page for the first time after the prog is reset, the "-" in the "Sensor 1 - " string is removed from the LCD and never comes back.

The code isn't very clean and probably doesn't follow best practice, but compiles, and I can't see what's wrong with it. I'd be very grateful if anyone has any ideas!

#include <OneWire.h>
#include <string.h>
#include "etherShield.h"
#include <LiquidCrystal.h>

OneWire ds(3);
byte addresses[2][8];
byte i;
int x = 0;

LiquidCrystal lcd(12, 11, 4, 5, 6, 7);

char temp_strings[2][10];

static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 
static uint8_t myip[4] = {192,168,10,15};
static char baseurl[]="http://192.168.10.15/";
static uint16_t mywwwport = 80;

#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];
#define STR_BUFFER_SIZE 22
static char strbuf[STR_BUFFER_SIZE+1];

EtherShield es=EtherShield();


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

void setup() {
  Serial.begin(9600);
  byte addr[8];
  byte done = 0;
  
  lcd.begin(16, 2);
  lcd.print("Sensor 1 - ");
  lcd.setCursor(0, 1);
  lcd.print("Sensor 2 - ");  
  
  /*initialize enc28j60*/
  es.ES_enc28j60Init(mymac);
  es.ES_enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
  delay(10);
  
  /* Magjack leds configuration, see enc28j60 datasheet, page 11 */
  // LEDA=green LEDB=yellow
  //
  // 0x880 is PHLCON LEDB=on, LEDA=on
  // enc28j60PhyWrite(PHLCON,0b0000 1000 1000 00 00);
  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);
  
  Serial.println("Searching for OneWire Devices....");

  while ( !done )
  {
    if ( ds.search(addr) != 1)
    {
      Serial.print("No more addresses.\n");
      ds.reset_search();
      done = 1;
      return;
    }
    else
    {
      Serial.print("Found ");
      printAddress(addr);   
    }
    if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.println(", but CRC is not valid!");
      return;
    }
  
    if ( addr[0] != 0x28) {
      Serial.println(", but Device is not a DS18B20 family device!");
      return;
    }
    memcpy(addresses[x], addr, 8);
    x++;
    Serial.println(" - DS18B20 device accepted.");
  }

}

void loop(void){

  uint16_t plen, dat_p;
  int8_t cmd;
  
  Serial.println("got here");
  lcd.setCursor(0,0);
  lcd.print("Sensor1 - 12.34");
  lcd.setCursor(0,1);
  lcd.print("Sensor2 - 56.78");
  Serial.println("got here too");
  
  plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);

      /*plen will ne unequal to zero if there is a valid packet (without crc error) */
  if(plen!=0){
                 
    // arp is broadcast if unknown but a host may also verify the mac address by sending it to a unicast address.
    if(es.ES_eth_type_is_arp_and_my_ip(buf,plen)){
      es.ES_make_arp_answer_from_request(buf);
      return;
    }

    // check if ip packets are for us:
    if(es.ES_eth_type_is_ip_and_my_ip(buf,plen)==0){
      return;
    }
    
    if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
      es.ES_make_echo_reply_from_request(buf,plen);
      return;
    }
    
    // tcp port www start, compare only the lower byte
    if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==mywwwport){
      if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){
         es.ES_make_tcp_synack_from_syn(buf); // make_tcp_synack_from_syn does already send the syn,ack
         return;     
      }
      if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
        es.ES_init_len_info(buf); // init some data structures
        dat_p=es.ES_get_tcp_data_pointer();
        if (dat_p==0){ // we can possibly have no data, just ack:
          if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){
            es.ES_make_tcp_ack_from_any(buf);
          }
          return;
        }
        if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
            plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
            goto SENDTCP;
        }
       if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
                plen=print_webpage(buf);
            goto SENDTCP;
         }
        cmd=analyse_cmd((char *)&(buf[dat_p+5]));
        if (cmd==1){
             plen=print_webpage(buf);
        }
SENDTCP:  es.ES_make_tcp_ack_from_any(buf); // send ack for http get
           es.ES_make_tcp_ack_with_data(buf,plen); // send data       
      }
    }
  }
  
}

uint8_t find_key_val(char *str,char *key)
{
        uint8_t found=0;
        uint8_t i=0;
        char *kp;
        kp=key;
        while(*str &&  *str!=' ' && found==0){
                if (*str == *kp){
                        kp++;
                        if (*kp == '\0'){
                                str++;
                                kp=key;
                                if (*str == '='){
                                        found=1;
                                }
                        }
                }else{
                        kp=key;
                }
                str++;
        }
        if (found==1){
                // copy the value to a buffer and terminate it with '\0'
                while(*str &&  *str!=' ' && *str!='&' && i<STR_BUFFER_SIZE){
                        strbuf[i]=*str;
                        i++;
                        str++;
                }
                strbuf[i]='\0';
        }
        return(found);
}

int8_t analyse_cmd(char *str)
{
        int8_t r=-1;
     
        if (find_key_val(str,"cmd")){
                if (*strbuf < 0x3a && *strbuf > 0x2f){
                        // is a ASCII number, return it
                        r=(*strbuf-0x30);
                }
        }
        return r;
}

void getOneWireTempFromAddr(byte address[8], int sensorno){
    byte present = 0; 
    byte data[12];
    float temperature = 0.0;
    byte ms = 0;
    byte ls = 0;
    int j;
  
    ds.reset();
    ds.select(address);
    ds.write(0x44);
    delay(1000);
    present = ds.reset();
    ds.select(address);    
    ds.write(0xBE);         // Read Scratchpad
    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
      if(i == 0) ls = data[i];
      if(i == 1) ms = data[i];
    }
    //process ms bit   
    for(j = 7; j > 4; j--){
      if((ms & 1) == 1) temperature = temperature + pow(2, (11 - j));
      ms = ms >> 1;
    }
    //process ls bit
    for(j = 7; j >= 0; j--){
      if((ls & 1) == 1) temperature = temperature + pow(2, (3 - j));
      ls = ls >> 1;
    }
    //turn temp float into char
    int tempdec = (temperature - (int)temperature) * 100;
    if(tempdec < 10){
      sprintf(temp_strings[sensorno], "%0d.0%d", int(temperature), tempdec);
    }else{
      sprintf(temp_strings[sensorno], "%0d.%d", int(temperature), tempdec);
    }
    Serial.println(temp_strings[sensorno]);
    //Serial.println(temp);
    //temp = "21.34";
    
}

void printAddress(byte address[8]){
  for( i = 1; i < 7; i++)
  {
    Serial.print(address[i], HEX);
    if(i != 6) Serial.print(":");
  }
}

uint16_t print_webpage(uint8_t *buf){

  
        getOneWireTempFromAddr(addresses[0], 0);
        getOneWireTempFromAddr(addresses[1], 1);

        uint16_t plen;
           plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/xml\r\n\r\n"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<?xml version=\"1.0\" encoding=\"ASCII\" standalone=\"yes\"?>"));
             plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<tempsensors>"));
       
        for(int z = 0; z < 2; z++){
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<sensor><name>Sensor"));        
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</name><temp>"));          
          i=0;
          while (temp_strings[z][i]) {
                  buf[TCP_CHECKSUM_L_P+3+plen]=temp_strings[z][i++];
                  plen++;
          }
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</temp></sensor>"));
        }       
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</tempsensors>"));
        return(plen);
 }

Many thanks!

EDIT: the "got here" and "got here too" in the loop are continuously appearing on the serial console, so it is looping through the code.

LiquidCrystal lcd([glow]12, 11[/glow], 4, 5, 6, 7);

http://arduino.cc/en/Main/ArduinoEthernetShield

Arduino communicates with both the W5100 and SD card using the SPI bus (through the ICSP header). This is on digital pins 11, 12, and 13 on the Duemilanove

Can't imagine what your problem is...

Thanks for your reply paul. I'm using the ethershield, based on the ENC28J60 chip, but same applies and it's using SPI.

Thanks for your help :slight_smile:

I'm using the ethershield, based on the ENC28J60 chip

I guess I missed that in your initial post.