2

I have two ESP32 cards. I want to set one of these cards as Master and the other as Slave and communicate via SPI. I have done this before on Arduino Uno, but I cannot do this on ESP32. Below are my Master and Slave codes that I have prepared simply. I can't get what I want in any way. Can anyone help?

Master Code:

#include <SPI.h>

#define CS_PIN 5  // Choose the appropriate pin for Chip Select (CS)

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

void loop() {
  char dataToSend = 'A';
  
  digitalWrite(CS_PIN, LOW); // Start communication with the slave
  SPI.transfer(dataToSend); // Send data to the slave
  digitalWrite(CS_PIN, HIGH); // End communication with the slave
  
  delay(2000); // Delay for demonstration purposes
}

Slave Code:

#include <SPI.h>

#define CS_PIN 5  // Choose the appropriate pin for Chip Select (CS)

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

void loop() {
  if (digitalRead(CS_PIN) == LOW) {  // Check if CS (Chip Select) is LOW, meaning the device is selected
    char receivedData = SPI.transfer(0); // Read received data from the master
    
    // Display received data on the serial monitor
    Serial.println("Received Data: " + String(receivedData));
    
    delay(1000);  // Optional delay for demonstration purposes
  }
}

New Code - New Problem:

I tried to adapt the codes at https://microcontrollerslab.com/esp32-spi-communication-tutorial-arduino/. From what I understand it uses the following pins for SPI: MISO-12; MOSI-13; SCLK-14; SS-15. I set my connections the same way, but I cannot get the output I expected from the Slave. It remains waiting at the slave.wait line.

Master Code:

#include <SPI.h>

// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus


  #define HSPI_MISO   MISO
  #define HSPI_MOSI   MOSI
  #define HSPI_SCLK   SCK
  #define HSPI_SS     SS

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * hspi = NULL;

void setup() {
  //initialise instance of the SPIClass attached to HSPI
  hspi = new SPIClass(HSPI);

  //initialise hspi with default pins
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  hspi->begin();

  pinMode(HSPI_SS, OUTPUT); //HSPI SS
}

// the loop function runs over and over again until power down or reset
void loop() {
  hspi_send_command();
  delay(100);
}

void hspi_send_command() {
  byte data_on = 0b00000001; // data 1 to turn on LED of slave
  byte data_off = 0b0000000; // data 0 to turn off LED of slave
  
  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(HSPI_SS, LOW);
  hspi->transfer(data_on);
  digitalWrite(HSPI_SS, HIGH);
  hspi->endTransaction();

  delay(1000);
  
  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(HSPI_SS, LOW);
  hspi->transfer(data_off);
  digitalWrite(HSPI_SS, HIGH);
  hspi->endTransaction();
  delay(1000);

}
*/

Slave Code:

#include <ESP32SPISlave.h>

ESP32SPISlave slave;

static constexpr uint32_t BUFFER_SIZE {32};
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];

#define LED 2

void setup() {
    Serial.begin(115200);
    delay(2000);
    pinMode(LED, OUTPUT);
    // begin() after setting
    // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12 -> default
    // VSPI = CS:  5, CLK: 18, MOSI: 23, MISO: 190
    slave.setDataMode(SPI_MODE0);
    slave.begin();
    // slave.begin(VSPI);   // you can use VSPI like this

    // clear buffers
    memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
    memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}

void loop() {
    // block until the transaction comes from master
    Serial.println("Initialize...");
    
    slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);

    Serial.println("*********************");

    // if transaction has completed from master,
    // available() returns size of results of transaction,
    // and buffer is automatically updated
    char data;
    while (slave.available()) {
        // show received data
         Serial.print("Command Received: ");
         Serial.println(spi_slave_rx_buf[0]);
         data = spi_slave_rx_buf[0];
         slave.pop();
    }
    if(data == 1 )
    {
        Serial.println("Setting LED active HIGH ");
        digitalWrite(LED, HIGH);
    }
    else if(data == 0 )
    {
        Serial.println("Setting LED active LOW ");
        digitalWrite(LED, LOW);
    }
}
0

2 Answers 2

2

For ESP32, unless the exact board variant is specified, by default the macros for MISO, MOSI, SCK and SS are defined as follows and are used for VSPI(i.e. SPI0):

