Author Topic: SPI communication problem with two ESP32  (Read 2343 times)

0 Members and 1 Guest are viewing this topic.

Offline fedimakniTopic starter

  • Regular Contributor
  • *
  • Posts: 63
  • Country: tn
SPI communication problem with two ESP32
« on: September 24, 2022, 03:49:52 am »
Hello,

I am currently trying to implement an SPI communication between 2 ESP32 using arduino IDE but i am facing a problem.

I set 1 as a master using the normal SPI library and the second one as slave using ESP32SPISlave.

Master SW is basically writing 0 or 1 to slave device and wait for a response

if the master send a 0 the slave will send back 2 in the next communication,

if the master send 1 the slave will send back 1 in the next communication.

the problem that sometimes even if the master send 1 i receive the number 2 instead of 1 so it seems that it doesn't override the previous value.

I am not sure exactly what's the problem. could you please support me?

I will paste both SW

You can find the picture of the issue in the link below

https://drive.google.com/file/d/1K08ntvOcR7fH9SyWb-RZu7XXCOKP2msH/view?usp=sharing

Master SW

Code: [Select]

#include <SPI.h>

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

#ifdef ALTERNATE_PINS
  #define VSPI_MISO   26
  #define VSPI_MOSI   27
  #define VSPI_SCLK   25
  #define VSPI_SS     32
#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

int data1;

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

void setup() {
  Serial.begin(115200);
    delay(2000);
  //initialise instance of the SPIClass attached to HSPI
  vspi = new SPIClass(VSPI);
 
  //clock miso mosi ss
#ifndef ALTERNATE_PINS
  //initialise hspi with default pins
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  vspi->begin();
#else
  //alternatively route through GPIO pins
  vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS); //SCLK, MISO, MOSI, SS
#endif

  //set up slave select pins as outputs as the Arduino API
  //doesn't handle automatically pulling SS low
  pinMode(VSPI_SS, OUTPUT); //HSPI SS
}

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

void vspi_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
 
  vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(VSPI_SS, LOW);
  data1 = vspi->transfer(data_on);
  digitalWrite(VSPI_SS, HIGH);
  vspi->endTransaction();
  Serial.print("data sent is 1 and data received is ");
  Serial.println(data1);
  delay(1000);
 
  vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(VSPI_SS, LOW);
  data1 = vspi->transfer(data_off);
  digitalWrite(VSPI_SS, HIGH);
  vspi->endTransaction();
  Serial.print("data sent is 0 and data received is ");
  Serial.println(data1);
  delay(1000);

}


Slave SW

Code: [Select]

#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: 19
    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
    slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);

    // 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);
        memset(spi_slave_tx_buf, 1, BUFFER_SIZE);
    }
    else if(data == 0 )
    {
        Serial.println("Setting LED active LOW ");
        digitalWrite(LED, LOW);
        memset(spi_slave_tx_buf, 2, BUFFER_SIZE);
    }
     Serial.println("");
}


Thank you again for your cooperation.

 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3036
  • Country: us
Re: SPI communication problem with two ESP32
« Reply #1 on: September 24, 2022, 04:37:00 am »
In your slave code try replacing:

Code: [Select]
    char data;

with:

Code: [Select]
    char data = 3;

The point is that you are potentially using an uninitialized value. Suppose that slave.wait() returns but there aren't any transactions to process. Then the variable data will contain an uninitialized value which could possibly screw things up.

You could also add a final else clause to the if-else block that checks the value of data to see if this ever happens:

Code: [Select]
    else { // data is not 0 or 1
        Serial.println("*** data is not 0 or 1 ***")
    }
 

Offline fedimakniTopic starter

  • Regular Contributor
  • *
  • Posts: 63
  • Country: tn
Re: SPI communication problem with two ESP32
« Reply #2 on: September 24, 2022, 05:02:00 am »
Thank you very much for the response.
but i think the problem comes from the master because the data received back in the master is what contain the error
initializing "data" will just fix the first iteration but the problem happened during the execution of the SW as you can see in the picture (link attached in the main post)
I was really thinking that it's a timing issue but i couldn't figure it out  :-//
 

Offline fedimakniTopic starter

  • Regular Contributor
  • *
  • Posts: 63
  • Country: tn
