Hello, im trying to figure out SPI communication with two arduinos - mega and nano.
Trying to transfer values between them like so - mega sends commands (like 'a', 'b', 'c', 'd', etc), and nano responds to that command with pot values (i have 4 pots). But problem is that there is a delay() in example code (Nick Gammon master/slave code), which we all know is not good for "multitasking" timed events. I understand that it needs to have delay() to grab data from slave (nano) How can it be done with millis()/micros() or mby there is different route?
Please post a complete sketch that illustrates the problem that you are trying to solve
Whilst the use of delays can cause problems is a delay of 20 microseconds really a problem in your project ? I assume that you realise how short a period of time that really is
byte transferAndWait (const byte what){
byte a = SPI.transfer (what);
delayMicroseconds (20); //somehow needs to be replaced with micros() function
return a;
}
transferAndWait ('a'); // comand to get pot 1 value | value is from 0-255.
transferAndWait (10); // send some data to get potval1 back?
byte potVal1 = transferAndWait (0); // get value into variable and send dummy data
//already 60 micros delay in the loop
And yes, it is a problem in my project, because i need send few tens of commands, and it adds up in loop, for example, i send 10 transferAndWait(); to slave, its already 200 micros and it messes up timing.
Above your comment is Master code, Here is the slave(nano) code:
volatile byte command = 0;
void setup (void){
Serial.begin(115200);
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
}
ISR (SPI_STC_vect){
byte c = SPDR;
Serial.println(SPDR);
switch (command){
// no command? then this is the command
case 0:
command = c;
SPDR = 0;
break;
case 'a':
SPDR = 115; // send value back to master
break;
}
void loop (void){
// if SPI not active, clear current command
if (digitalRead (SS) == HIGH)
command = 0;
}
No worries, there is no need for full sketch, its (few pages/ files long). I`m just trying to get these sketches to work. Problem is with implementing millis()/micros() function to control spi transfer/recieve timing
It is declared false in global variables, than when millis() function executes code inside, it sets it true, so code inside runs one time every 500 millis, than it sets it back to false, so it can run continuously
I think delay needs to be because slave is not yet put value in SPDR register. If it waits some time, than SPDR is populated with value, and can be sent to master, if there is no delay time, it just sets a variable (and prints out) to value which master is sending to slave.
But yeah, how can it be, that value is not put after 2 of 3 times sending command?
If you ask me the delay is there to give the slave time to place the answer in the SPDR register.
This is a clue how to remove it. There are multiple levels of optimization each comes with its own compromise/drawback. Nothing is free in life.
Just remove the delay and do something else for that amount of time, before you send the next command to your slave.
Make sure your slave is as fast as possible e.g., remove the Serial.println from the ISR. The faster your slave the shorter you can make the delay and will still answer in the next cycle. If your slave needs to do something else e.g., compute the answer make sure it has a good processor and high enough clock speed.
Write your own SPI library. That will give you the least amount of wasted time, but you will need to handle the fact that the SPI transfer takes time. You can get all the code you need from the Arduino SPI library. https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SPI/src/SPI.h
So, after each write to SPDR you can do something else until you can read the value from the current transfer and then you need to give the slave time to place the answer into its SPDR register and do another transfer.