Introduction: Send Sensor Data (DHT11 & BMP180) to ThingSpeak With an Arduino, Using ENC28J60 Ethercard

About: I am a physician by trade. After a career in the pharmeceutical world I decided to take it a bit slower and do things I like. Other than my hobbies that involves grassroots medicine in S.E.&P Asia. I have buil…

Note: This instructable is for the old ENC26J60 Ethershield and ethercard. If you have the modern WIZ5100 based Ethernetshield or an ESP8266 go visit my other instructable that I mention below

About a year and a half ago I published an instructable showing how to upload data to Thingspeak with an Arduino W5100 based Ethernet card or an ESP8266. There however is another ethernet card for the Arduino, being the ENC28J60 based Ethercard. It is available as Shield, but also as a module.

Though I wouldnt advise anybody to buy the Ethercard, as the W5100 Ethernetcard is more versatile, many people may still have one and rather than gathering dust one might as well put it to use

Things you need:
Arduino
ENC28J60 based EtherShield or Ethercard ( or module)
Thingspeak Account
Sensors (DHT11 and BMP180)
Internet connection

Step 1: Send Sensor Data (DHT11 & BMP180) to ThingSpeak With an Arduino, Using ENC28J60 Ethercard: Issues

The libraries

There are basically 4 libraries for the ENC28J60

Ethershield (development stopped) uses pin10 as chipselect
Ethercard develped to allow use of an SD card, uses pin 8 as chipselect
Ether_2860 from Simon Monk. If you do not already have that one, you probably will never get it.

UIPEthernet from Norbert Truchsess. This library is a drop in replacement for the WS5100 Ethernet library, it makes the ENC28J60 behave like a WIZ5100.That means that programs developed for the latter, can be used for the former, simply by replacing

#include <Ethernet.h> by #include <UIPEthernet.h>

However, that does require some memory.

When googling for the ethercard library, one may come across forks of the various libraries as well.

If for whatever reason you want to use the Ethercard library with pin 10 (e.g. if you use it with the Ethershield), change the pin assignment in the library files ENC28J60.h (line 25 and 41 I believe) and the EtherCard.h (Line 134: uint8_t csPin = 8 ). (Depending on the version it can also be in line 154.)

But it is easier to add the declaration for pin 10 in the program itself like this:

ether.begin(sizeof Ethernet::buffer, mymac, 10)

In this instructable I will be using the Ethercard library.

Powersupply
The Ethershield- and Ethercard shield as wel as most of the modules expect 3.3 Volt.

The Thingspeak Data Format
In my earlier instructable on Thingspeak, i discussed the dataformat and particularly that it expects strings, whereas the DHT11 and BMP180 deliver floats.

The program
Fortunately the EtherCard library had a good example to start from. Although Initially I added a routine to convert the float data to strings, I realized that the Ethercard library sends the data to Thingspeak through the print class. Generally this turns floats int strings. tested it and yes, I do not have to do a string conversion and still keep precision in the data.

The ENC28J60 is quite hungry regarding memory so the program has reached a critical mass with only 412 bytes to spare for local variables. I have had it running constantly for 2 days without any problem. I could probably win some memory by stripping the adafruit BMP library a bit,

Step 2: The Code

The program. As instructables is not great in publishing code, I suggest to use the file that i have added

// The full development history of this code is in the attached file

#include <EtherCard.h> // if this library disappeared, it is EtherCard.h
#include <Wire.h> // it is Wire.h
#include <Adafruit_BMP085.h> // it is Adafruit_BMP085.h
#include <dht11.h> // it is dht11.h
#define DHT11PIN 2
Adafruit_BMP085 bmp;
dht11 DHT11;
#define APIKEY "QTRR4654FRE3" // put your key here
#define ethCSpin 10 // put your CS/SS pin here.
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x75,0x68,0x68,0x68,0x68,0x68 };
const char website[] PROGMEM = "api.thingspeak.com";
byte Ethernet::buffer[700];
uint32_t timer;
Stash stash;
byte session;
//timing variable
int res = 100; // was 0

