Passing Array With SPI

Hi I am new at SPI communication. So I have a question about that. I want to pass an array its named 2D motArray[225][3]. I wrote my self master and slave code. I can pass the array clearly at the slave side but array doesnt putting correct. Always shifting or or placing it in the wrong order
or happening something I cant explain. Can anyone which named SPI MASTER can help me about that problem. I am open for making code more effective or usable for test and project. Thanks for help. Here I added my master code:

//Arduino SPI Master
//com 5

#include <SPI.h>
byte motArray[225][3] = {0}; // [number of rectangles] [number of variables (x, y, h, w)]

byte writeCommand = 0xCE;
byte endWriteCommand = 0xFF;
void setup (void)
{
  Serial.begin (9600);
    for (int i = 0 ; i < 225; i++) {
    motArray[i][0] = i;
    motArray[i][1] = i;
    motArray[i][2] = i;
  }
  Serial.println ("Master");


  // 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);

}  // end of setup


int b;
int statusBuffer;
void loop (void)
{
    statusBuffer = SPI.transfer(writeCommand);
  if(statusBuffer == 0xCE){  
    statusBuffer = 0;
    for ( int i = 0 ; i < 225 ; i++)
    {
      for (int j = 0 ; j < 3 ; j++)
      {
        b = (motArray[i][j]);
        int y = SPI.transfer (b);
        delayMicroseconds(200); //give the slave time to process
       Serial.print(motArray[i][j]);
       Serial.print(" ");
   
      }
        Serial.println();

    }
  }
  else if(statusBuffer == 0xFD){
    Serial.println("unknown command!!!");
    }
  else{
    Serial.print("Failed!!!");
    }
  
  delay(1000);
  Serial.println();
  Serial.println("=================");

}  // end of loop

slave code:

//arduino SPI Slave
//com 11
#include <SPI.h>
const byte writeCommand = 0xCE;
const byte endWriteCommand = 0xFF;
volatile bool writeFlag = false;
volatile bool flag2 = false;
volatile bool endWriteFlag = false;
volatile int c;
volatile int fit, fitCtrl;


int i = 0;
volatile int holdArray [675];
int motArray[225][3];
void setup (void)
{
  Serial.begin (9600);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // turn on interrupts
  SPCR |= _BV(SPIE);
}  // end of setup

ISR (SPI_STC_vect)
{

  c = SPDR;
  if (c == writeCommand) {
    writeFlag = true;
    endWriteFlag = false;
    SPDR = 0xCE;
  }
  else if (c == endWriteCommand) {
    endWriteFlag = true;
    writeFlag = false;
  }
  else{
    SPDR = 0xFD;
    }
  if (writeFlag  & !endWriteFlag) {
    holdArray[i] = c;
    i++;
    if (i >= 676) {
      i = 0;
      flag2 = true;
      writeFlag = false;
    }
  }
} // end of interrupt service routine (ISR) SPI_STC_vect


void arrayToMatrix() {
  int a = 2;
  for (int l = 0; l < 225; l++) {
    for (int m = 0; m < 3; m++) {
      motArray[l][m] = holdArray[a];
      a++;
    }
  }
}
void printMatrix() {
  for (int x = 0; x < 225; x++) {
    for (int y = 0; y < 3; y++) {
      Serial.print(motArray[x][y]);
      Serial.print(" ");
    }
    Serial.println();
  }
}

void loop (void)
{
  if (flag2 == true) {
    //   for ( int k = 0 ; k < 675 ; k++){
    //          Serial.print(holdArray[k]);
    //
    //    Serial.println(" ");
    //    }
    arrayToMatrix();
    printMatrix();
    flag2 = false;

  }  // end of flag set
}

Which Arduino boards are you using ?

Arduino mega2560

In this code I can clearly receiving and fitting my datas inside of the holdArray but when the slave and master synchronization is broken this array filling wrong order. Datas are shifting. How I can fix that. Self solution I tried to add a writeCommand when this received by slave slave starts to fill holdArray but I couldnt implemented perfectly.

No surprise that when the master and slave are out of synch it causes a problem

Add begin and end markers to the data that is sent so that you can synchronise the receipt of data with what is being written

Actually I am using writeCommand and endWriteCommand for it. But implementation really bad probably. Can you help me how can I add that markers effectively and synched.

The technique that I had in mind is described here Serial input basics - updated

