SPI - cannot communicate with multiple peripherals

Hello,
I am simply trying to get my master device (raspberry pi pico) to communicate with multiple peripherals. As it is with spi, MOSI, MISO, and CLK lines are common, and each device has its own CS pin.

When I setup my code to only communicate with one peripheral, the peripheral receives all bytes without a problem and everything works perfectly. The code is below (only SPI related stuff included)

void setup(){
  SPI1.setRX(12);
  SPI1.setCS(motCS);
  SPI1.setSCK(10);
  SPI1.setTX(11);
  SPI1.begin(true);
}

void sendCommand(){
  bufferOut[0] = uint8_t(controlWord>>8);
  bufferOut[1] = uint8_t(controlWord);
  for (int i = 0; i < 4; i++){
    bufferOut[i+2] = controlValue.bytes[i];
  }

  SPI1.beginTransaction(spi1settings);
  for (int i = 0; i < 6; i++){
    SPI1.transfer(bufferOut[i]);
    delayMicroseconds(comDelay);//found the communciation is more reliable with slight delay
  }
  SPI1.endTransaction();
}

But when I initialize and control the CS pin manually, since that is how every single tutorial does it, the data is just not going through. The code for that is the following:

void setup(){
  SPI1.setRX(12);
  SPI1.setSCK(10);
  SPI1.setTX(11);
  SPI1.begin(true);
  pinMode(motCS,OUTPUT);
  digitalWrite(motCS,HIGH);
}
void sendCommand(){
  bufferOut[0] = uint8_t(controlWord>>8);
  bufferOut[1] = uint8_t(controlWord);
  for (int i = 0; i < 4; i++){
    bufferOut[i+2] = controlValue.bytes[i];
  }
  digitalWrite(motCS,LOW);
  SPI1.beginTransaction(spi1settings);
  for (int i = 0; i < 6; i++){
    SPI1.transfer(bufferOut[i]);//send command to RP2040 motor
    delayMicroseconds(comDelay);
  }
  SPI1.endTransaction();
  digitalWrite(motCS,HIGH);
}

I tried differnet order of commands, including slight delays, everything I could think of, but in neither case the data is transfered from the master to the slave.

Since it works without a problem in the first case, I know hardware is not the problem.

If anybody's got any ideas, I'd be very grateful.

use SPI1.begin() without true

1 Like

That means to me that the RasPi class will handle a single client device and do the CS itself. So I see two possible solutions:

  1. a special value tells the SPI class not to select a client
  2. setCS() must be called before a transaction

What is board oackage do you use for Pico?

tried it, did't make a difference. Actually, it made the first working code not work

It's a custom board so I am just programming the RP2040. But in arduino IDE I use the Raspberry Pi pico build by Earl Philhower

Indeed

The flag in SPI.begin() controls, whether the library use hardware CS pin to interface with slave or not.
Therefore, you need ...begin(true) in your first code and begin(false) or just begin() in the second - it allow you to use software controlled CS pins for multiple slaves.

there it is need. in the other it interferes.
you didn't look up the meaning of the parameter?

I tried calling setCS() with the different CS pins before each communication and it didn't help unfortunately. I also couldn't find anything useful on handling CS pins within the SPI calss

I tried it and it didn't help. Doesn't matter if I manually pull the CS pins high/low or try to call setCS() with the right pin each time. The moment I dont call setCS() before SPI1.begin(true) and try to do anything else, I can't get the communciation to work

Ok I found the solution.
The problem was with sending multiple bytes one by one. Before each SPI.transfer() the CS pin needs to pulled low and after each SPI.transfer the CS pin needs to be pulled high. SO the working code looks the follwoing:

void setup() {
  SPI1.setRX(12);
  SPI1.setSCK(10);
  SPI1.setTX(11);
  SPI1.begin();
  pinMode(motCS,OUTPUT);
  digitalWrite(motCS, HIGH);
  delay(200);
}

void sendCommand(){
  bufferOut[0] = uint8_t(controlWord>>8);
  bufferOut[1] = uint8_t(controlWord);
  for (int i = 0; i < 4; i++){
    bufferOut[i+2] = controlValue.bytes[i];
  }
  digitalWrite(motCS,LOW);
  SPI1.beginTransaction(spi1settings);
  for (int i = 0; i < 6; i++){
    if(i>0) digitalWrite(motCS,LOW);
    SPI1.transfer(bufferOut[i]);//send command to RP2040 motor
    if(i<5) digitalWrite(motCS,HIGH);
    delayMicroseconds(comDelay);
  }
  SPI1.endTransaction();
  digitalWrite(motCS,HIGH);
}

no, it is incorrect

alright, well regardless the solution code I povided solves my problem so I am sticking with it

Well, if you provided the whole code for context, perhaps someone could illuminate why you both may be correct. As it is, your snippet is worthless.
Loop() is missing, as are variable declarations that are needed to understand, so :man_shrugging:.

Without the full code the solution mark should be removed, the post #11 is not the solution

1 Like

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