Ethernet stops working after SPI access

Hi Everyone,

I am using the Arduino Ethernet Board with an Arduino Proto Shield with the Arduino 1.0.1 software. I am having a problem where the ethernet works fine until I try to access another SPI device, but stops working after I call SPI.transfer(). In my code, I can simply comment out the SPI.transfer() lines and ethernet will work fine, but I comment them back in and ethernet stops behaving.

In my hardware configuration, I am using the default ETHCS to select the W5100 chip and I have configured A1, A2, and A3 to select my other SPI devices (A2D converters).

Has anyone seen this problem?

Thanks for you help, Chris

Has anyone seen this problem?

If "this problem" is the lack of code, then, yes, we see it all the time. If it is something else (as I suspect it is), we need to see the code to see why it might be happening.

If "this problem" is the lack of code, then, yes, we see it all the time. If it is something else (as I suspect it is), we need to see the code to see why it might be happening.

Sorry, I should have included code, but didn't think I could provide something meaningful. However, I did find my problem. I had code that ran as a side effect of getting data from the SPI, which had a negative array index. This was causing data to be improperly written into the EthernetServer instance.

Sorry for the wasted bandwidth.

Hi... I have the same issue in my proyect...could you share your code here??. I just want to know how work with the ethernetboard and other spi device without error..

eddy_grosse8: Hi... I have the same issue in my proyect...could you share your code here??. I just want to know how work with the ethernetboard and other spi device without error..

What other SPI device? The w5100 and SD work ok together if initialized correctly.

edit: The basic theory is each device library controls the Slave Select pin for that device, and the objective is to keep that device SPI disabled (slave select pin HIGH) unless you are reading/writing to that device.

Thank you for your fast post…

My Proyect:
I want to control the stepper motor driver L6470 that communicates via SPI with a Arduino Ethernetboard . thats mean 2 spi devices…

The current status is:
-Motor works preatty fine
-Comunication with Arduino and My software user interface via Ethernet also ok…

but .
My issue:

If I understand correctly … I have to disable the wiz5100 (Ethernet chip) in order to achieve comunicaction with the l6470 Stepper Driver…

I can disable the chip wiz5100 (Pin10, HIGH) via software… but I don´t understand how to reactivate the communication between my software and Arduino and then control my motor
It sounds preatty easy but it does not…(for me)

I spent many hours on this. if anyone has an idea I’ll be very grateful …

Thanks

I don't know what digital pin you are using for the slave select for the motor driver, but let's presume digital pin 8, and the SPI mode and bit order settings are the same for both devices. When you want to communicate with the motor driver, use something like this:

  // enable motor driver SPI
  digitalWrite(8,LOW);
  // read/write to motor driver
  spiRead = SPI.transfer(spiWrite);
  // disable motor driver SPI
  digitalWrite(8,HIGH);

You do not need to manipulate the w5100 SS pin after the setup routine. After you call Ethernet begin(), set digital pin 10 HIGH to disable its SPI.

  digitalWrite(10,HIGH);

After that, the w5100 uses the same procedure when it transfers data.

Thank you very very much.. I supossed somthing like that... i will try your idea..

otherwise..do you think is posible to read the stall register from the l6470 via Ethernet/udp in live time..?? It looks very hard?.. :astonished: maybe I need to buy a encoder..

If you plan on using the driver library on this site, it will take some code modification. The motor driver wants to use digital pin 10 for its SS, but the w5100 already uses it. https://www.sparkfun.com/products/10859

Here is the low level read/write for your device. It handles its SS pin well also.

byte dSPIN_Xfer(byte data)
{
  byte data_out;
  // enable motor SPI
  digitalWrite(SLAVE_SELECT_PIN,LOW);
  // SPI.transfer() both shifts a byte out on the MOSI pin AND receives a
  //  byte in on the MISO pin.
  data_out = SPI.transfer(data);
  // disable motor SPI
  digitalWrite(SLAVE_SELECT_PIN,HIGH);
  return data_out;
}

I added a couple comments for you.

Ok…
actually im using other _SSPin (7) I change it in the library also…

Im Testing the work from Adam Meyer GitHub - ameyer/Arduino-L6470: L6470 Stepper Motor Driver library for Arduino … he wrote a Arduino´s Library with the sparkfun´s Code… Im just want to extend this code for my proyect. Ehternet /OSC /and Position Tracking In I think It could be a very good example for the arduino comunity