As I said before I added begin and end commands named writeCommand = 0xCE, endWriteCommand = 0xFF. When transmitting starts with first data in the master's array first data sent by master 0xCE after then master starts to send array in for loop. When this loop ended to transmitting array last character sends 0xFF it means write action ended. At the slave side slave controls the data in SPI interrupt routine and controls the data if SPDR buffer reads 0xCE turns on the writeFlag if SPDR buffer reads 0xFF turns off the writeFlag. When write flag activated system fills the holdArray with received array values. I imagined that If I use that flags. I can fill the array correctly all the time. What I mean correctly. I mean 0. data is received and replaced in hold array 0,1.-1. etc. But I am losing synch sometimes I dont know reasons. I hope I could explain the situation clearly. That is the main problem that I have.

Here is the solution everyone can implement it. If you have any data loses you can use the frequency divider of SPI's.

//Arduino SPI Master
#include <SPI.h>
byte motArray[225][3] = {0}; // [number of rectangles] [number of variables (x, y, h, w)]

const char writeCommand = 0xFE;
const char endWriteCommand = 0xFF;
void setup (void)
{
  Serial.begin (9600);
  for (int i = 0 ; i < 225; i++) {
    motArray[i][0] = i;
    motArray[i][1] = i;
    motArray[i][2] = i;
  }
  Serial.println ("Master");
  // 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_DIV16);
}  // end of setup


int b;
int statusBuffer;
void loop (void)
{
  statusBuffer = SPI.transfer(writeCommand);

  delayMicroseconds(20);

  for ( int i = 0 ; i < 225 ; i++)
  {
    for (int j = 0 ; j < 3 ; j++)
    {
      b = (motArray[i][j]);
      //        Serial.println(b);
      SPI.transfer (b);
      delayMicroseconds(10);
      //        Serial.print(motArray[i][j]);
      //        Serial.print(" ");

    }
    //        Serial.println();

  }
  SPI.transfer(endWriteCommand);

  //  Serial.println();
  //  Serial.println("=================");
  delay(100);
}  // end of loop```

```//arduino SPI Slave
#include <SPI.h>
const int writeCommand = 0xFE;
const int endWriteCommand = 0xFF;
volatile bool writeFlag = false;
volatile bool loopFlag = false;
volatile bool endWriteFlag = false;
volatile int c;


volatile int i = 0;
volatile int holdArray [677];
int motArray[225][3];
void setup (void)
{
  Serial.begin (9600);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // turn on interrupts
  SPCR |= _BV(SPIE);
}  // end of setup

ISR (SPI_STC_vect)
{

  c = SPDR;
  if (c == writeCommand) {
    writeFlag = true;
//    Serial.println("started");
  }
  else if (c == endWriteCommand) {
    writeFlag = false;
//    SPDR = endWriteCommand;
    
  }
  if (writeFlag) {
    holdArray[i] = c;
    i++;
    if (i >= 677) {
      i = 0;
      loopFlag = true;
      writeFlag = false;
      endWriteFlag = true;
//        Serial.println("array filled checkpoint!!!");

    }
  }
//  Serial.println(i);
//  Serial.println(c);
} // end of interrupt service routine (ISR) SPI_STC_vect


void arrayToMatrix() {
  int a = 1;
  for (int l = 0; l < 225; l++) {
    for (int m = 0; m < 3; m++) {
      motArray[l][m] = holdArray[a];
      a++;
    }
  }
  a = 0;
}
void printMatrix() {
  for (int x = 0; x < 225; x++) {
    for (int y = 0; y < 3; y++) {
      Serial.print(motArray[x][y]);
      Serial.print(" ");
    }
    Serial.println();
  }
}

void loop (void)
{
  if (loopFlag == true) {
    arrayToMatrix();
    printMatrix();
    motArray[225][3]={0};
    loopFlag = false;
}
  // end of flag set
}

The "solution" seems to not be a very efficient.
Why did you send the array byte by byte? Why the delay after every byte?

Because SPI send the data 8 bits also byte data type takes memory 8 bits of memory space. I though its the more efficiend way to send data with byte to byte. Also I added delay between each bytes for stability. I tested this circuit a little bir long range which I mean 3 meter I know SPI doesnt perfect way to test with this ranges but It was just a test. In this test I had the best solution with this small delay and without any lose. I hope this reasons I thoughts are correct. Can you send or modify the code more efficient way for me pls. I am really open for better ideas.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.