I'm trying to change the SS pin from 10 to 8 with the Ethernet shield. As a test I have a Duemilanove and an Ethernet shield ver 01. I don't have them stacked, instead I have jumper wires connecting the following pins.
11, 12, 13, Reset, Gnd, 5V.
I have w5100.h file in the same directory as my .ino sketch file. In the w5100.h I commented out the lines that make pin 10 the SS pin and changed it so it should be pin 8. But this doesn't seem to do anything. If I have pin 10 on the Arduino connected to pin 10 on the Ethernet shield, it works. But it shouldn't. If I change it so pin 8 on the Arduino is connected to pin 10 on the Ethernet shield it doesn't work. But that's the configuration that I want to work.
Here is the modification to w5100.h
private:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
inline static void initSS() { DDRB |= _BV(4); };
inline static void setSS() { PORTB &= ~_BV(4); };
inline static void resetSS() { PORTB |= _BV(4); };
#elif defined(__AVR_ATmega32U4__)
inline static void initSS() { DDRB |= _BV(6); };
inline static void setSS() { PORTB &= ~_BV(6); };
inline static void resetSS() { PORTB |= _BV(6); };
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
inline static void initSS() { DDRB |= _BV(0); };
inline static void setSS() { PORTB &= ~_BV(0); };
inline static void resetSS() { PORTB |= _BV(0); };
#else
// inline static void initSS() { DDRB |= _BV(2); }; // SS Pin 10
// inline static void setSS() { PORTB &= ~_BV(2); };
// inline static void resetSS() { PORTB |= _BV(2); };
inline static void initSS() { DDRB |= _BV(0); }; // SS Pin 8
inline static void setSS() { PORTB &= ~_BV(0); };
inline static void resetSS() { PORTB |= _BV(0); };
#endif
Here is my sketch
#include <SPI.h>
#include "Ethernet.h"
#include "w5100.h"
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x18, 0x45 }; // MAC address from Ethernet shield sticker under board
IPAddress ip(192,168,216,48);
EthernetServer server(80); // create a server at port 80
String HTTP_req; // stores the HTTP request
void setup()
{
pinMode(10, OUTPUT);
pinMode(8, OUTPUT);
digitalWrite(10, HIGH);
digitalWrite(8, HIGH);
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
Serial.begin(9600); // for diagnostics
pinMode(7, INPUT_PULLUP ); // switch is attached to Arduino pin 7
Serial.println("Setup()");
} // setup()
void loop()
{
EthernetClient client = server.available(); // try to get client
if (client)
{ // got client?
boolean currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{ // client data available to read
char c = client.read(); // read 1 byte (character) from client
HTTP_req += c; // save the HTTP request 1 char at a time
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank)
{
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();
// AJAX request for switch state
if (HTTP_req.indexOf("ajax_switch") > -1)
{
// read switch state and analog input
GetAjaxData(client);
}
else // HTTP request for web page
{
// send web page - contains JavaScript with AJAX calls
client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<title>Arduino Web Page</title>");
client.println("<script>");
client.println("function GetSwitchAnalogData() {");
client.println("nocache = \"&nocache=\" + Math.random() * 1000000;");
client.println("var request = new XMLHttpRequest();");
client.println("request.onreadystatechange = function() {");
client.println("if (this.readyState == 4) {");
client.println("if (this.status == 200) {");
client.println("if (this.responseText != null) {");
client.println("document.getElementById(\"sw_an_data\").innerHTML = this.responseText;");
client.println("}}}}");
client.println("request.open(\"GET\", \"ajax_switch\" + nocache, true);");
client.println("request.send(null);");
client.println("setTimeout('GetSwitchAnalogData()', 1000);");
client.println("}");
client.println("</script>");
client.println("</head>");
client.println("<body onload=\"GetSwitchAnalogData()\">");
client.println("<h1>Arduino AJAX Input</h1>");
client.println("<div id=\"sw_an_data\">");
client.println("</div>");
client.println("</body>");
client.println("</html>");
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
break;
} // end if currentLineIsBlank
// every line of text received from the client ends with \r\n
if (c == '\n')
{
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r')
{
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
// send the state of the switch to the web browser
void GetAjaxData(EthernetClient cl)
{
int analog_val;
if (digitalRead(7)) {
cl.println("<p>Switch 7 state: ON</p>");
}
else {
cl.println("<p>Switch 7 state: OFF</p>");
}
if (digitalRead(6)) {
cl.println("<p>Switch 6 state: ON</p>");
}
else {
cl.println("<p>Switch 6 state: OFF</p>");
}
// read analog pin A2
analog_val = analogRead(2);
cl.print("<p>Analog A2: ");
cl.print(analog_val);
cl.println("</p>");
// Print seconds on
cl.print("<p>On Time: ");
cl.print(millis()/1000);
cl.println(" seconds</p>");
}
Does your ethernet shield have a 6 pin (2x3) connector centered on the bottom of the circuit board? If so, those are the SPI data lines. The new shields that have that connector do not have any w5100 SPI lines connected to D11 to D13. They connect to the ICSP pins only.
SurferTim:
Does your ethernet shield have a 6 pin (2x3) connector centered on the bottom of the circuit board?
No it doesn't have the2x3 connector. I'm using an old rev 01 shield. MISO, MOSI and CLK pins are not the problem since my setup does work when using pin 10 as SS. Put I want to use Pin 8 (or any pin between from 2-8) as SS.
I used this in w5100.h. I commented out all the old code and used digitalWrite() instead. Worked great on my Mega. Give it a try.
private:
// Tim added
inline static void initSS() { digitalWrite(8, HIGH); };
inline static void setSS() { digitalWrite(8, LOW); };
inline static void resetSS() { digitalWrite(8, HIGH); };
// end of add
// Tim removed
/*
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
inline static void initSS() { DDRB |= _BV(4); };
inline static void setSS() { PORTB &= ~_BV(4); };
inline static void resetSS() { PORTB |= _BV(4); };
#elif defined(__AVR_ATmega32U4__)
inline static void initSS() { DDRB |= _BV(6); };
inline static void setSS() { PORTB &= ~_BV(6); };
inline static void resetSS() { PORTB |= _BV(6); };
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
inline static void initSS() { DDRB |= _BV(0); };
inline static void setSS() { PORTB &= ~_BV(0); };
inline static void resetSS() { PORTB |= _BV(0); };
#else
inline static void initSS() { DDRB |= _BV(2); };
inline static void setSS() { PORTB &= ~_BV(2); };
inline static void resetSS() { PORTB |= _BV(2); };
#endif
*/
// end of remove
I have since modified that to select the slave select through an Ethernet library call so I can access two ethernet shields in the same sketch code.
SurferTim:
I used this in w5100.h. I commented out all the old code and used digitalWrite() instead. Worked great on my Mega. Give it a try.
I tried digitalWrite() but it didn't work for me. If I used pin 10 with digitalWrite() it would work. When i changed to pin 8 it didn't work. I also tried pin 9 and 7, they didn't work either. When I change the pin number, I moved the wire on the Arduino to that pin. So when I tried digitalWrite with pin 8, the jumper was connected from Arduino pin 8 to Ethernet shield pin 10,
BTW - I'm using Arduino IDE ver 1.05 on a Mac. My Arduino is a Duemilanove with Adafrut's adaboot boot loader.
SurferTim:
I have since modified that to select the slave select through an Ethernet library call so I can access two ethernet shields in the same sketch code.
Would you mind sharing your modified libraries?
ScottG:
Would you mind sharing your modified libraries?
OK. They are attached. These are from IDE v1.0.5, but should also work with IDE v1.5.x also. I tested it with v1.5.5.
To select the slave select, use
Ethernet.select(10);
Bear in mind if you are also using the SD card, you must disable the w5100 slave select also.
No guarantees, but if you have a problem, let me know.
edit: Use code in reply #21.
Thanks! I'll let you know how it works out. I'm not using the SD card.
It isn't working. It has problems with dhcp. I'm working on it now.
edit: I found the problem. I'm testing it now. If it works ok in the morning, I'll post the new code.
OK. It works now. The new files are attached. I tried most of the sketches I have and all are running ok.
It should be compatible with older sketches now. If you do not call Ethernet.select(), it uses D10 by default.
Here is the DhcpAddressPrinter sketch from the ethernet library examples modified for D9 as the w5100 slave select. I bent D10 on the shield so it wouldn't insert into my Mega, then jumpered D10 and D9 on the shield.
/*
DHCP-based IP printer
This sketch uses the DHCP extensions to the Ethernet library
to get an IP address via DHCP and print the address obtained.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 12 April 2011
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
int freeRam() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
}
void setup() {
// start the serial library:
Serial.begin(115200);
pinMode(4,OUTPUT);
digitalWrite(4,HIGH);
Serial.print(F("SRAM left: "));
Serial.println(freeRam());
// start the Ethernet connection:
Ethernet.select(9);
Serial.println("Starting ethernet");
while (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
delay(5000);
Serial.print(F("SRAM left: "));
Serial.println(freeRam());
Serial.println("trying DHCP again");
}
// print your local IP address:
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
}
void loop() {
byte updateVal = Ethernet.maintain();
if(updateVal) {
Serial.print(F("DHCP maintain..."));
switch(updateVal) {
case 0: Serial.println(F("no action"));
break;
case 1: Serial.println(F("renew failed"));
break;
case 2: Serial.println(F("renew success"));
break;
case 3: Serial.println(F("rebind failed"));
break;
case 4: Serial.println(F("rebind success"));
break;
default: Serial.println(F("unknown"));
}
}
delay(1000);
}
edit: Use the files in reply #21.
SurferTim,
I'm trying your modified files, but I'm having some trouble getting it to compile. I put the 4 files (Ethernet.h/cpp, w5100.h/cpp) in the same directory as my INO file; so in the Arduino IDE (1.05 on Mac) they show up as tabs. When I use the sketch you posted, I get this error:
error: 'class EthernetClass' has no member named 'select'
I'm including the library with <> like this:
#include <Ethernet.h>
So I assume the sketch us using the built-in Ethernet.h library and not the modified one in my INO directory . So I changed the syntax to:
#include "Ethernet.h"
So now I think it's using your version that's in my sketch directory, but I'm getting tons of multiple definition errors.
I'd prefer to leave the original Ethernet.h and w5100.h files alone. What's the right way to do this?
If you do not want to replace the files in the ethernet library with my files, then you are dead in the water.
I recommend renaming your original w5100 and Ethernet files before replacing them. That is what I did.
I renamed:
w5100.h to w5100.h.orig
w5100.cpp to w5100.cpp.orig
Ethernet.h to Ethernet.h.orig
Ethernet.cpp to Ethernet.cpp.orig
Then I moved my files into those directories. If all goes bad, remove my files and rename those .orig files back to the original filenames.
SurferTim:
If you do not want to replace the files in the ethernet library with my files, then you are dead in the water.
I recommend renaming your original w5100 and Ethernet files before replacing them. That is what I did.
I renamed:
w5100.h to w5100.h.orig
w5100.cpp to w5100.cpp.orig
Ethernet.h to Ethernet.h.orig
Ethernet.cpp to Ethernet.cpp.orig
Then I moved my files into those directories. If all goes bad, remove my files and rename those .orig files back to the original filenames.
Okay, I'll try it that way. I was hoping to avoid doing that because I use several computers to program my Arduinos. So I have to change it everywhere. Also, when I upgrade the IDE, I have to remember to change the files again. How come the header guards don't solve the multiple definition problem?
#ifndef ethernet_h
#define ethernet_h
I don't know about the multiple definition part. I think it is the difference between the way sketches are compiled into the code versus the libraries.
But on the "several computers" part, I can sympathize with you. I even have computers with multiple IDE versions that I must change the files on each version. It is a pain in the backside, but if you want the movable slave select pin, it is part of it.
Surfer Tim,
Using you modified library for slave select, I can't create an Ethernet connection using the static IP method, like this:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,216,40);
Ethernet.begin(mac, ip);
It works fine if I use DHCP method:
Ethernet.begin(mac);
The static method does work if my slave select pin is 10, but if it's something else, the sketch doesn't set the IP address. Instead of the IP I'm trying to set, I get 255,255,255,255
A big advantage to static IP is it uses a lot less memory, so I'd like to get this working. Any ideas on how to fix it?
Are you bending the D10 pin on the ethernet shield so it doesn't insert into the Arduino?
Are you jumpering the D10 pin on the shield to the new slave select?
Are you calling Ethernet.select() before Ethernet.begin() to select the new slave select? I just changed mine to D8 and this worked.
Ethernet.select(8);
The Ethernet shield is not stacked on the Arduino, I'm using jumpers for everything. I connecting D9 on the Arduino to D10 on the Ethernet shield. I'm also trying it with a WIZ811 module and for that I have a PCB I made. On that sketch I think I'm using D7 on the Arduino going to WIZ811 SS pin.
I've got the Ethernet.Select(9) statement before Ethernet.begin().
Everything works fine if I connect with DHCP, so I don't think I've got anything wired wrong or it wouldn't work at all.
I just tried a static IP and dhcp. Both worked.
Hmm. I guess I'll have to do some more tinkering. Which model Arduino are you using?
I'm using a Mega 2560, but that shouldn't make a difference if the DHCP sketch is working for you.