Im understanding (slowly) more about the whole comunication process…
My question is… With the following code I can send just 1 position message with vvvv but just I Time an then I need to load the code one more time… =(javascript:void(0);

I think I need to make a function which switch between the 2 Chips… but
the" how and when "should I call these function is my problem/doubt
I post my code here.

//=====================================================================================================
/*Receive Values from vvvv to control Arduino pins and Step Motor Driver L470 using the Ethernet shield
Status:
The programa can just send only one position value to L6470 but first is necesary put the pin 10 in HIGH
issue:
How to restore the comunication between Arduino and wiz5100?

To do:
Chip select Function/routine to handel the comunication between arduino and wiz5100 and l6470
*/
//================================================================================================================================================================

#include <SPI.h>
#include <Ethernet.h>
#include <Z_OSC.h>
#include <L6470.h>
L6470 stepper(7);

//==============================================================================================================================================================

byte myMac = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // A Media Access Control address (MAC address)
byte myIp = { Ethernet IP,}; // Ethenet Shield IP Adresse// Marked as Remote Host in vvvv
int serverPort = 4441; // Marked as Remote Port in vvvv Patch
byte destIp = { Computer Adress }; // Your Computer IP Adress
int destPort = 4442; // Destination Port

char oscAdr = “/z-osc/di”; // Adress for sending the values (Speed,Pos,Etc/ from the L6470 ) to vvvv

//=============================================================================================================================================================

boolean test; //Test comunication with Arduino´s Pin 7 and vvvv
//===============================================================================================================================================================
//Motor control variables//
long int pos = 0; // Variable to set the Position
long int mode =0;
//================================================================================================================================================================
//OSC//
Z_OSCServer server;
Z_OSCClient client;
Z_OSCMessage *rcvMes;
//================================================================================================================================================================
void setup(){
//Set pins as Outputs
pinMode(5,OUTPUT); // Test Pin
//===========================================================================================================================================================
Serial.begin(9600);
Ethernet.begin(myMac ,myIp);
server.sockOpen(serverPort);
}
//============================================================================================================================================================
void loop()
{
ComunicationProcedure ();
MotorProcedure();
PrintValues();
}

void ComunicationProcedure ()

{
if(server.available()){ //Gets a client that is connected to the server and has data available for reading.
rcvMes=server.getMessage();

//Position values from vvvv to Arduino
if( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ) )
{
pos = rcvMes->getInteger32(0); //Get value from vvvv

}

// Get the operation mode from L6470//goTo()//move()
if( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ) )
{
mode = rcvMes->getInteger32(1);// Get the operation mode from L6470//goTo()//move()

}

//test Turning on/off Arduino Pin 5_

if ( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ))
{
test = rcvMes->getInteger32(2); //Get the value from vvvv
test = constrain(test, 0, 1); // limit the value to 0-1
if ( test == 1 )
{
digitalWrite(5,HIGH);
}
else {
digitalWrite(5,LOW);
}
}
}

}
void MotorProcedure()

{

int Type = mode;
switch (Type) {

case 1:
delay(10);
stepper.init();
//stepper.isBusy();
stepper.setAcc(5); //set acceleration
stepper.setDec(1); //set decelaration
stepper.setMicroSteps(2); // Step Mode :1,2,4,8,16,32,64 or 128
stepper.setOverCurrent(3000); //set overcurrent protection
stepper.setStallCurrent(3000);
stepper.goTo(pos);

break;

case 2: //
delay(10);
stepper.init();
//stepper.isBusy();
stepper.setAcc(5); //set acceleration
stepper.setDec(1);
stepper.setMicroSteps(2); //1,2,4,8,16,32,64 or 128
stepper.setOverCurrent(3000); //set overcurrent protection
stepper.setStallCurrent(3000);
stepper.move(FWD,pos);

break;

case 3:

pinMode(10,OUTPUT); // set the SS pin as an output
digitalWrite(10, HIGH); // set the SS pin in HIGH to set the comunication with L6470
delay(10);
break;

}
}
void PrintValues ()
{
long newposition;
newposition=stepper.getPos();
Z_OSCMessage mes;
mes.setAddress(destIp,destPort);
mes.setZ_OSCMessage(oscAdr,“i” ,&newposition);
client.send(&mes);
}

void setup(){
 Serial.begin(9600);                   

 // disable 6470 SPI while initializing w5100
 pinMode(7,OUTPUT);
 digitalWrite(7,HIGH);

 // this begin function returns with the w5100 SPI enabled...
 Ethernet.begin(myMac ,myIp); 
 // ...so disable it
 digitalWrite(10,HIGH);

 server.sockOpen(serverPort); 
}

Now if the SPI mode is the same (I haven't checked that) you should be able to transfer to both without changing pin 7 or 10.

Hi ... Thanks for yor help.. Your idea works... now I don´t need to put the pin 10_on HIGH.. via Software.. that is a big step for me....

but ...

when the motor starts to work the comunication with the wiz5100 goes dont´come back..

void MotorProcedure()

{

int Type = mode; switch (Type) {

case 1: delay(10); stepper.init(); stepper.isBusy(); stepper.setAcc(5); //set acceleration stepper.setDec(1); //set decelaration stepper.setMicroSteps(2); // Step Mode :1,2,4,8,16,32,64 or 128 stepper.setOverCurrent(3000); //set overcurrent protection stepper.setStallCurrent(3000); stepper.goTo(pos); if(stepper.getPos()==pos);// Test if the position achieved delay(10); digitalWrite(7,LOW); break;

}

//Thank yor for yor post

if(stepper.getPos()==pos);// Test if the position achieved

If it is, do nothing. If it isn't, do nothing.

Why bother?

 int Type = mode;
 switch (Type) {

As opposed to switching on mode?

Much of what you are doing in case 1, with the stepper setup, belongs in setup(), not in a function called from loop(). Why would you need to set the stall current level to different values throughout the program?

Hey thank you still here .. Sorry if I made some fatal errors I'm not a really programmer ..

1 .. I wrote the L6470 set up Functions in each case (3 cases in the full program) because I figured /supossed l6470 would not conflict with wiznet. This means the chip would be activated until the case 1 is selected via software .. (I'm not sure that's 100% correct) .

2. The loop:

if (stepper.getPos () == pos); digitalWrite (7, LOW);

My Idea is:

The if loop compares the "L6470 POS register" with variable (pos) which comes from vvv if it is: pin 7 goes to LOW and reactive communication with wiznet5100

anyway this if loop dont works because the wiz5100 dont come back..

Thank you very very much for your help

if (stepper.getPos () == pos);
   digitalWrite (7, LOW);

This block of code does NOT set pin 7 LOW if the stepper gets to the desired position. The body of the if statement is the (incorrectly placed) semicolon at the end - a no-operation.

Then, pin 7 is unconditionally set LOW.

enorm error..(The semicolon) Thanks..

Hi everybody…

I just do not understand what could be the error … my program only sent once a value of position and then communication with Arduino fells

I have a Serial Version which works preatty good…I know that the motor functions are not the problem…

I will be very grateful for the help

my code:

#include <SPI.h>
#include <Ethernet.h>
#include <Z_OSC.h>
#include <L6470.h>
L6470 stepper(7);

//==============================================================================================================================================================

byte myMac = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // A Media Access Control address (MAC address)
byte myIp = { MY ARDUINO IP}; // Ethenet Shield IP Adresse// Marked as Remote Host in vvvv
int serverPort = 4441; // Marked as Remote Port in vvvv Patch
byte destIp = { IP }; // My Computer IP Adress
int destPort = 4442; // Destination Port

const int L6470SC = 7;
const int ETHERNETSC = 10;

//=============================================================================================================================================================
//Arduino digital Pins Variable//
boolean test; //Sleep Mode Arduino Pin 7
//===============================================================================================================================================================
//Motor control variables//
long int pos = 0; // Variable to set the Position
long int mode =0; // Variable to set the Motion Mode
//================================================================================================================================================================
//OSC Comunication variables//
Z_OSCServer server;
Z_OSCMessage *rcvMes;
//================================================================================================================================================================
void setup(){
pinMode(5,OUTPUT); // Test Pin as Output
Serial.begin(9600);
Ethernet.begin(myMac ,myIp);
server.sockOpen(serverPort);
//digitalWrite(10,HIGH); //
//========================================================================================
//MOTOR Set up
stepper.setMaxSpeed(600);
stepper.setMinSpeed(0);
stepper.setAcc(100); //set acceleration
stepper.setDec(100); //set decc
stepper.setMicroSteps(8); //1,2,4,8,16,32,64 or 128
stepper.setOverCurrent(3000); //set overcurrent protection
stepper.setStallCurrent(3000);

}

//============================================================================================================================================================

void loop()
{

ComunicationProcedure ();

}

void ComunicationProcedure ()
{

if(server.available()){ //Gets a client that is connected to the server and has data available for reading.
rcvMes=server.getMessage();

//pos
if( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ) ) //compares the adress
{
pos = rcvMes->getInteger32(0); //Get value from vvvv

if(pos > 0) //
MotorProcedure();

}

// mode
if( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ) )
{
mode = rcvMes->getInteger32(1); //Get value from vvvv

}

//test_Pin: if you can blink a Pin with “vvvv Bang button” you have comunication

if ( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ))
{
test = rcvMes->getInteger32(2); //Get the value from vvvv
test = constrain(test, 0, 1); // limit the value to 0-1
if ( test == 1 )
{
digitalWrite(5,HIGH);
}
else {
digitalWrite(5,LOW);
}
}
}

}
void MotorProcedure()
//,
{

int Type = mode;//////// //Changes the operation Mode////////////////////////////////////////
switch (Type) {

case 1: //Testing getPos() function

stepper.init();
stepper.isBusy();
stepper.goTo(long (pos));
if(stepper.getPos()==pos){
digitalWrite(L6470SC, LOW);
digitalWrite(10,LOW);
}
break;

case 2: // Testing move() function

stepper.init();
stepper.isBusy();
stepper.move(long (pos));
if(stepper.getPos()==pos){
digitalWrite(L6470SC, LOW);
digitalWrite(10,LOW);
}
break;

}
}

