I am going to contribute a little bit here. I hope it helps a little.
I am still new to Arduino and SPI. There are still many things that I don't understand well.
I was following Nick's tutorial closely here on how to send data back to the master from slave.
However, that tutorial shows you how to send a byte back to the master. If let say you want to send a string of text back to the master, its not as easy as I thought.
Ok, here is a code that is not working. Please note that it is not the complete code. I only show you the necessary codes that involves SPI communcations.
//master
int gpsSlavePin = 49;
const int GPS_LENGTH = 29;
void setup () {
pinMode(gpsSlavePin, OUTPUT);
digitalWrite(gpsSlavePin, HIGH); // ensure SS stays high for now
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
// Then put SPI hardware into Master mode and turn SPI on
SPI.begin ();
// Slow down the master a bit
SPI.setClockDivider(SPI_CLOCK_DIV8);
Serial.begin(115200);
Serial.println("Master initialized");
getGpsCoordinates();
} // end of setup
void loop () {
} // end of loop
//This, its not gonna work. You are gonna get garbage responses from the slave
void getGpsCoordinates() {
// enable Slave Select
String testString = "";
digitalWrite(gpsSlavePin, LOW); // SS is pin 49
for(int i=0; i<GPS_LENGTH; i++) { //GPS_LENGTH
char response = SPI.transfer(GPS_COORDINATES);
//testString += response;
Serial.print(response);
}
digitalWrite(gpsSlavePin, HIGH); // disable Slave Select
}
//slave
#define GPS_COORDINATES 0x0B
char coordinatesArray[] = "Lat: 1.123456 Lon: 103.123456";
void setup() {
Serial.begin(115200);
pinMode(MISO, OUTPUT); //have to send on MISO, pin 12 on UNO
SPCR |= _BV(SPE); //Turn on SPI in slave mode
SPI.attachInterrupt(); //turn on interrupt
}
// SPI interrupt routine
ISR (SPI_STC_vect) {
byte c = SPDR; //grab a byte from SPI data register
switch(c) {
case GPS_COORDINATES:
SPDR = coordinatesArray[counter]; //THIS WORKS
bGpsCoordinates = true;
break;
}
}
// wait for flag to set in interrupt routine
void loop() {
if(bGpsCoordinates) {
charToSend = coordinatesArray[counter];
counter++;
Serial.print(charToSend);
bGpsCoordinates = false;
}
}
The master codes below works, and I would be able to get the coordinates String from the slave.
//master
int gpsSlavePin = 49;
const int GPS_LENGTH = 29;
void setup () {
pinMode(gpsSlavePin, OUTPUT);
digitalWrite(gpsSlavePin, HIGH); // ensure SS stays high for now
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
// Then put SPI hardware into Master mode and turn SPI on
SPI.begin ();
// Slow down the master a bit
SPI.setClockDivider(SPI_CLOCK_DIV8);
Serial.begin(115200);
Serial.println("Master initialized");
getGpsCoordinates();
} // end of setup
void loop () {
} // end of loop
//This one works. I can get the responses from the slave
void getGpsCoordinates() {
String testString = "";
digitalWrite(gpsSlavePin, LOW);
SPI.transfer(GPS_COORDINATES); //Don't need to store this response
digitalWrite(gpsSlavePin, HIGH);
SPI.end();
delay(1000);
for(int i=0; i<GPS_LENGTH; i++) { //GPS_LENGTH
SPI.begin();
digitalWrite(gpsSlavePin, LOW); // SS is pin 49
char response = SPI.transfer(GPS_COORDINATES);
testString += response;
digitalWrite(gpsSlavePin, HIGH); // disable Slave Select
SPI.end();
}
Serial.print(testString);
}
Ok, that's all about it. I am not sure why do I need to disable and re-enable the SPI in the loop on the master to make it work. Perhaps, can someone please explain to me why is that so?
Secondly, I am also not sure whether this is a good practice or not. If there is a better practice to achieve the same thing let me know.
Last but not least, I hope it helps for those who are trying to send a String / array of characters from slave to the master. ![]()