Pages: [1]   Go Down
Author Topic: Communication between 3 or more Arduinos with SPI  (Read 1039 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I need to communicate  more than 2 Arduinos with SPI.
I connected them this way:



I wrote the following code for receive double on master:

Code:
#include <SPI.h>

const int SS1 = 8;
const int SS2 = 9;
double valor;
byte* pvalor;
byte slave = 0;

void setup() {
  // set the SS1 as an output:
  pinMode (SS1, OUTPUT);
  pinMode (SS2, OUTPUT);
  // Begin sending data to Slave 1
  digitalWrite(SS1,LOW);
  digitalWrite(SS2,HIGH);
  // initialize SPI:
  SPI.begin();
  Serial.begin (57600);   // debugging
  
  pvalor = (byte *) &valor;
}

void loop() {
  
  SPI.transfer(0x0F);
  for (int i = 0; i < 4; i++) {
    pvalor[i] = SPI.transfer(i);
    delay(100);
  }
  delay(500);
  Serial.println(valor);
  
  i++;
  
  if ((i % 10) == 0) {
    slave = (slave + 1) % 2;
    switch (slave) {
      case 0:
        digitalWrite(SS2,HIGH);
        delay(1000);
        digitalWrite(SS1,LOW);
        break;
      case 1:
        digitalWrite(SS1,HIGH);
        delay(1000);
        digitalWrite(SS2,LOW);
        break;
    }
  }
}

and for slaves:

Code:
#include <SPI.h>
// Definition of interrupt names
#include < avr/io.h >
#include < avr/interrupt.h >

int sensePin = 2;
double valor = 5000;
byte* pvalor;
boolean interrupt = false;
int led = 9;

void setup (void)
{
  Serial.begin (57600);   // debugging

  // read from the sense pin
  pinMode(sensePin, INPUT);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  pvalor = (byte *) &valor;

}  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;  // grab byte from SPI Data Register
  Serial.print(c);
  Serial.print(" ");
  switch (c) {
    case 0x0F:
      valor = valor + 1.12;
      SPDR = pvalor[0];
      break;
    case 0:
      SPDR = pvalor[1];
      break;
    case 1:
      SPDR = pvalor[2];
      break;  
    case 2:
      SPDR = pvalor[3];
      break;      
  }
}  // end of interrupt routine SPI_STC_vect

void loop (void)
{
  int valor = digitalRead(sensePin);
  if ((valor == HIGH) && (interrupt == true)) {
    digitalWrite(led, LOW);
    
    SPI.detachInterrupt();
    SPI.end();
    interrupt = false;
  } else if ((valor == LOW) && (interrupt == false)) {
    digitalWrite(led, HIGH);
    
    // turn on SPI in slave mode
    SPCR |= _BV(SPE);
    // now turn on interrupts
    SPI.attachInterrupt();
    interrupt = true;
  }
  delay(100);
}  // end of loop

This works fine for communicating 2 arduinos but, when I connect another arduino the master only receive zeros. Anyone know what can be happening?
« Last Edit: October 30, 2012, 09:08:41 am by Muchael » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19118
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
when I put another arduino

What do you mean by that? How have you wired it all up?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick, I mean when a connect another Arduino to the bus, now there is a image of how I wired it on the first post.
Logged

nr Bundaberg, Australia
Online Online
Tesla Member
***
Karma: 129
Posts: 8603
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't have the slave's SS pins (pin 10) connected. You do have two wires going to pins 2 for some reason but that won't do anything for SPI.

Read up on SPI's use of the SS pin when the chip is a slave.

BTW you can't just hang a LED form a pin straight to GND, you MUST have a current-limiting resistor.

Also I can't really follow your master code but you seem to do X SPI.transfer()s and then dick with SS1 and SS2 after the transfers?? You have to drop SSx, do the transfers then raise SSx.

Is SPI.attachInterrupt(); valid code? It does compile but I can't see any documentation for it. And if it is valid surely it needs a reference to a function as the parameter.

______
Rob
« Last Edit: October 30, 2012, 10:25:08 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Graynomad, the problem was with the SS pin.
And the SPI.attachInterrupt(); is a valid code. I didn't pass the function as parameter because I'm registering the interrupt this way:  ISR (SPI_STC_vect)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19118
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

SPI.attachInterrupt just does this, so that part look OK.

Code:
void SPIClass::attachInterrupt() {
  SPCR |= _BV(SPIE);
}

@OP: http://www.gammon.com.au/spi
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19118
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Apart from no resistors for the LEDs, you have to have the SS line on the slaves to be pin 10, which is what the hardware expects, as Graynomad said.

Also, as he said:

Code:
void loop() {
 
  SPI.transfer(0x0F);
  for (int i = 0; i < 4; i++) {
    pvalor[i] = SPI.transfer(i);
    delay(100);
  }

Bring the SS line (for one of the slaves) low, transfer data, bring it high again, then do the same for the other slave, as required. Don't have both low at once.

What's the delay for? Do you like code that runs slowly?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code that I'm using now is like this:

Code:
void receiveDouble() {
  digitalWrite(slave,LOW);
  SPI.transfer(0x0F);
  for (int i = 0; i < 4; i++) {
    pvalor[i] = SPI.transfer(i);
    delay(10);
  }
  digitalWrite(slave,HIGH);
}

And I put the delay because without it the master don't get the right value from slave.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19118
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, OK, yes I forgot about that. My web page mentions needing a delay. Heh.

Is it working now?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, now it's working  smiley
Thanks Nick, I was trying to find some resource about Arduino SPI Slave and the one that you wrote is just what I need.
Logged

nr Bundaberg, Australia
Online Online
Tesla Member
***
Karma: 129
Posts: 8603
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
SPI.attachInterrupt(); is a valid code
Fair enough, I couldn't find any documentation. BTW I still can't, where is this documented?

Another typical example of Arduino bad naming practice. How can something call "attach" simply set a bit and not load a function pointer like the function of the same name does elsewhere. This should be enableInterrupt() or something.

_____
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 506
Posts: 19118
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It's an Easter Egg for those that browse the code. smiley-wink
Logged


nr Bundaberg, Australia
Online Online
Tesla Member
***
Karma: 129
Posts: 8603
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

He he, like I said, typical Arduino (non)documentation and bad naming practices.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Pages: [1]   Go Up
Jump to: