SOLVED !!!!!!! How to TRANSFER data from SLAVE to MASTER using SPI

Hola muy buenas tardes
Mi nombre es Adrian, soy novato con proyectos en ARDUINO, y he estado siguiendo varios post de nickgammon, y foros de discusión en https://forum.arduino.cc, acerca de cómo TRANSFERIR datos entre MASTER y SLAVE usando SPI.

Inicialmente he conectado un ARDUINO NANO como MASTER a un ARDUINO UNO como SLAVE, usando los pines ->
o pin 10 (SS) -> Green
o pin 11 (MOSI) -> Gray
o pin 12 (MISO) -> Orange
o pin 13 (SCK) -> Cyan
o +5v (if required) -> Red
o GND (for signal return) -> Black
También he conectado dos sensores de temperatura 1-DHT11, y 2-DHT11, al Arduino UNO, siendo los cables con señal:
o 1-DHT11 ->Violet ->SGN pin A3
o 2-DHT11 ->Yellow ->SGN pin A2
Les adjunto un esquema de la conexión->

Estos componentes los he conseguido en BANGGOOD:

 Geekcreit® UNO R3 ATmega328P Development Board For Arduino No Cable
 Digital Temperature Humidity Sensor Module Probe For HVAC Arduino 4pin
 Geekcreit® ATmega328P Nano V3 Controller Board Compatible Arduino Improved Version Module
 Geekcreit® UNO R3 Improved Version + 2.8TFT LCD Touch Screen + 2.4TFT Touch Screen Display Module Kit For Arduino

Lo que intento conseguir es:
Cuando el MASTER lo solicite (enviando en el primer byte <1> ó <2>), obtener la temperatura registrada por el sensor seleccionado, conectado al SLAVE, transmitir el dato de la temperatura, y ver el resultado en el Monitor Serie asociado al MASTER.
Mi proyecto FINAL será poder visualizar las temperaturas en una pantalla TFT LCD 2.4” conectada al MASTER, dejando de lado la funcionalidad de la SD CARD que tiene el shield mcufriend TFT-LCD 2.4”.

Hasta el momento, los ejemplos dentro de SKETCH encontrados, funcionan para enviar y/o recibir un byte, o una cadena “Hola Mundo\n”, pero cuando intento modificar el código, no he podido hasta el presente obtener un flujo “estable” de datos entre MASTER & SLAVE.

Aunque los datos leídos en los sensores son del tipo float, realizo un “typecast” con int() y transmito SOLO enteros.
Siguiendo con el ejemplo encontrado en el post:  Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino
Utilizo la estructura ->

// create a structure to store the different data values:
typedef struct tempSTRUCT{
  byte ID;
  int nroTRANSACTION;
  int tempID;
  long nroSEQUENTIAL;
};

Para elegir el Sensor DHT11, genero un número aleatorio, y me aseguro de obtener un “byte” 

 randomT = byte(random(1,3));
// de esta forma obtendré aleatoriamente 1 ó 2
  dataSEND.a=randomT;

Finalmente desde el MASTER realizo ->

SPI_writeAnything (dataSEND);

Donde teóricamente debería poder RECIBIR, los datos leídos en el sensor ID DHT11, almacenado en -> dataSEND.a
Bien, en esta parte es donde me pierdo, y NO puedo lograr que las modificaciones realizadas en el SLAVE, se vean reflejadas en el MASTER.

A modo de ejemplo en el código original del sketch realizado por Nick GAMMON, la salida por monitor serie es:

42
32000
101064

42
32000
101065

42
32000
101066

Donde foo.a = 42 y foo.b = 32000 están asignados en el setup() del MASTER.
Y al tener éxito con la instrucción SPI_writeAnything (foo);
En el código del MASTER realizo foo.c++, razón por la cual, en las sucesivas iteraciones se ve el resultado: 101064, 101065, 101066 etc …
Noten que en el código adjunto más abajo del SLAVE, probé realizar lo siguiente:

   if ((int)dataSLAVE.a==1){
      dataSLAVE.b++;
    } else {
      dataSLAVE.b--;
    }

o su equivalente en el código de Nick  foo.b++, ó foo.b- -, que al imprimirse por el monitor serie se ve el cambio MOMENTANEO de la variable <foo.b>
Pero en la siguiente iteración del loop del MASTER, vuelve al valor ORIGINAL que tenía asignado en el setup(), como si no hubiese sido modificado.

18:03:46.116 -> 2
18:03:46.116 -> 12345
18:03:46.116 -> 156
18:03:46.116 -> 100322

18:03:47.094 -> 2
18:03:47.094 -> 12345
18:03:47.094 -> 156
18:03:47.094 -> 100323

18:03:48.117 -> 1
18:03:48.117 -> 12346
18:03:48.117 -> 156
18:03:48.117 -> 100324

18:03:49.092 -> 1
18:03:49.092 -> 12346
18:03:49.092 -> 156
18:03:49.092 -> 100325

Es decir, me falta poder incluir en el código del MASTER ->lo recibido, ACTUALIZARLO en la estructura definida.

¿Podría alguien ayuudarme a corregir este concepto al cual NO le puedo encontrar solución?

¿Es que necesito realizar transferencias INDIVIDUALES por cada variable de la estructura generada?

Desde ya agradezco su gentil colaboración,

Adrian RUFFATO

MASTER CODE

#include <SPI.h>
#include "SPIanything.h"

// create a structure to store the different data values:
typedef struct myStruct{
  byte a;         //  byte with ID
  int b;          //  int N° transaction
  int c;          //  int temp * 10 -> float(temp/10.0)
  long d;         //  long, increment to view data TRANSFER
  //char e;
};

volatile myStruct dataSEND;
volatile myStruct dataRECEIVED;

void setup (){
  SPI.begin ();
  Serial.begin(115200);
  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV128);

  dataSEND.a = 2;              //  byte with ID
  dataSEND.b = 12345;      //  int N° transaction
  dataSEND.c = 156;          //  int temp * 10 -> float(temp/10.0)
  dataSEND.d = 100000;    //  long, increment to view data TRANSFER
//  dataSEND.str = "M";     //  not available, for future uses
}                                     // end of setup

byte randomT;             //  ID of the DHT's random access

void loop (){ 
  digitalWrite(SS, LOW);    // SS is pin 10
  randomT = byte(random(1,3));
  dataSEND.a=randomT;
  SPI_writeAnything (dataSEND);
  //  *************************************************
  // I make a probe with the next sentences, but I only receive (0)
  //
  //SPI_readAnything (dataRECEIVED);  
  //  *************************************************

  digitalWrite(SS, HIGH);
  delay (100);  // for testing  

  //  *******************************************************
  //  Something like this, is what I think I need to RECEIVED from SLAVE
  //  dataSEND.b=dataRECEIVED.b;
  //  *******************************************************

  dataSEND.d++;       // <- this work OK

}  // end of loop

SLAVE CODE

#include <SPI.h>
#include "SPIanything.h"

// create a structure to store the different data values:
typedef struct myStruct{
  byte a;     //  byte with ID
  int b;      //  int N° transaction, no matter if increment, or decrement
  int c;      //  int temp * 10 -> float(temp/10.0)
  long d;     //  long, increment to view data TRANSFER loop
  //char e;
};

volatile myStruct dataSLAVE;
volatile bool haveData = false;

void setup (){
  Serial.begin (115200);   

  // have to send on master in, *slave out*
  //  ***************************************
  //  * Forma de preparar el SLAVE
  //  ***************************************
  pinMode(MISO, OUTPUT);
  //  pinMode(MOSI, INPUT);
  //  pinMode(SCK, INPUT);
  //  Ver el gráfico en blog de gammon.com.au
  //  _______________________________________

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // now turn on interrupts
  SPI.attachInterrupt();
  
}  // end of setup

void loop (){ 
  if (haveData){
    if ((int)dataSLAVE.a==1){
      dataSLAVE.b++;
      //  ************************************
      //  * To obtain temperature from 1-DHT11
      //  ************************************
      //float tA = dhtA.readTemperature();
      //dataSLAVE.b = int(tA*10);
    } else {
      //dataSLAVE.b--;
      //  ************************************
      //  * To obtain temperature from 2-DHT11
      //  ************************************
      //float tB = dhtB.readTemperature();
      //dataSLAVE.b = int(tB*10);
    }
     Serial.println ((int) dataSLAVE.a);
     Serial.println (dataSLAVE.b);
     Serial.println (dataSLAVE.c);
     Serial.println (dataSLAVE.d);
     //Serial.println (dataSLAVE.str);
     haveData = false;

//  **********************************
//  * This do not work ->
//     digitalWrite(SS, LOW);    // SS is pin 10
//    SPI_writeAnything (dataSLAVE);
//    digitalWrite(SS, HIGH);
//  **********************************


    delay (20);  // for testing  
  }
}  // end of loop

// SPI interrupt routine
ISR (SPI_STC_vect){
  SPI_readAnything_ISR (dataSLAVE);
  haveData = true;
}  // end of interrupt routine SPI_STC_vect

MasterSlave.pdf (795 KB)

There is an example in Section-7.3(7) of this pdf file on how UNO-SPIMaster receives float data (temp signal of LM35) from NANO-SPISlave.

Hello good moorning
Sorry for my English, I'm a SPANISH spoken.

My name is Adrian, I am a newest with projects in ARDUINO, and I have been following several nickgammon’s posts, and discussion forums at https://forum.arduino.cc, about how to TRANSFER data from SLAVE to MASTER (when MASTER request) using SPI.

Initially I have connected an ARDUINO NANO as MASTER to an ARDUINO ONE as SLAVE, using the pins:
pin 10 (SS) -> Green wire
pin 11 (MOSI) -> Gray
pin 12 (MISO) -> Orange
pin 13 (SCK) -> Cyan

  • 5v (if required) -> Red
    GND (for signal return) -> Black
    as you could see at the image and file attached, for the squematic conections (MasterSlave.pdf)

I have also connected two temperature sensors 1-DHT11, and 2-DHT11, to the Arduino UNO, the cables being signal:
1-DHT11 ->Violet ->SGN ->pin A3
2-DHT11 ->Yellow ->SGN ->pin A2

I have obtained these components at BANGGOOD:
Links: https://www.banggood.com/
Geekcreit® UNO R3 ATmega328P Development Board For Arduino No Cable
Digital Temperature Humidity Sensor Module Probe For HVAC Arduino 4pin
Geekcreit® ATmega328P Nano V3 Controller Board Compatible Arduino Improved Version Module
Geekcreit® UNO R3 Improved Version + 2.8TFT LCD Touch Screen + 2.4TFT Touch Screen Display Module Kit For Arduino

What I’ll try to achieve is:
When the MASTER requests it (sending in the first byte <1> or <2>), obtain the temperature registered by the selected sensor, connected to the SLAVE (COMM PORT 14), transmit the temperature data, and watch the result in the Serial Monitor associated to the MASTER (COMM PORT 10)

ON my FINAL project I hope will be able to visualize the temperatures on a 2.4 ”TFT LCD screen connected to the MASTER, leaving aside the functionality of the SD CARD that has the 2.4” TFT-LCD mcufriend shield.

So far, the examples within SKETCH found, work to send and/or receive a byte, or a string "Hello World \ n", but when I had tried to modify the code, I have not been able to obtain a "stable" flow until now of data between MASTER & SLAVE.

Although the data read on the sensors are of the float type, I perform a "typecast" with int () and transmit ONLY integers.
Following the example found in the post:  Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino
I use one similiar structure:

// create a structure to store the different data values:
typedef struct myStruct{
  byte a;         //  byte with ID
  int b;          //  int N° transaction
  int c;          //  int temp * 10 -> float(temp/10.0)
  long d;         //  long, increment to view data TRANSFER
  //char e;      //not used, only for investigate functionality
};

volatile myStruct dataSEND;
volatile myStruct dataRECEIVED;

At moment, to select the DHT11 Sensor, I generate a random number, and make sure I get a “byte” ->

   randomT = byte (random (1,3));
// in this way I will randomly get 1 or 2
   dataSEND.a = randomT;

Finally from the MASTER I do ->

  SPI_writeAnything (dataSEND);

Where theoretically I should be able to RECEIVE, the data read on the DHT11 ID sensor, stored in -> dataSEND.a

Well, this part is where I get lost, and I CANNOT make that the changes made in the SLAVE, be reflected at the MASTER. I have TROUBLE

As an example in the original code of the sketch made by Nick GAMMON, the output by serial monitor is:

42
32000
101064

42
32000
101065

42
32000
101066

Where foo.a = 42 and foo.b = 32000 are assigned in the setup () of the MASTER.
And by succeeding with the instruction SPI_writeAnything (foo);
In the MASTER code I do foo.c ++, which is why, in the successive iterations the result is seen: 101064, 101065, 101066 etc ...
Note that in the attached SLAVE code, I tried to perform:

    if ((int)dataSLAVE.a==1){
      dataSLAVE.b++;
    } else {
      dataSLAVE.b--;
    }

or its equivalent in the Nick code foo.b ++, or foo.b- -, that when printed by the serial monitor you can see the MOMENTARY change of the variable <foo.b>

But in the next iteration of the MASTER loop, it returns to the ORIGINAL value that was assigned in the setup (), as if it had not been modified.

18:03:46.116 -> 2
18:03:46.116 -> 12345
18:03:46.116 -> 156
18:03:46.116 -> 100322

18:03:47.094 -> 2
18:03:47.094 -> 12345
18:03:47.094 -> 156
18:03:47.094 -> 100323

18:03:48.117 -> 1
18:03:48.117 -> 12346
18:03:48.117 -> 156
18:03:48.117 -> 100324

18:03:49.092 -> 1
18:03:49.092 -> 12346
18:03:49.092 -> 156
18:03:49.092 -> 100325

That is, I need to be able to include in the MASTER code what has been received, and UPDATE it in the defined structure.

Could someone help me to correct this concept to which I can NOT find a solution?

Do I need to make INDIVIDUAL transfers for each variable in the generated structure?, and HOW could I make it?

Thank you in advance for your kind collaboration,

MASTER CODE

#include <SPI.h>
#include "SPIanything.h"

// create a structure to store the different data values:
typedef struct myStruct{
  byte a;         //  byte with ID
  int b;          //  int N° transaction
  int c;          //  int temp * 10 -> float(temp/10.0)
  long d;         //  long, increment to view data TRANSFER
  //char e;
};

volatile myStruct dataSEND;
volatile myStruct dataRECEIVED;

void setup (){
  SPI.begin ();
  Serial.begin(115200);
  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV128);

  dataSEND.a = 2;         //  byte with ID
  dataSEND.b = 12345;     //  int N° transaction
  dataSEND.c = 156;       //  int temp * 10 -> float(temp/10.0)
  dataSEND.d = 100000;    //  long, increment to view data TRANSFER
//  dataSEND.str = "M";   //  not available, for future uses

}    // end of setup

byte randomT;             //  ID of the DHT's random access


void loop (){ 
  digitalWrite(SS, LOW);    // SS is pin 10
  randomT = byte(random(1,3));
  dataSEND.a=randomT;

  SPI_writeAnything (dataSEND);
 // ****************************
 // * I try with these sentences, 
 //SPI_readAnything (dataRECEIVED);  
 // **************************** 
 digitalWrite(SS, HIGH);

  dataSEND.d++;
  delay (1000);
}  // end of loop

SLAVE CODE

#include <SPI.h>
#include "SPIanything.h"

// create a structure to store the different data values:
typedef struct myStruct{
  byte a;     //  byte with ID
  int b;      //  int N° transaction, no matter if increment, or decrement
  int c;      //  int temp * 10 -> float(temp/10.0)
  long d;     //  long, increment to view data TRANSFER loop
  //char e;
};

volatile myStruct dataSLAVE;
volatile bool haveData = false;

void setup (){
  Serial.begin (115200);   // debugging

  // have to send on master in, *slave out*
  //  ***************************************
  //  * Forma de preparar el SLAVE
  //  ***************************************
  pinMode(MISO, OUTPUT);
  //  pinMode(MOSI, INPUT);
  //  pinMode(SCK, INPUT);
  //  Ver el gráfico en blog de gammon.com.au
  //  _______________________________________

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // now turn on interrupts
  SPI.attachInterrupt();
  
}  // end of setup

void loop (){ 
  if (haveData){
    if ((int)dataSLAVE.a==1){
      dataSLAVE.b++;
      //  ************************************
      //  * To obtain temperature from 1-DHT11
      //  ************************************
      //float tA = dhtA.readTemperature();
      //dataSLAVE.b = int(tA*10);
    } else {
      //dataSLAVE.b--;
      //  ************************************
      //  * To obtain temperature from 2-DHT11
      //  ************************************
      //float tB = dhtB.readTemperature();
      //dataSLAVE.b = int(tB*10);
      // *************************************
      // * HOW to get the temperature, ->
      // * This part of CODE, I do not attach
      // *************************************
    }
     Serial.println ((int) dataSLAVE.a);
     Serial.println (dataSLAVE.b);
     Serial.println (dataSLAVE.c);
     Serial.println (dataSLAVE.d);
     //Serial.println (dataSLAVE.str);
     haveData = false;
//     digitalWrite(SS, LOW);    // SS is pin 10

//    SPI_writeAnything (dataSLAVE);
//    digitalWrite(SS, HIGH);
    delay (20);  // for testing  
  }
}  // end of loop

// SPI interrupt routine
ISR (SPI_STC_vect){
  SPI_readAnything_ISR (dataSLAVE);
  haveData = true;
}  // end of interrupt routine SPI_STC_vect

MasterSlave.pdf (795 KB)

SPI_writeAnything (dataSEND);

Why do you send 9 bytes if one would be enough?

It seems you try to use the SPI interface as a replacement to a UART connection. It's not created for that purpose and doesn't fit to it.
SPI communication is strictly master to slave, the slave might send some data back while the master is sending it's data. While your specific usage might be possible (you can send the structure to the slave and after that receive the slave's response. But you have to ensure the slave is reading/writing exactly the same number of bytes as the master. Using Nick's SPI_anything library hides a lot of the internals from the user but in your use case this contra-productive.

Looking at your code my impression is SPI is the wrong choice. Please explain, why you did choose SPI to communicate between the two Arduinos. Why is the communication necessary after all? Cannot one of the Arduinos do the whole job?

Pylon,

Thank you for your quickly reply, it seems I have at least two faults, my poor English and poor knowledges about electronics, specially with ARDUINO.

At the present if I attach a shield mcufriend LCD TFT 2.4" to Arduino UNO, to view temperature's data, and want to attach two DHT11 at the same board, or a RTC DS3231, I haven't enough pins, at least those pins can be shared. But I think this is not possible, I'm waiting to receives a module ARDUINO MEGA, that I just bougth last week-end.

If I intented to add a BUZZER(only in pin8 works) !!!, if I add a RED led to show something was wrong, all contribute to tell me I couldn't do with only ONE ARDUINO.

So, I'll try to understood how could I use and transfer data between two modules. If I use the library <Wire.h>, again pin A4, and A5 are in use...

And I do not know how could I transfer data, between ARDUINO NANO and ARDUINO UNO.

I hope, I have been clear with Why, and Because I'll trying to do.

:slight_smile: Thank you so much for your help and guide, best regards

Adrian

The way SPI works is that when the master sends a byte it simultaneously receives a byte from the slave. The data TO the slave goes on the MOSI line and the data FROM the slave comes on the MISO line.

If you want to get a byte from the slave the master must send a byte. Of course the byte that the master sends can be any old rubbish if the slave is not required to use it.

Associated with all this is the requirement that the slave will have placed the byte that is to go to the master in its SPDR register BEFORE the master begins the request.

The details are in (for example) the Atmega 328 datasheet.

...R

I've merged your cross posts @aruffato.

Cross posting is against the rules of the forum. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend 15 minutes writing a detailed answer on this thread, without knowing that someone else already did the same in the other thread.

Repeated cross posting will result in a suspension from the forum.

In the future, please take some time to pick the forum section that best suits the topic of your question and then only post once to that forum section. This is basic forum etiquette, as explained in the sticky "How to use this forum - please read." post you will find at the top of every forum section. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Dear PERT:
I'm apologize for the "cross post", but I do not undestand how I make a cross post, I have just only make a reply to Robin.

best regards
Adrian

You posted the same question yesterday and then you posted it again today. That's called cross posting and it's against the rules. Please don't do it.

Pert,
I'm sorry. Yes, yesterday I post a SPANISH question, but this morning I could be able to find it in the posted. So I think, that I must write in English, so I post AGAIN.

SORRY, it's my fault, but believe me, I could not find the first post, it was on September 12th 10:00 PM as you could see in main page.

Best regards,

Adrian

Here's how you can find your previous posts:

  • Hover the mouse pointer over your avatar in the top right corner of any arduino.cc page.
  • Click "Profile".
  • Click "Forum Settings > Edit".
  • Click "Show Posts".

Let us see how good the SPI communication goes between NANO and UNO --

1. This is your connection diagram among NANO (SPI Master), UNO (SPI Slave), DHT122-1 (in place of DHT11-1 whcih I don't have), and LM35 (inplace of DHT11-2 which I also don't have).
spix.png
Figure-1:

2. Upload the following sketch to UNO to acquire float type myTemp1 and myTemp2 signals from DHT22-1 and LM35 respectively at 1-sec interval; to show temperature signals onto SM2 (Serial Monitor); to convert 'float myTemp1' into its equivalent 32-bit (4-byte) binary32 formatted data and save into array 'byte data1.txmyTempArray[4]' so that this value can be sent to NANO when requests come; to convert 'float myTemp2' into its equivalent 32-bit (4-byte) binary32 formatted data and save into array 'byte data2.txmytempArray[4]' so that this value can be sent to NANO when requests come.

#include "DHT.h"
#define DHTPIN1 A2     // what pin we're connected to
#define DHTTYPE1 DHT22   // DHT 22  (AM2302)
float myTemp1;
float myTemp2;

union
{
  float txmyTemp;
  byte txmyTempArray[4];
} data1, data2;

DHT dht1(DHTPIN1, DHTTYPE1);

void setup()
{
  Serial.begin(9600);
  dht1.begin();
  analogReference(INTERNAL);
}

void loop()
{
  tempDht1();
  tempLM35();
  Serial.println("=====================");
  delay(1000);
  //Serial.println(data1.txmyTempArray[2], HEX); debugging
  //Serial.println(data2.txmyTempArray[2], HEX);
}

void tempDht1()
{
  myTemp1 = dht1.readTemperature();
  Serial.print("Temperature1: ");
  Serial.print(myTemp1, 2);
  Serial.println(" *C");
  //-----------------------
  data1.txmyTemp = myTemp1;
}

void tempLM35()
{
  myTemp2 = (float)100 * (1.1 / 1023.0) * analogRead(A3);
  Serial.print("Temperature2: ");
  Serial.print(myTemp2, 2);
  Serial.println(" *C");
  //-----------------------
  data2.txmyTemp = myTemp2;
}

smdht22.png
Figure-2:

3. Have some basic idea on SPI Communication referring to the diagram of Fig-3. For more rredaing you are referred to this pdf file.
spi328x.png
Figure-3:

(1) In SPI, data exchange happens one byte at a time. It is the Master that initiates data transfer. When the Master executes this instruction: SPDR = 0x23;, 8 clock pulses are automatically generated on the SCK line.

(2) Data exchange is simultaneous. When the Master executes this code: SPDR = 0x23;, the data byte 23 (00100011) with MSBit first starts moving towards Slave and at the same time the content of SPDR Register of Slave (whatever is there) starts moving towards Master. If bit transfer rate is 125 kbits/sec, then the SPDR Registers of both Master and Slave will be updated after this time: 64 µs (1/125000*8). When data of Master arrives at the Slave, the SPIF flag of SPSR Register becomes HIGH and the same is true for Master. Therefore, both Master and Slave have to wait until their SPIF flags become HIGH and then read the data from SPDR Register into a variable. The Master will naturally execute these codes:

SPDR = 0x23;
while(bitRead(SPSR, SPIF) != HIGH)
{
   ;
}   

bitSet(SPSR, SPIF); //clear the flag bit
byte x = SPDR;       //x contains that has come from Slave

The above codes are equivalent to the following Arduino code:

byte x = SPI.transfer(0x23);

4. Now, Master is sending a command byte (0x01) at 2-sec interval which the Slave will recognize and then the Slave will put myTemp1 data on its SPI Port. Master will collect the data from its SPI Port, format/convert them as necessary and then will show on its Serial Monitor (SM1).
(1) Upload the following sketch into NANO -- the SPI Master )command byte is not yet implemented)

#include <SPI.h>
byte myData[4] = {0x12, 0xEF, 0xCD, 0xAB};

union
{
  float rxmyTemp;
  byte rxmyTempArray[4];
} data1, data2;

void setup (void)
{
  Serial.begin(9600);
  SPI.begin ();
  digitalWrite(SS, LOW);    //Slave is selected
  delay(100);
  SPI.setClockDivider(SPI_CLOCK_DIV128);  //500 Kbits/sec
}

void loop()
{
  SPI.transfer(myData, sizeof(myData));
  data1.rxmyTempArray[3] = myData[0]; //12345678
  data1.rxmyTempArray[0] = myData[1];
  data1.rxmyTempArray[1] = myData[2];
  data1.rxmyTempArray[2] = myData[3];

  // Serial.println(data.x, HEX);    //binary32 formatted 32-bit receibed from Slave
  Serial.print("Temperature1 from DHT22: ");
  Serial.print(data1.rxmyTemp, 2);
  Serial.println(" *C");
  delay(2000);
}

(2) Upload the following sketch into UNO -- the SPI Slave

#include "DHT.h"
#include <SPI.h>
volatile bool flag1 = false;
volatile int i = 0;
//volatile byte myData[4] = {0x78, 0x56, 0x34, 0x12};
#define DHTPIN1 A2     // what pin we're connected to
#define DHTTYPE1 DHT22   // DHT 22  (AM2302)
float myTemp1;
float myTemp2;

union
{
  float txmyTemp;
  byte txmyTempArray[4];
} data1, data2;

DHT dht1(DHTPIN1, DHTTYPE1);

void setup()
{
  Serial.begin(9600);
  dht1.begin();
  analogReference(INTERNAL);
  //-------------------------
  pinMode(SS, INPUT_PULLUP);  // ensure SS stays high for now
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);
  SPCR |= !(_BV(MSTR)); //Arduino is Slave
  SPCR |= _BV(SPIE);
//  SPDR = 0x67;
  //SPI.attachInterrupt();  // SPCR |= _BV(SPIE);
}

void loop()
{
  tempDht1();
  tempLM35();
  Serial.println("=====================");
  delay(1000);
  //Serial.println(data1.txmyTempArray[2], HEX); debugging
  //Serial.println(data2.txmyTempArray[2], HEX);
}

void tempDht1()
{
  myTemp1 = dht1.readTemperature();
  Serial.print("Temperature1: ");
  Serial.print(myTemp1, 2);
  Serial.println(" *C");
  //-----------------------
  data1.txmyTemp = myTemp1;
}

void tempLM35()
{
  myTemp2 = (float)100 * (1.1 / 1023.0) * analogRead(A3);
  Serial.print("Temperature2: ");
  Serial.print(myTemp2, 2);
  Serial.println(" *C");
  //-----------------------
  data2.txmyTemp = myTemp2;
}

ISR(SPI_STC_vect)
{
  SPDR = data1.txmyTempArray[i];
  i++;
  if (i == 4)
  {
    i = 0;
  }
}

Screenshot(NANO shows received temperature1)
smRxDht.png

nanoUnoDhLM.png

(3) Add necessary codes with NANO sketch and UNO sketch so that the exchange of both temperature1 and temperature2 signals from both sensors of Slave can take place. (see Post#15).

(4) Practice with this working program for the implementation of the command byte.

spix.png

smdht22.png

spi328x.png

smRxDht.png

nanoUnoDhLM.png

smboth.png

:slight_smile: THANK YOU VERY MUCH !!!!!!!

Best Regards

Adrian

Please, do share your codes and works with us for educational purposes.

:slight_smile: Yes of course, I'm very glad with your support. When I finish my tests, I'll upload the functional codes.

By the way, last nigth I'll be working trying to check HOW FAR AWAY I'll be able to put the MASTER and SLAVE, and make some kinds of test.

In short period of time, with NickGammon's code with structure, I transfer and receive SIX of the NINE byte that I wanted to SEND from Master to SLAVE, the rest was garbage.

I know that long distance is not possible, but how far ???
It's depend of the type of wire, and another cupples of variables, but, as I said in the first post, I'm new with ARDUINO and electronics.

Tonight, I'll check the code your are posted, and try to get the temperature of DHT11 (1 and 2) from two distance wires far away seven meters from SLAVE, and at least 1 meter from MASTER. If you ask why?

It's simple for me, for a DIY purpose, at least you have two alternatives:

  1. Proyect over the desk, with a protoboard as a scale
  2. Proyect over the wall of the kitchen, one 7m in front of the second one. One termometer Inside, and the other Outside.
  3. Master & Slave inside a durlock wall, and Touch Screen TFT 2.4" mcufriend to view Main Menu, that you could select what to see, for example:
    a) Temperatures & Humidity
    b) Timer for cooking
    c) Cronometer
    d) Real Time (RTC 3231)
    e) Alarms
    f) Sound alarms (means buzzer)
    g) Movement detected with PIR installed outside
    All of them working, stand alone.

But 32 KB, and 20 pins are really LESS than I need, but I'm doing my best.

Again, I'm apologize for my English, or if the code is not professional, but I'm trying to learn while make a hobby, on my free time.

Adrian

GolamMostafa:
(3) Add necessary codes with NANO sketch and UNO sketch so that the exchange of temperature1 and temperature2 signals from from both sensors of Slave can take place. (see Post#15).

NANO-SPIMaster Codes

#include <SPI.h>
byte myData[] = {0x12, 0xEF, 0xCD, 0xAB, 0x12, 0xEF, 0xCD, 0xAB};

union
{
  float rxmyTemp;
  byte rxmyTempArray[4];
} data1, data2;

void setup (void)
{
  Serial.begin(9600);
  SPI.begin ();
  digitalWrite(SS, LOW);    //Slave is selected
  delay(100);
  SPI.setClockDivider(SPI_CLOCK_DIV128);  //500 Kbits/sec
}

void loop()
{
  //SPI.transfer(0x01);
  SPI.transfer(myData, sizeof(myData));
  data1.rxmyTempArray[3] = myData[0]; 
  data1.rxmyTempArray[0] = myData[1];
  data1.rxmyTempArray[1] = myData[2];
  data1.rxmyTempArray[2] = myData[3];

  data2.rxmyTempArray[3] = myData[4]; 
  data2.rxmyTempArray[0] = myData[5];
  data2.rxmyTempArray[1] = myData[6];
  data2.rxmyTempArray[2] = myData[7];

  // Serial.println(data.x, HEX);    //binary32 formatted 32-bit receibed from Slave
  Serial.print("Temperature1 from DHT22: ");
  Serial.print(data1.rxmyTemp, 2);
  Serial.println(" *C");
  Serial.print("Temperature2 from LM35: ");
  Serial.print(data2.rxmyTemp, 2);
  Serial.println(" *C");
  Serial.println("==================================");
  delay(2000);
}

UNO-SPISlave Codes

#include "DHT.h"
#include <SPI.h>
volatile bool flag1 = false;
volatile int i = 0, j = 0;
//volatile byte myData[4] = {0x78, 0x56, 0x34, 0x12};
#define DHTPIN1 A2     // what pin we're connected to
#define DHTTYPE1 DHT22   // DHT 22  (AM2302)
float myTemp1;
float myTemp2;
byte dataArray[8];
union
{
  float txmyTemp;
  byte txmyTempArray[4];
} data1, data2;

DHT dht1(DHTPIN1, DHTTYPE1);

void setup()
{
  Serial.begin(9600);
  dht1.begin();
  analogReference(INTERNAL);
  //-------------------------
  pinMode(SS, INPUT_PULLUP);  // ensure SS stays high for now
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);
  SPCR |= !(_BV(MSTR)); //Arduino is Slave
  SPCR |= _BV(SPIE);
  //  SPDR = 0x67;
  //SPI.attachInterrupt();  // SPCR |= _BV(SPIE);
}

void loop()
{
  tempDht1();
  tempLM35();
  for (int i = 0; i < 4; i++)
  {
    dataArray[i] = data1.txmyTempArray[i];
  }

  for (int i = 4, j = 0; i < 8, j < 4; i++, j++)
  {
    dataArray[i] = data2.txmyTempArray[j];
  }
  Serial.println("=====================");
  delay(1000);
  //Serial.println(data1.txmyTempArray[2], HEX); debugging
  //Serial.println(data2.txmyTempArray[2], HEX);
}

void tempDht1()
{
  myTemp1 = dht1.readTemperature();
  Serial.print("Temperature1: ");
  Serial.print(myTemp1, 2);
  Serial.println(" *C");
  //-----------------------
  data1.txmyTemp = myTemp1;
}

void tempLM35()
{
  myTemp2 = (float)100 * (1.1 / 1023.0) * analogRead(A3);
  Serial.print("Temperature2: ");
  Serial.print(myTemp2, 2);
  Serial.println(" *C");
  //-----------------------
  data2.txmyTemp = myTemp2;
}

ISR(SPI_STC_vect)
{
  SPDR = dataArray[j];
  j++;
  if (j == 8)
  {
    j = 0;
  }
}

Screenshot(NANO-SPIMaster)
smboth.png

smboth.png