Spi on arduino nano

hello there
I am trying to program a slave and Master with a arduino Nano.
the communication is via SPI
the slave does a reading on one analog port.

The master reads this value with two instructions.

till now the readings are instable.

code slave:

#include <SPI.h>

const int SS_PIN = 2; // Pin voor Slave Select (SS)
volatile bool ssLowDetected = false;
volatile int dataToSend = 5; // Data die we willen verzenden
float counter = 0;

void setup() {
  pinMode(MISO, OUTPUT);  // MISO als uitgang
  //pinMode(SS_PIN, INPUT_PULLUP); // SS als ingang (met pull-up weerstanden)
  pinMode(SS_PIN, INPUT); // SS als ingang (met pull-up weerstanden)
 // pinMode(LED_BUILTIN,OUTPUT);  // sets onBoard LED as output
  
  SPCR |= _BV(SPE);       // SPI als Slave inschakelen
  
  // Externe interrupt instellen op de SS-pin
  attachInterrupt(digitalPinToInterrupt(SS_PIN), onSSLow, FALLING);

  Serial.begin(9600);
  Serial.println("SPI Slave gestart");
}

void loop() 
{ 
  if (ssLowDetected)
  {
    Serial.println("SPI ss is low");
    // Laad de data in SPDR om het klaar te maken voor verzending
    
    //SPDR = (dataToSend >> 8) & 0xFF; // MSB verzenden
    SPDR = 5;
    while (!(SPSR & _BV(SPIF)));     // Wacht op transmissie
    
    //SPDR = dataToSend & 0xFF;        // LSB verzenden
    SPDR = 10;
    
    ssLowDetected = false; // Reset de vlag
    Serial.println("Data verzonden op SS-laag");
  }
  Serial.print("Counter: ");
  Serial.println(counter);
  if ( counter > 100000)
  {
    counter = 0;
  }
  delay(1000);
  
}

// Interrupt Service Routine (ISR) voor SS laag
void onSSLow() 
{
  counter ++;
  //Serial.println("SPI ss is low");
  ssLowDetected = true; // Zet de vlag voor de hoofdloop
}
<CODE/>
code master
<CODE/>
#include <SPI.h>

const int slaveSelectPin = 10;//nano uno
//const int slaveSelectPin = 53;//mega
/*
pins spi on nano/uno
MISO pin 12 
MOSI pin 11
SCK pin 13
SS pin 10

pins spi on mega
MISO pin 50
MOSI pin 51
SCK pin 52
SS pin 53
 */
void setup() 
{
 // analogReadResolution(12);
  Serial.begin(9600);
  pinMode(slaveSelectPin, OUTPUT); // Zet SS pin als uitgang
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(slaveSelectPin, HIGH); // Houd slave inactief
  SPI.begin();                       // Start SPI in master-modus
}

void loop()
{
   
  //Select the slave and asks low byte
  digitalWrite(LED_BUILTIN,HIGH);
  digitalWrite(slaveSelectPin, LOW);
 
  //just for test
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  byte highByte = SPI.transfer(0x00);
  byte lowByte = SPI.transfer(0x00);
  digitalWrite(LED_BUILTIN,LOW   );
  digitalWrite(slaveSelectPin, HIGH);
  SPI.endTransaction();

  // Combineer highByte en lowByte tot de originele analoge waarde
  int analogValue = (highByte << 8) | lowByte;

  // Show the received value
  Serial.print("The value ise: ");
  Serial.println(analogValue);


  delay(500);//rest a little bit
}

<CODE/> is a button in the composer window on the forum, not a text that you type in.