static const uint8_t SS    = 5;
static const uint8_t MOSI  = 23;
static const uint8_t MISO  = 19;
static const uint8_t SCK   = 18;

This can be seen in the source code and HSPI is automatically configured to use SCLK 14, MISO 12, MOSI 13 and SS 15 when SPI.begin() is called, see this part of the source code.

Since you defined HSPI_SS as #define HSPI_SS SS, when you do pinMode(HSPI_SS, OUTPUT);, you are actually setting pin 5 as output, not the pin 15 that you thought it was.

There are two ways to properly set up the HSPI port.

  1. What you can do is to define the macros as follows and call hspi->begin(); by passing your configuration:
#define HSPI_MISO   12
#define HSPI_MOSI   13
#define HSPI_SCLK   14
#define HSPI_SS     15

void setup() {
  hspi = new SPIClass(HSPI);
  hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
  // rest of your setup code
}
  1. As you can see from the source code shown in the above link, if you don't explicitly pass the pins as parameters when calling SPI.begin(), the library will automatically assign the pins based on whether VSPI is used (SCLK 18, MISO 19, MOSI 23, SS 5), or HSPI is used (SCLK 14, MISO 12, MOSI 13 and SS 15). So all you need to define is your HSPI_SS pin:
#define HSPI_SS     15

void setup() {
  hspi = new SPIClass(HSPI);
  hspi->begin();
  // rest of your setup code
}
1
  • Thank you so much. I managed to send a string expression. Below you can see the Slave-Master codes that send messages from Master to Slave using the "Hello From Master" string.
    – Enes Orhan
    Nov 30, 2023 at 9:36
1

You can see the Slave-Master codes that send messages from Master to Slave using the "Hello From Master" string.

Master Code:

#include <SPI.h>

#ifdef ALTERNATE_PINS
  #define VSPI_MISO   19
  #define VSPI_MOSI   23
  #define VSPI_SCLK   18
  #define VSPI_SS     5
#else
  #define VSPI_MISO   MISO
  #define VSPI_MOSI   MOSI
  #define VSPI_SCLK   SCK
  #define VSPI_SS     SS
#endif

static const int spiClk = 1000000; // 1 MHz

char input;

const int size_arr = 25;
char buf[size_arr];
String sendData = "Hello from Master";

//uninitalised pointers to SPI objects
SPIClass* vspi = NULL;

void setup() {
    Serial.begin(115200);
    
    vspi = new SPIClass(VSPI);
    
#ifndef ALTERNATE_PINS
    vspi->begin();
#else
    vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
#endif

    pinMode(VSPI_SS, OUTPUT); //HSPI SS

    vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
}

void loop() {
    input = Serial.read();
    
    if(input == 's'){
      sendData.toCharArray(buf, size_arr);
      spi_transmis(VSPI_SS, buf);
    }
    delay(50);
}

void send_spi(int selectPin, byte pram) {
    digitalWrite(selectPin, LOW);
    vspi->transfer(pram);
    digitalWrite(selectPin, HIGH); 
    vspi->endTransaction();
    delayMicroseconds(75);
}

void spi_transmis(int selectPin, char buf[]) {
  for (int i = 0; i < size_arr; i++) {
    send_spi(selectPin, buf[i]);
  }
  send_spi(selectPin, '\n');
}

Slave Code:

#include <ESP32SPISlave.h>

ESP32SPISlave slave;

static constexpr uint32_t BUFFER_SIZE { 1 };
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];

const int size_arr = 151;
char buf[size_arr];

volatile int pos = 0;
volatile bool active;
volatile bool process;

String received;

void setup() {
    Serial.begin(115200);
    slave.setDataMode(SPI_MODE0);
    slave.begin(VSPI);

    memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
    memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}

void loop() {
    recvHandle();
    spiHandler();
}

void spiHandler() {
  slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);
    
  while (slave.available()) {
      char c = spi_slave_rx_buf[0];
      if (c == '\n') {
        buf[pos] = '\0';
        process = true;
      } else {
        buf[pos++] = c;
      }
      slave.pop();
  }
}

void recvHandle() {
  if (process) {
    received = String(buf);
    process = false;
    pos = 0;
    Serial.println(received);
    delayMicroseconds(20);
  }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.