How can I set a character in a variable to send over SPI?

Hello,

I am making a Master-Slave system with ArduSPi (you can find it here on Github)
Now I made some code for the slave to switch 2 led’s. But how can I send the right characters to the slave from the master?
It works with a variable that’s need to have a character but how can I do this?

On internet I found some tutorials but they are all with the serial port where the user types the characters and that’s not what I want. I just want a demo code to start. Soemthing like this: turn led 1 on, turn led 2 on, turn both led’s off.

Here is my code:

Master:

// ArudSPI_master

#define LED_PIN 13

const int slavePause = 50,
          nbSlaves = 1,
          select = 0,
          ack = 1,
          slaves[nbSlaves][2] = {{2,3}}//slave O {Select,ack}

// some pretend data to send to the slaves
char dataOut[nbSlaves] = {'R'};

void setup(){
  Serial.begin(9600);
  for (int i=0;i<nbSlaves;i++){
    pinMode(slaves[i][select], OUTPUT);
    digitalWrite(slaves[i][select], LOW);
    pinMode(slaves[i][ack], INPUT);
  }
  pinMode(LED_PIN, OUTPUT);
  waitForSlaves();
}

void waitForSlaves(){
  // pulse LED for 5 seconds before going to the loop.
  // this gives time to turn on the slaves,
  // it is preferable to turn the slaves on before the master
  for(int i=0;i<5;i++){
    delay(1000);
    pulse(1);
  }
}

void loop(){
  for (int i=0;i<nbSlaves;i++){
    // give visual feedback that we are about to write to a slave
    // the number of pulses = 3*SlaveID
    pulse(i+1);
    writeSlave(i,dataOut[i]);
    delay(slavePause);
  }
}

void pulse(int c){
  // pulse the LED 3 * (arg+1) times
  for(int i=0;i<3*c;i++){
    digitalWrite(LED_PIN,HIGH);
    delay(200);
    digitalWrite(LED_PIN,LOW);
    delay(200);
  }
}

void writeSlave(int id, char data){
  // select salve
  digitalWrite(slaves[id][select],HIGH);
  // send off the data
  Serial.write(data);
  // wait for the slave to ACK receptions
  while(digitalRead(slaves[id][ack]) == LOW){;}
  // deselect the slave
  digitalWrite(slaves[id][select],LOW);
}

Slave:

// ArduSPI_slave

////////////////////////////////////////////////////////////////////
///  ONLY the following line needs to be changed for each slave !!!!
#define THIS_SLAVE 1
//// end of slave specifics
////////////////////////////////////////////////////////////////////

#define SLAVE_ID THIS_SLAVE
#define SELECT_PIN 2
#define ACK_PIN 3
#define LED_PIN 13

char data;
boolean ledON[2] = {
  false};

void setup(){
  Serial.begin(9600);
  while(!Serial){
    ;
  }  // necessary on some Arduinos, may as well keep it.
  pinMode(SELECT_PIN, INPUT);  // we will read from the 'select' pin
  pinMode(ACK_PIN, OUTPUT);    // and write to the ACK pin
  digitalWrite(ACK_PIN, LOW);  // init it to NACK
  pinMode(LED_PIN, OUTPUT);    // set LED_PIN to writing
  digitalWrite(LED_PIN, HIGH);
  delay(100);
  digitalWrite(LED_PIN, LOW);  // and init to' off'
  pinMode(5, OUTPUT);    // set RED_LED to writing
  digitalWrite(5, LOW);  // and init to' off'
  pinMode(6, OUTPUT);    // set BLUE_LED to writing
  digitalWrite(6, LOW);  // and init to' off'

}

void loop(){
  // all we do is get some data and do what it says
  // if there is data, do something, otherwise loop
  if(getData()){
    doSomethingWithData();
  }
}

boolean getData(){
  // if not selected, ensure ACK_PIN is LOW and do nothing!
  if(digitalRead(SELECT_PIN)==LOW){
    digitalWrite(ACK_PIN,LOW);
    return false;
  }
  // if we got here, the the SELECT_PIN is HIGH, 
  // so we need to read serial
  // first wait for something to be available to read
  while(!Serial.available()){
    ;
  } 
  // then read 1 byte into the 'data' variable
  while(Serial.readBytes(&data,1) == 0) {
    ;
  }
  // ACK the serial read
  digitalWrite(ACK_PIN,HIGH);
  return true;
}

// just to demonstrate that the slave is doing something  
// change the LED state at every reception of data.
void doSomethingWithData(){
  switch(data){
  case 'R':
    changeState(5);
    break;
  case 'B':
    changeState(6);
    break;
  }
}

void changeState(int pin)
{
  int x = (pin - 5); // pins starts at 5 and array at 0 so we need to 'convert' it.
  ledON[x] = !ledON[x]; // change the state from the boolean variable
  if(ledON[x]) // write the change to the corect pin
  {
    digitalWrite(pin,HIGH);
  }
  else
  {
    digitalWrite(pin,LOW); 
  }
}

regards,
Dylan

Does it have to be SPI? even the Attiny85 (which has no hardware serial pins) can communicate at 9600 using softwareserial library and makes life so much simpler....

It works now for 1 led :/ How are you going to do that with serial (Master - Slave?)

regards, minitreintje

Does it have to be SPI?

Have you followed the link? That’s not SPI, that’s just standard serial communication with an “SPI style” chip select pin to tell the slave that the master wants to tell it something.

@OP: How did you wire this? If you connect all slaves TX lines directly you’ll produce a short circuit. The serial interface is NOT a bus and you get several problem if you try to use it like that. If you want to use it as a bus get a MAX485 (or similar) and form a RS485 bus with it.

No I know it isn't 'real' SPI. Bus with be easier. What's better then? For a distance like 10 metres max.

regards, Dylan

SPI can't handle that distance anyway...

Try UART (Softserial)

Yes I will try it. But is it possbile to work with adressing then? And how?

Dylan

it's easy then, you send a byte of data and you read the contents the other end then check it's contents with an if statement....

Have you coded much?

Yes it is really simply if I read it but it’s the first time I am experimenting with communication and I can’t get it…

Dylan

SPI can't handle that distance anyway...

Try UART (Softserial)

UART also is the wrong answer for such distances. As I already suggested, use RS485 or any other technology that was developed for longer distances (Ethernet comes to mind too).

I will search for something else... Thanks for the replies :)

Dylan

10meters too long?... the signal degrades thatmuch? ..

Wow