Code tags are three back ticks (```) on their own line at the beginning and the end of the code block; that is basically what the <CODE/> button does. I've fixed the code tags for you.

float counter = 0;
This value is changed in the isr and should be volatile. There is no reason for it not to be an unsigned long integer.

What does this mean exactly?

Your MEGA is SPI-Master and NANO is SPI-Slave.
NANO acquires analog signal and sends it to Master on demanded.

1. Connection Diagram between Master and Slave (Fig-1).


Figure-1:

2. Upload the following Master (SPI-MEGA) Sketch to receive two bytes (0xABCD) data from Slave.

#include<SPI.h>
int y = 0x1234;

void setup()
{
  Serial.begin(9600);
  SPI.begin();  //default speed: 4 Mbits/sec
  digitalWrite(SS, LOW);   //Slave is enabled
}

void loop()
{
  byte y1 = SPI.transfer(highByte(y));
  delayMicroseconds(10);  //must be
  byte y2 = SPI.transfer(lowByte(y));
  delayMicroseconds(10);  //must be
  //--------------------------------
  int recInt = y2 << 8 | y1;
  Serial.println((uint16_t)recInt, HEX);
  delay(1000);
}

3. Upload the following Slave (SPI-NANO) Sketch to receive 2-byte (0x1234) data from Master.

#include<SPI.h>

byte txData[] = {0xAB, 0xCD};
byte rxData[2];
volatile bool flag = false;
int i = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(SS, INPUT_PULLUP);
  pinMode(MISO, OUTPUT);
  bitClear(SPCR, MSTR);  //UNO-2 is Slave
  bitSet(SPCR, SPE);  //SPI Port is created
  SPI.attachInterrupt();  //LIE, GIE are active
}

void loop()
{
  if (flag == true)
  {
    Serial.print("Received Data: ");
    Serial.print(rxData[0], HEX);
    Serial.println(rxData[1], HEX);
    //------------------------------
    flag = false;
  }
}

ISR(SPI_STC_vect)
{
  rxData[i] = SPDR;
  SPDR = txData[i];
  i++;
  if (i == 2)
  {
    i = 0;
    flag = true;
  }
}

4. Open Serial Monitor (SM) of SPI-Master.
5. Open Serial Monitor of SPI-Slave.
6. Press and Hold REST uttons of both Arduino.
7. Release RESET utton of Slave.
8. Release RESET Button of Master.
9. Check that SM of Master shows ABCD at 1-sec interval.

ABCD
ABCD
ABCD

10. Check that SM of Slave shows 1234 at 1-sec interval.

Received Data: 1234
Received Data: 1234
Received Data: 1234

11. Now modify Slave sketch to acquire 2-byte data from the Pot of Slave and send them to SPI-Master.
Hints:

byte txData[2];

void loop()
{
     int y1 = analogRead(A0);
     txData[0] = highByte(y1);
     txData[1] = lowByte(y1);
}

thanks for your respond

the problem is that the slave does not give the right value.
it seems that the signal on the mosi comes back on the miso.

code master

byte highByte = SPI.transfer(0x00);
byte lowByte = SPI.transfer(0x00);

if I change this to

byte highByte = SPI.transfer(0x01);
byte lowByte = SPI.transfer(0x05);

I can see that those values comes back.
I have a small usb scope to check the signals.

Do you have better code for the slave for me?
thanks in advance.

Jos

See post #4 for the Master Sketch and Slave Sketch which have been tesed.

Thanks Golam

it works with a Mega and a Nano as Slave.

Blockquote

digitalWrite(SS, LOW); //Slave is enabled
byte y1 = SPI.transfer(highByte(y));
delayMicroseconds(10); //must be
byte y2 = SPI.transfer(lowByte(y));
delayMicroseconds(10); //must be
//--------------------------------
int recInt = y2 << 8 | y1;
Serial.println((uint16_t)recInt, HEX);
digitalWrite(SS, HIGH); //Slave is enabled
delay(1000);


After transmission I set SS High for better syncronisation
do you know if there is code for a esp 32 for the same purpose?

Please use code tags correctly.

You start a code block with three back ticks (```) and end it with three back ticks (```); they need to be on their own line.

FYI, the first one can have added options but we will not be critical on that.

  • ```cpp for cpp code
  • ```text for text (e.g. output from serial monitor)

And more.

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