Crazy Homebrew SPI!?

I have designed a homebrew board using the ATmega 328p. The SPI does not work with the Ethernet portion of the Yourduino ethernet shield but DOES work with the SD slot portion... I know the ethernet works because I have tested the code with that shield and a store bought UNO. As soon as I connect the home brew, the web site being served does MIA.

I don't know what you guys will need for info so.....:

22 IDE windows 7 64bit FTDI programmer (Adafruit) I'm connecting to the shield thru the ISP header and not the 11-13 pins Reset is connected. Bootloader, fuses, blah blah from the board file

homebrew.name=Ardweenio (5V, 16 MHz) w/ ATmega328

homebrew.upload.protocol=stk500
homebrew.upload.maximum_size=30720
homebrew.upload.speed=57600

homebrew.bootloader.low_fuses=0xff
homebrew.bootloader.high_fuses=0xda
homebrew.bootloader.extended_fuses=0x06
homebrew.bootloader.path=atmega
homebrew.bootloader.file=ATmegaBOOT_168_atmega328.hex
homebrew.bootloader.unlock_bits=0x3F
homebrew.bootloader.lock_bits=0x0F

homebrew.build.mcu=atmega328p
homebrew.build.f_cpu=16000000L
homebrew.build.core=arduino

I led blink tested every pin to make sure they all operated correctly I ran the SD card info code successfully (which to me is mind blowing seeing as they are on the same communication pins!) Again the shield is the Yourduino Ethernet Shield.

I'm am totally defeated on this one... and really pissed. Any insight would be great.

Thanks.

How are you asserting slave select (SS) on the Ethernet Shield?

Board and sch for reference

Sch removed because it was impossible to read…

Ethernet code…

#include <SPI.h> // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <TextFinder.h>
#include <avr/pgmspace.h> // for progmem
#define P(name) static const prog_uchar name[] PROGMEM // declare a static string
byte mac[] = { 0xC4, 0xA2, 0xDA, 0x00, 0xE3, 0xA2 };
byte ip[] = { 192, 168, 1, xxx };
byte gateway[] = { 192, 168, 1, 1 };
char buffer[8]; // buffer holding the requested page name
Server server(8080);
int relayPin = 2;
int switchPin = 3;
int ledPin = 4;

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
delay(3000);
Serial.println("Ready");
pinMode(relayPin, OUTPUT);
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(relayPin, HIGH);
digitalWrite(switchPin, HIGH);
digitalWrite(ledPin, HIGH);
}

void loop(){
Client client = server.available();
if (client) {
TextFinder finder(client );
int type = 0;
while (client.connected()) {
if (client.available()) {
// GET, POST, or HEAD
if(finder.getString("","/", buffer,sizeof(buffer))){
if(strcmp(buffer,"POST ") == 0){
finder.find("\n\r"); // skip to the body
// find string starting with "pin", stop on first blank line
// the POST parameters expected in the form pinDx=Y
// where x is the pin number and Y is 0 for LOW and 1 for HIGH


while(finder.findUntil("pinD", "\n\r")){
relayPin = finder.getValue(); // the pin number
int val = finder.getValue(); // 0 or 1
digitalWrite(relayPin, val);
delay(3000);
digitalWrite(relayPin, HIGH);
}
}


sendHeader(client,"Votto Vines Warehouse");
//create HTML button to control pin 9
client.println("<h2>Open Garage Door</h2>");
client.print("<form action='/' method='POST'><p><input type='hidden'name='pinD2'");
client.println(" value='0'><input type='submit' value='Off'/></form>");
//create HTML button to turn on pin 9
client.print("<form action='/' method='POST'><p><input type='hidden'name='pinD2'");
client.print(" value='1'><input type='submit' value='Operate Door'/></form>");

client.print("Door is ");
//client.print(i);
//client.print(" is ");
if(digitalRead(switchPin) == LOW){ //not the right pin!
client.print("OPEN!");
digitalWrite(ledPin, LOW);
}
else{
client.print("CLOSED");
digitalWrite(ledPin, HIGH);
}
client.println("
");

client.println("</body></html>");
client.stop();
}
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}

//----------------------------------------------------------------

void sendHeader(Client client, char *title){
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print(title);
client.println("</title><body>");
}

[quote author=Coding Badly link=topic=116610.msg877609#msg877609 date=1343701366]

How are you asserting slave select (SS) on the Ethernet Shield?

[/quote]

Frankly... I just realized that I'm not.

So how the hell does the Uno run the code sucessfully!?

edit FYI, I'm not running the SD and WIZnet at the same time, Perhaps thats why I got confused by your question.

Board and sch for reference

Does the Ethernet Shield plug directly into your board?

[quote author=Coding Badly link=topic=116610.msg877692#msg877692 date=1343709294]

Board and sch for reference

Does the Ethernet Shield plug directly into your board?

[/quote]

No sir. Everything is connected by jumper wires. MISO, MOSI, SCK all connect at the ICSP header from the MCU pins 11-13, SS from pin 10 on the MCU to pin 10 on the shield, Vcc, Gnd and Rst are pin to pin from the MCU to the shield.

Two things:

From my experience, it's a good idea to have a 10k pull-up resistor on each of the CS lines. That way, SD cards and other stuff on the SPI bus do not accidentally interfere with the ISP while it's trying to program.

Individual CS lines are obviously a must. My guess re: why one SPI device works while the other one does not probably has to do with the device that works intentionally or unintentionally pulling down the CS pin. Another possibility is that a library is automagically doing the work for you - many .h files define CS pins in them. I'd use a voltmeter to assess either possibility.

Obviously, when your time comes to implement CS pins, remember to define each CS line as an output and that it's HIGH unless your code calls to select a device at which point the appropriate CS pin has to go LOW.

Best of luck!

Constantin: Two things:

From my experience, it's a good idea to have a 10k pull-up resistor on each of the CS lines. That way, SD cards and other stuff on the SPI bus do not accidentally interfere with the ISP while it's trying to program.

Individual CS lines are obviously a must. My guess re: why one SPI device works while the other one does not probably has to do with the device that works intentionally or unintentionally pulling down the CS pin. Another possibility is that a library is automagically doing the work for you - many .h files define CS pins in them. I'd use a voltmeter to assess either possibility.

Obviously, when your time comes to implement CS pins, remember to define each CS line as an output and that it's HIGH unless your code calls to select a device at which point the appropriate CS pin has to go LOW.

Best of luck!

I guess I'm a bit confused on why I would have to go through the trouble of adding pull-ups on the CS line if there is only one SPI device connected?

I assume that the ethernet lib calls out for the pin 10 to be the CS, because I don't think I have ever seen a code where only the ethernet was running and pin 10 was explicitly called LOW in the code.

What is troubling me is that nothing changes (code, wiring, shield, ip, ports, etc.) from the working UNO to the homebrew. I was only was the SD slot to provide confirmation that the SPI communication was working, which it does on the homebrew. Knowing that the SPI is working on the homebrew board, when I wire it so that ONLY the ethernet shield is connected, the communication fails.

If I take that exact same wiring and code, transfer it to a UNO, everything works.

RobDrizzle: No sir.

No need for that.

Frankly... I just realized that I'm not. ... Everything is connected by jumper wires. MISO, MOSI, SCK all connect at the ICSP header from the MCU pins 11-13, SS from pin 10 on the MCU to pin 10 on the shield, Vcc, Gnd and Rst are pin to pin from the MCU to the shield.

You are. Slave Select is provided by pin 10 (by default).

Were I in your shoes I would: Build a short simple sketch using the SPI library that queries the Ethernet Shield for something simple like status. Use the slowest possible SPI bitrate. Have the sketch query once a second and output the results. Use an oscilloscope to determine what is happening with the hardware.

I don't have an oscilloscope so: Use LEDs on the four lines to determine if there is any activity and to ensure SS is high when the sketch is idle.

I guess I'm a bit confused on why I would have to go through the trouble of adding pull-ups on the CS line if there is only one SPI device connected?

Every device typically needs an individual CS line on the SPI bus. The only exception I can think of are some multiplexing devices, IIRC. I found having said resistors are very useful when programming the MCU via the ISP, i.e. a SD card would not interfere with the MOSI/MISO signals because it thought it was being addressed because the CS pin output on the Atmel may or may not have been in the right place for the SD card not to respond. So in past instances, my home-made board required me to remove the SD card before programming via ISP (bootloader, for example).

As for the question of whether pin 10 is being pulled low or not, check the .cpp file and the .h file. The answer is usually there. I would prefer libraries in general to allow the user to set the CS pin on SPI devices but libraries are usually written for specific shields and this is one way for people to reduce the complexity of the shield purchasers to get their shield going - at the expense of those who'd like to use the library, just not with the specific shield or the specific configuration.

Maybe someone can figure it out? I mean, I see some obvious differences... But I have to double check the voltage on the homebrew MISO. Looks low to me.

both voltages check out... The second time observing the uno MISO, I get 36kHz with really obvious spikes. I kinda wonder if the sample rate of my scope is too slow.

I wonder why the homebrew SCK is running at half speed? That should be constant for all devices right?

Just burned and programmed another atmega328 just to make sure it wasn't the MCU itself... nothing, same story.

RobDrizzle: I wonder why the homebrew SCK is running at half speed? That should be constant for all devices right?

If the processors are clocked the same and running the same code then SCK will be the same. Are you using a bootloader on the homebrew board?

[quote author=Coding Badly link=topic=116610.msg878756#msg878756 date=1343786590]

RobDrizzle: I wonder why the homebrew SCK is running at half speed? That should be constant for all devices right?

If the processors are clocked the same and running the same code then SCK will be the same. Are you using a bootloader on the homebrew board?

[/quote]

ATmegaBOOT_168_atmega328.hex

The board.txt file is posted above if you want any of the fuse info too.

How did you burn the bootloader? Through the IDE?

Try different cables between the homebrew and Ethernet shield.

So I guess I'll report in that the problem appears to be in the pcb itself. I used a chip burning board I made and tried the atmega in that, It worked fine. I changed out the crystal in the homebrew, nothing. I soldered leads directly to the atmega on the homebrew, nothing. Tomorrow, I'm going to check all the traces for shorts. But for now, looks like the pcb is a dud. :(

ok seems that there is a short from SCK to ground... somewhere. I check the rest of the boards in the batch and they all check out ok. I don't know where the short is and don't really care at the moment. I just will check for this on the next one to make sure that it's not something getting mistakenly soldered.

Thanks for the help guys.