Re: SPI communication problem with two ESP32
« Reply #3 on: September 24, 2022, 05:33:17 am »
I checked something right now,
I actually found that i receive the number 2 in the slave when i only send 0 or 1 something weird but i don't know how to fix it.
Do you have an idea?
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5913
  • Country: es
Re: SPI communication problem with two ESP32
« Reply #4 on: September 24, 2022, 08:12:03 am »
Or use static char data, so it holds the value.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline fedimakniTopic starter

  • Regular Contributor
  • *
  • Posts: 63
  • Country: tn
Re: SPI communication problem with two ESP32
« Reply #5 on: September 24, 2022, 08:33:27 am »
That cannot help because actually i need that value to change depending on the received value. so static is not an option
 

Online rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: SPI communication problem with two ESP32
« Reply #6 on: September 24, 2022, 01:17:06 pm »
In the past, I noted that sometimes SS goes high before the last byte is completely transmitted.  I found it necessary to actually check that the byte had been transmitted and the output buffer empty before raising SS.
 
The following users thanked this post: fedimakni

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5913
  • Country: es
Re: SPI communication problem with two ESP32
« Reply #7 on: September 25, 2022, 01:26:28 am »
Static doesn't mean constant!
Basicaly it's initialized only once and its last value is always  kept.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline fedimakniTopic starter

  • Regular Contributor
  • *
  • Posts: 63
  • Country: tn
Re: SPI communication problem with two ESP32
« Reply #8 on: September 26, 2022, 02:56:13 am »
Do you have an idea how we can check that the SS went high before the last byte??
 

Offline JustMeHere

  • Frequent Contributor
  • **
  • Posts: 744
  • Country: us
Re: SPI communication problem with two ESP32
« Reply #9 on: September 26, 2022, 10:39:29 am »
Do you have an oscilloscope?  Need to see your signals.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: SPI communication problem with two ESP32
« Reply #10 on: September 26, 2022, 12:10:21 pm »
Code: [Select]
data1 = vspi->transfer(data_off);

This is your problem area.  This class method sends out 8 bits of data and simultaneously receives 8 bits of data.  The slave cannot determine what value to place in it's TX buffer until it's received and processed the data you have sent it, so it's impossible for your value returned by this function to be correct.

This is a general problem with SPI and some other synchronous protocols when implemented on a microcontroller, the master has to give sufficient turnaround time for the slave to process data it has received and form a response and get it ready for the master to read it.  Even with very fast micros there isn't typically enough time to do this in half an SPI clock cycle with highish SPI clock speeds (10-20MHz), so either you send dummy bytes during the turn around period, or you implement some kind of service request pin on the slave to let the master know data is ready for reading.

Note that in your SPI slave you have also committed the cardinal sin of putting printf functions in the receive handling code which will greatly slow the slave's response time.

As a simple but ugly proof of concept you could just repeat the SPI transfer after a suitable delay e.g.

Code: [Select]
data1 = vspi->transfer(data_off);
delay(10);
data1 = vspi->transfer(data_off);


By the time the second transfer method is run, the slave should have processed the value received from the first and put the correct value in it's TX buffer.  Using a delay like this is horribly ugly, you either have to use an excessively long delay, slowing down the SPI comms or do a bunch of work to find out the worst case times and repeat this whenever you change the code.  You should implement a better solution.
 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3036
  • Country: us
Re: SPI communication problem with two ESP32
« Reply #11 on: September 26, 2022, 01:09:45 pm »
Code: [Select]
data1 = vspi->transfer(data_off);

This is your problem area. ...

Hi mikerj, I don't think this is the problem. If you look at the google drive file the OP linked to in the first post you'll see that when a 1 is sent a 1 is received on the next transfer -- except in the circled area where you can see an instance of a 2 being returned instead.

Here's an excerpt:

Code: [Select]
...
data sent is 0 and data received is 1
data sent is 1 and data received is 2
data sent is 0 and data received is 2  <-- problem here
data sent is 1 and data received is 2
data sent is 0 and data received is 1
...

So one of the transfers glitched.
« Last Edit: September 26, 2022, 01:12:16 pm by ledtester »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf