Adapting sketch from Ethernet Shield to WiShield

Hi,

Is anyone able to point me in the right direction with regards to where I might start in order to change this sketch for use with a WiShield rather than an Ethernet Shield?

I'm very new to programming and it's all quite confusing, I'm trying to work through the basic tutorials for my aruduino but wanted to try and get a wireless thermometer up and running. I already have it working with the Ethernet shield.

Thanks for any help.

Cheers,
Ben

/**
 * OnlineThermometer
 *
 * Reads values from DS18B20 1-wire temperature sensors and displays
 * the current readings in a web page. This version is designed to work
 * with Ethernet shields based on the Wiznet W5100 chipset, including
 * the official Arduino Ethernet shield and also the Freetronics
 * Ethernet shield with PoE support:
 *     www.freetronics.com/ethernet-shield
 *
 * This sketch requires the "Webduino" library, available from:
 *     code.google.com/p/webduino
 *
 * Copyright 2009-2010 Jonathan Oxer <jon@oxer.com.au>
 *     www.practicalarduino.com/projects/online-thermometer
 *     www.freetronics.com/pages/online-thermometer
 */

#include <SPI.h>
#include <Ethernet.h>
#include <WebServer.h>

// No-cost stream operator as described at 
// http://sundial.org/arduino/?page_id=119
template<class T>
inline Print &operator <<(Print &obj, T arg)
{ obj.print(arg); return obj; }

// Modify the following lines to suit your local network configuration.
// The MAC and IP address have to be unique on your LAN:
static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEE, 0xEE, 0xEF };
static uint8_t ip[] = { 192, 168, 1, 2 };
static uint8_t myPort = 80; // Listen port for tcp/www (range 1-254)

/* This creates an instance of the webserver.  By specifying a prefix
 * of "/", all pages will be at the root of the server. */
#define PREFIX "/"
WebServer webserver( PREFIX, myPort );

// Specify data pins for connected DS18B20 temperature sensors
#define SENSOR_A  14
#define SENSOR_B  15
#define SENSOR_C  16
#define SENSOR_D  17
#define SENSOR_E  18
#define SENSOR_F  19

// Function prototypes to trick the Arduino pre-processor into
// allowing call-by-reference
void sendTemperatureValues( WebServer &server);
void sendAboutPage( WebServer &server);
void sendFormButtons( WebServer &server);

/**
 * Default page to return to browser
 */
void valuesCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.httpSuccess();
  sendTemperatureValues( server );
  sendFormButtons( server );
}

/**
 * Default page to return to browser
 */
void aboutCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.httpSuccess();
  sendAboutPage( server );
  sendFormButtons( server );
}

/**
 * Configure Ethernet shield
 */
void setup(){
  Serial.begin(38400);

  Ethernet.begin(mac, ip);
  webserver.begin();
  
  webserver.setDefaultCommand( &valuesCmd );
  webserver.addCommand( "values", &valuesCmd );
  webserver.addCommand( "about", &aboutCmd );

  // Set up the data pins for communication with DS18B20 sensors
  digitalWrite(SENSOR_A, LOW);
  pinMode(SENSOR_A, INPUT);
  digitalWrite(SENSOR_B, LOW);
  pinMode(SENSOR_B, INPUT);
  digitalWrite(SENSOR_C, LOW);
  pinMode(SENSOR_C, INPUT);
  digitalWrite(SENSOR_D, LOW);
  pinMode(SENSOR_D, INPUT);
  digitalWrite(SENSOR_E, LOW);
  pinMode(SENSOR_E, INPUT);
}

/**
 * Main program loop
 */
void loop(){
  webserver.processConnection();
}

/**
 * Send the HTML for the "about" page
 */
void sendAboutPage( WebServer &server )
{
  server.print("<h1>Online Thermometer v1.0 (Wiznet version)</h1>");
  server.print("As featured in Practical Arduino.
");
  server.print("See <a href=\"http://practicalarduino.com\">practicalarduino.com</a> for more info.");
}

/**
 * Send the HTML for the navigation buttons
 */
void sendFormButtons( WebServer &server )
{
  // Display a form button to update the display
  server << "<p><form METHOD='POST' action='" PREFIX "'>";
  server.println("<input type=submit value=\"Update\">");
  server.println("</form></p>");
}  
  // Display a form button to access the "about" page
/*
  server << "<p><form METHOD=POST action='" PREFIX "/about'>";
  server.println("<input type=submit value=\"About\">");
  server.println("</form>");
}
*/
/**
 * Get temperature values from connected sensors and generate the HTML
 */
void sendTemperatureValues( WebServer &server )
{
  char temp_string_a[10];
  char temp_string_b[10];
  char temp_string_c[10];
  char temp_string_d[10];
  char temp_string_e[10];
  char temp_string_f[10];
  
  getCurrentTemp(SENSOR_A, temp_string_a);
  getCurrentTemp(SENSOR_B, temp_string_b);
  getCurrentTemp(SENSOR_C, temp_string_c);
  getCurrentTemp(SENSOR_D, temp_string_d);
  getCurrentTemp(SENSOR_E, temp_string_e);
  getCurrentTemp(SENSOR_F, temp_string_f);
  
  server.print("Current Apartment Temperature: ");
  server.print(temp_string_a);
  server.print("
");
/* server.print("Sensor B:");
  server.print(temp_string_b);
  server.print("
");
  server.print("Sensor C:");
  server.print(temp_string_c);
  server.print("
");
  server.print("Sensor D:");
  server.print(temp_string_d);
  server.print("
");
  server.print("Sensor E:");
  server.print(temp_string_e);
  server.print("
");
  server.print("Sensor F:");
  server.print(temp_string_f);
  server.print("
");
*/
}

/**
 * Reset the 1-wire bus
 */
void OneWireReset (int Pin) // reset.  Should improve to act as a presence pulse
{
  digitalWrite (Pin, LOW);
  pinMode (Pin, OUTPUT);        // bring low for 500 us
  delayMicroseconds (500);
  pinMode (Pin, INPUT);
  delayMicroseconds (500);
}

/**
 * Send data to a 1-wire device
 */
void OneWireOutByte (int Pin, byte d) // output byte d (least sig bit first).
{
  byte n;

  for (n=8; n!=0; n--)
  {
    if ((d & 0x01) == 1)  // test least sig bit
    {
      digitalWrite (Pin, LOW);
      pinMode (Pin, OUTPUT);
      delayMicroseconds (5);
      pinMode (Pin, INPUT);
      delayMicroseconds (60);
    }
    else
    {
      digitalWrite (Pin, LOW);
      pinMode (Pin, OUTPUT);
      delayMicroseconds (60);
      pinMode (Pin, INPUT);
    }

    d = d>>1; // now the next bit is in the least sig bit position.
  }
}

/**
 * Read data from a 1-wire device
 */
byte OneWireInByte (int Pin) // read byte, least sig byte first
{
  byte d, n, b;

  for (n=0; n<8; n++)
  {
    digitalWrite (Pin, LOW);
    pinMode (Pin, OUTPUT);
    delayMicroseconds (5);
    pinMode (Pin, INPUT);
    delayMicroseconds (5);
    b = digitalRead (Pin);
    delayMicroseconds (50);
    d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
  }
  return (d);
}


/**
 * Read temperature from a DS18B20.
 * int sensorPin: Arduino digital I/O pin connected to sensor
 * char *temp: global array to be populated with current reading
 */
void getCurrentTemp (int sensorPin, char *temp)
{
  int HighByte, LowByte, TReading, Tc_100, sign, whole, fract;

  OneWireReset (sensorPin);
  OneWireOutByte (sensorPin, 0xcc);
  OneWireOutByte (sensorPin, 0x44); // Perform temperature conversion, strong pullup for one sec

  OneWireReset (sensorPin);
  OneWireOutByte (sensorPin, 0xcc);
  OneWireOutByte (sensorPin, 0xbe);

  LowByte = OneWireInByte (sensorPin);
  HighByte = OneWireInByte (sensorPin);
  TReading = (HighByte << 8) + LowByte;
  sign = TReading & 0x8000;  // test most sig bit
  if (sign) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's complement
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  whole = Tc_100 / 100;  // separate off the whole and fractional portions
  fract = Tc_100 % 100;

  if (sign) {
    temp[0] = '-';
  } else {
    temp[0] = '+';
  }

  if (whole/100 == 0) {
    temp[1] = ' ';
  } else {
    temp[1] = whole/100+'0';
  }

  temp[2] = (whole-(whole/100)*100)/10 +'0' ;
  temp[3] = whole-(whole/10)*10 +'0';
  temp[4] = '.';
  temp[5] = fract/10 +'0';
  temp[6] = fract-(fract/10)*10 +'0';
  temp[7] = '\0';
}

It's an unfortunate side-effect of the various driver implementations that code written for one particular networking shield (WiShield, Wiznet-based Ethernet Shield, or ENC28J60-based Ethernet Shield for example) has to be structured in totally different ways. There's some discussion on the Arduino Developers mailing list at the moment about possibly (in the distant future) having a generalised API so that any sketches that need network support could talk to the API, and not care about the hardware of the underlying network device. That's not here now though, so it doesn't solve your problem.

The best place to start would be to install the WiShield drivers using the instructions on the Async Labs wiki, and test out one or two example sketches to make sure you have the driver and shield working correctly.

http://asynclabs.com/wiki/index.php?title=AsyncLabsWiki

Test the "SimpleServer" example sketch and make sure you can access the demo page in your browser.

My suggestion is to then take the SimpleServer example as a starting point, and copy the DS18B20-related code from the OnlineThermometer sketch into it. That should get you pretty close, and you'll then need to modify the "sendMyPage" function to have it build the response page dynamically including the temperature sensor values. You should be able to lift most of that code from the OnlineThermometer sketch as well.

Jon
Freetronics TwentyTen (Arduino-compatible with built in prototyping area) TwentyTen (100% Arduino Compatible) | Freetronics

Hi Jon,

Thanks heaps for you reply, it was excellent. Exactly the kind of guidance I was after.

Whilst I'm no expert (more of a jack of all trades) the idea of a generalised API seems to make sense to me.

Keep up the great work.

Cheers,

Ben

Back again.

I've tried that SimpleServer example but just can't get the damn thing to compile. If anyone can help here is the same info I posted on Async Labs forum:

Banging my head against the wall (hard).

I can't get the SimpleServer to compile. I have modified the apps-conf.h file as instructed on the wiki but it just refuses to play and gives me the following errors:

SimpleServer.cpp.o: In function `loop':
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:74: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:74: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:74: undefined reference to `Server::server_task()'
SimpleServer.cpp.o: In function `setup':
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:64: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:64: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:64: undefined reference to `Server::init(unsigned char (*)(char*))'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:68: undefined reference to `Server::enableVerboseMode(unsigned char)'
SimpleServer.cpp.o: In function `sendMyPage(char*)':
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:50: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:50: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:51: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:51: undefined reference to `WiServer'
C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:52: undefined reference to `WiServer'
SimpleServer.cpp.o:C:\Users\BENTHO~1\AppData\Local\Temp\build8957222777927115908.tmp/SimpleServer.cpp:52: more undefined references to `WiServer' follow

I have not changed anything in the sketch, only added and removed '//' in the above file as instructed.

I'm using a the 1.3.0 version on github, the wiki says to use 1.0. Does this matter? I assumed the latest version would make sense as I didn't know how up to date the wiki is.

Having said that, I tried version 1.0, got an error regarding a missing g2100.h file, so I fetched it from the directory of the newer version. Compiled again and got a whole new set of errors:

WiShield\WiServer.cpp.o: In function `Server::server_task()':
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:654: undefined reference to `zg_drv_process'
WiShield\WiServer.cpp.o: In function `Server::init(unsigned char (*)(char*))':
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:85: undefined reference to `zg_init'
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:86: undefined reference to `zg_isr'
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:86: undefined reference to `zg_isr'
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:88: undefined reference to `zg_drv_process'
D:\Arduino\arduino-0022\libraries\WiShield/WiServer.cpp:87: undefined reference to `zg_get_conn_state'
WiShield\network.c.o: In function `network_send':
D:\Arduino\arduino-0022\libraries\WiShield/network.c:59: undefined reference to `zg_set_buf'
D:\Arduino\arduino-0022\libraries\WiShield/network.c:61: undefined reference to `zg_set_tx_status'
WiShield\network.c.o: In function `network_read':
D:\Arduino\arduino-0022\libraries\WiShield/network.c:48: undefined reference to `zg_get_rx_status'
WiShield\stack.c.o: In function `stack_init':
D:\Arduino\arduino-0022\libraries\WiShield/stack.c:59: undefined reference to `zg_get_mac'

I'm starting to regret my Wishield + Black Widow purchases, having a lot of trouble getting anything working apart from the example WebServer. Think I should just stick with Ethernet Shields but I'm not giving up just yet!

Thanks for your help.

I was going to modify my last post and remove everything saying I had solved my problem but I thought I'd leave it there in case someone else has the same problem as me.

I was editing the apps-conf.h file in notepad so there was no word wrap and the file had no format, structure or spaces in it. Turns out I was adding my '//' in the right place but it was putting them on the wrong line (at the end of the previous line instead of at the start of the line I wanted.

I only found this out when I decided to open the file in Wordpad, I'm now going to go and download Programmers Notepad and use that from now on.

Thanks.

Hi again,

So I've managed to copy the DS18B20-related code from the OnlineThermometer sketch into the SimpleServer sketch and it is compiling successfully. I have also got it working on my Black Widow and am able to get to the webpage it's serving.

The only thing I'm completely stuck on is how to modify the "sendMyPage" function to have it build the response page dynamically including the temperature sensor value (I only have one being 'a'). It looks like the way the online thermometer sketch is serving the page is different from the way the SimpleServer does it. My expertise doesn't extend that far I'm afraid, actually my expertise in this area doesn't really exist at all! :stuck_out_tongue:

I've got some code commented out in the sketch from the original one but I'm not sure what to do with it, it looks like it's what I need modified.

If anyone can help finish this of that would be great. Here's the sketch:
http://home.exetel.com.au/benthomas/files/wishield_therm_pde.rar

Cheers.

Edit: URL adjustment.