void setup () {
  Serial.begin(9600);
  Serial.println("\n[ThingSpeak example]");

  //Initialize Ethernet
  initialize_ethernet();
}

void loop () { 
  //------DHT11--------
int chk = DHT11.read(DHT11PIN);
int t=(DHT11.temperature);
int h=(DHT11.humidity);

//-----BMP180-----------
bmp.begin();
            float p=(bmp.readPressure()/100.0);//this is for pressure in hectoPascal
            float m=(bmp.readPressure()/133.3);//  this is for pressure in mmHG
            float t2=(bmp.readTemperature());
          
 //------ENC28J60----------
  //if correct answer is not received then re-initialize ethernet module
  if (res > 220){
    initialize_ethernet(); 
  }
  
  res = res + 1;
  
  ether.packetLoop(ether.packetReceive());
  
  //200 res = 10 seconds (50ms each res)
  if (res == 200) {

    
    // field1=(Field 1 Data)&field2=(Field 2 Data)&field3=(Field 3 Data)&field4=(Field 4 Data)&field5=(Field 5 Data)&field6=(Field 6 Data)&field7=(Field 7 Data)&field8=(Field 8 Data)&lat=(Latitude in Decimal Degrees)&long=(Longitude in Decimal Degrees)&elevation=(Elevation in meters)&status=(140 Character Message)
    byte sd = stash.create();
    stash.print("field1=");
    stash.print(t);
    stash.print("&field2=");
    stash.print(h);
    stash.print("&field3=");
    stash.print(p);
    stash.print("&field4=");
    stash.print(t2);
    stash.print("&field5=");
    stash.print(t);
    stash.print("&field6=");
    stash.print(h);
    stash.print("&field7=");
    stash.print(p);
    stash.print("&field8=");
    stash.print(t2);
    stash.save();

      // generate the header with payload - note that the stash size is used,
    // and that a "stash descriptor" is passed in as argument using "$H"
    Stash::prepare(PSTR("POST /update HTTP/1.0" "\r\n"
      "Host: $F" "\r\n"
      "Connection: close" "\r\n"
      "X-THINGSPEAKAPIKEY: $F" "\r\n"
      "Content-Type: application/x-www-form-urlencoded" "\r\n"
      "Content-Length: $D" "\r\n"
      "\r\n"
      "$H"),
    website, PSTR(APIKEY), stash.size(), sd);

    // send the packet - this also releases all stash buffers once done
    session = ether.tcpSend(); 

 // added from: http://jeelabs.net/boards/7/topics/2241
 int freeCount = stash.freeCount();
    if (freeCount <= 3) {   Stash::initMap(56); } 
  }
  
   const char* reply = ether.tcpReply(session);
   
   if (reply != 0) {
     res = 0;
    // Serial.println(F(" >>>REPLY recieved...."));
    // Serial.println(reply);
   }
   delay(300);
}



void initialize_ethernet(void){  
  for(;;){ // keep trying until you succeed 
    //Reinitialize ethernet module
    //Serial.println("Reseting Ethernet...");
    //digitalWrite(5, LOW);
    //delay(1000);
    //digitalWrite(5, HIGH);
    //delay(500);

    if (ether.begin(sizeof Ethernet::buffer, mymac, ethCSpin) == 0){ 
      Serial.println( F("Failed to access Ethernet controller"));
      continue;
    }
    
    if (!ether.dhcpSetup()){
      Serial.println(F("DHCP failed"));
      continue;
    }

    ether.printIp("IP:  ", ether.myip);
    ether.printIp("GW:  ", ether.gwip);  
    ether.printIp("DNS: ", ether.dnsip);  

    if (!ether.dnsLookup(website))
      Serial.println(F("DNS failed"));

    ether.printIp("SRV: ", ether.hisip);

    //reset init value
    res = 180;
    break;
  }
}

----------------