You seem to be missing the fact that pin 10 MUST be set as an OUTPUT pin, whether you (think you) use it or not.

void loop()
{
  ComunicationProcedure ();
}

Why? Perhaps you want to write another function for CommunicationProcedure() to call that calls another function that calls another function to do the real work.

Ok man…Thanks for your patience ,let us keep all very easy an simple…

I have just 2 questions

1.-
If I understand correctly when I put the pin 10 on HIGH. the comunication with my software should come down …but that is not the case… I modifided the code and this one i dont inlcude the other spi device just to be shure that i be able to turn off the WIZNET5100… if I select the case 1 (which in my code means (PIN 10, HIGH)) ! ohh surprise ! “the comunication persists”…
that is very very strange…

#include <SPI.h>
#include <Ethernet.h>
#include <Z_OSC.h>
//==============================================================================================================================================================

byte myMac = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // A Media Access Control address (MAC address)
byte myIp = { bla,bla}; // Ethenet Shield IP Adresse// Marked as Remote Host in vvvv
int serverPort = 4441; // Marked as Remote Port in vvvv Patch
byte destIp = { bla,bla }; // My Computer IP Adress
int destPort = 4442; // Destination Port

char oscAdr = “/z-osc/di”; // Adress for sending the Digital pins (2,3,5,6,7,8,9)

boolean sleep;
long int pos = 0;
long int mode =0;
//================================================================================================================================================================
//OSC Comunication //

Z_OSCServer server;
Z_OSCClient client;
Z_OSCMessage *rcvMes;
//================================================================================================================================================================
void setup(){
Ethernet.begin(myMac ,myIp);
server.sockOpen(serverPort);
pinMode(5,OUTPUT);
pinMode(10,OUTPUT);
digitalWrite(10,HIGH);
}
//============================================================================================================================================================

void loop()
{

if(server.available()){ //Gets a client that is connected to the server and has data available for reading.

rcvMes=server.getMessage();

if (!strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ))

pos = rcvMes->getInteger32(0); //Arduino recives a Position value

if (!strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ))

mode = rcvMes->getInteger32(1); // Arduino recieves the mode variable an then we make 3 diferent things

switch (mode) {
case 0:
PrintValues(pos); // first thing: “Print the values”
break;

case 1:

digitalWrite(10,HIGH);//Second thing: “break´s the comunication”

break;
case 2:
long test=500;
PrintValues(test); //Third thing: Just print the test variable value(500)
break;
}

if ( !strcmp( rcvMes->getZ_OSCAddress() , “/arduino/out” ))
{

sleep = rcvMes->getInteger32(2); //Get the value from vvvv
sleep = constrain(sleep, 0, 1); // limit the value to 0-1
if ( sleep == 1 ) {
digitalWrite(5,HIGH); // turns the pin 5 on/off with vvvv
}
else {
digitalWrite(5,LOW);
}
}
}

}

void PrintValues (long value ) // The function print the values in vvvv
{
Z_OSCMessage mes;
mes.setAddress(destIp,destPort);
mes.setZ_OSCMessage(oscAdr,“i” ,&value,DEC);
client.send(&mes);
}

2.-
Have you checked this link that talk about a bug in Ethernet Shields?
http://john.crouchley.com/blog/archives/662

thank you for your help…

Digital pin 10 is controlled by the ethernet library low level read and write routines. Setting pin 10 HIGH does not disable the communication. This is from w5100.cpp. Note the calls to setSS (sets pin 10 LOW) and resetSS (sets pin 10 HIGH).

uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
{
  for (uint16_t i=0; i<_len; i++)
  {
    setSS();    
    SPI.transfer(0xF0);
    SPI.transfer(_addr >> 8);
    SPI.transfer(_addr & 0xFF);
    _addr++;
    SPI.transfer(_buf[i]);
    resetSS();
  }
  return _len;
}

uint8_t W5100Class::read(uint16_t _addr)
{
  setSS();  
  SPI.transfer(0x0F);
  SPI.transfer(_addr >> 8);
  SPI.transfer(_addr & 0xFF);
  uint8_t _data = SPI.transfer(0);
  resetSS();
  return _data;
}

I have found the compatibility problem is caused by a difference in SPI mode. The w5100 and the microSD cards get along ok because they are both SPI mode 0. If the other device is not mode 0, there are problems.

edit: There would be problems if the interface code for the other SPI device did not use the same method for setting the SS pin for that device. The SD library uses this same method. If the code just sets the slave select LOW, and then you call the ethernet library functions, the other SPI device would respond also, causing trash and confusion on the SPI bus.