SPI not triggering when using external power

Hey everyone,
I am working on a quite complex system, where we have a master Arduino (Mega), which communicates with lots of slaves (Nano's) via SPI. When the system is powered through USB, the communication works perfectly. The problem is, that there are some slaves, which are operating some tools with high current draw (i.e. motor), and in the future the number of slaves might increase (from ~5 to >10), so we need an external power supply. Now the problem is, that when we use one (9V/2A), the SPI communication is flawed with one of the components.
This single slave is accepting user commands from the computer through Serial, and forwards it to the master, if it got one. The interrupt of this slave looks something like this:

ISR (SPI_STC_vect)
{
  digitalWrite(DEBUG_PIN, HIGH); //for debugging
  input_byte = SPDR;
  if (mode == IDLE_MODE) {
    if (input_byte == 1) {
      SPDR = has_command; // if the user provided a command, answer '1'
    } else if(input_byte & 0b10) { // getting command
//if the input_byte ends with 0b10, it's asking for a byte; the index of the byte is at the higher bits
      int idx = (input_byte >> 2); 
      if(idx == 0){
        has_command = 0; //reset when sending the command
      }
      if(idx < sizeof(UserCommand)) {
        SPDR = temp_cmd_data.buf[idx];
      } else {
        SPDR = 0;
      }
    } else {
      SPDR = 0;
    }
  } else if (mode == GETTING_LOGDATA_MODE) {
   //deleted as not relevant 
  }
  else {
    SPDR = 0;
  }
  digitalWrite(DEBUG_PIN, LOW);
}

The idea is simple: the master asks for specific bytes from the command, and the slave sends them one by one. (For safety reasons the master specifically asks for each bytes, to not get jumbled data).
The master simply asks for the bytes in a loop:

SPI.beginTransaction(spiSettings);
  Serial.println("receive");
  digitalWrite(SS, LOW);
  delayMicroseconds(200); //I increased the delay to make sure it's not a speed issue
  SPI.transfer(0b10); //asking for the first byte
  delayMicroseconds(200);
  for(int i=0; i < sizeof(UserCommand); i++){
    cmd_buf[i] = SPI.transfer(((i+1) << 2) + 0b10); //asking for each byte
    delayMicroseconds(200);
  }
  delayMicroseconds(20);
  digitalWrite(SS_LOGGER, HIGH);
  SPI.endTransaction();

When powered from USB, everything works fine. When using the power supply, sometimes:

  1. The interrupt after the 3rd byte (i==1, because of the initial 0b10) does not run (measured the DEBUG_PIN of the slave with a scope, along with the SCK and SS), and
  2. After that byte the master simply gets the sent bytes back (0b0A, 0b0E etc.)

What's pretty strange:

  1. It is always the third byte, which doesn't trigger the interrupt, so I might think about a software issue, but again, this occurs only when the external power supply is connected. As you can see, I leave a pretty big delay between each byte, and the speed was set to 300kHz, but nothing changes (previously the delays were 20 microseconds, and speed was 3MHz, with the same results). The 8 clock signals and the data signal are all arriving (checked with a scope), so this is not the issue.
  2. After the missing interrupt, the other interrupts are triggered, but the master still receives back the sent bytes.

Does anyone have an idea, what could cause this? Where should I start to debug?
I tried to include every useful information, but if anything else needed, just let me know.

Is the power supply for all the devices same or is the master on USB and slaves on 9V supply? If so then are the ground lines common?

1 Like

To be honest this sounds like a path to eventual failure if the SPI wiring is over 1 meter in length. SPI was designed for on board communications between master and slave chips, not as a communication bus. Pick some other protocol designed to to this, such as CAN, RS485 and others. How are you doing the chip selects. An annotated schematic would help.

The 9V and the ground from the power supply are both wired to arrays of PCB connectors (one array for each), and all arduinos are connected to these (9V-Vin, GND-GND).

All the Arduinos are in a box (30cm×40cm), so they are not far from each other. There's a single Mega, which is outside of the box, and actually its cables were longer than a meter, but we replaced it with a shorter cable, unfortunately without any effect. Also, the fact that the system works without the power supply shows that it should work with the current cable lengths.

What do you mean? By writing LOW to the given slave's slave select pin (I guess you already know that). Could you specify, what you're interested in?

I will create a schematic soon, but I don't think anything surprising will occur. Every slave is connected to the MISO-MOSI-SCK lines on the master, and also every single Arduino is connected to 9V and GND from the power supply. Actually we tried different voltage, from 5V to 9V, but nothing works.

@mohitsingh2806 , @gilshultz thanks for looking into this!

If you have access to a scope show the MISO, MOSI and SCK signals. I am interested in both rise and fall times as well as amplitude. Also do a waveform of the 9V when it first comes on.

It seems that we have some contact error. We'll fix it, and see if this solves the problem. I will get back here when we see if it worked.

Aand yes, a connectivity issue caused an interrupt on one of the slave's pins, so as the slave was in an interrupt during getting the data byte, it did not trigger the byte received interrupt. Stupid mistake indeed... Thanks for all your help!

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