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:
- The interrupt after the 3rd byte (
i==1, because of the initial0b10) does not run (measured theDEBUG_PINof the slave with a scope, along with the SCK and SS), and - After that byte the master simply gets the sent bytes back (
0b0A,0b0Eetc.)
What's pretty strange:
- 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.
- 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.