0% found this document useful (0 votes)
40 views

ESP32_Communication

Uploaded by

Malick THIAM
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views

ESP32_Communication

Uploaded by

Malick THIAM
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

ESP32 SPI Communication: Set Pins,

Multiple SPI Bus Interfaces, and


Peripherals (Arduino IDE)
This is a simple guide about SPI communication protocol with the ESP32 using Arduino IDE.
We’ll take a look at the ESP32 SPI pins, how to connect SPI devices, define custom SPI pins,
how to use multiple SPI devices, and much more.

Table of Contents:
 Introducing ESP32 SPI Communication Protocol
 ESP32 SPI Peripherals
 ESP32 SPI Pins
 Using Custom ESP32 SPI Pins
 ESP32 with Multiple SPI Devices
 Multiple SPI Devices (same bus, different CS pin)
 Using Two SPI Bus Interfaces (use HSPI and VSPI simultaneously)
This tutorial focus on programming the ESP32 using the Arduino core, so before proceeding,
you should have the ESP32 add-on installed in your Arduino IDE. Follow the next tutorial to
install the ESP32 on the Arduino IDE, if you haven’t already.

 Installing the ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux
instructions)
Alternatively, you can also use VS Code with the PlatformIO extension to program your
boards using the Arduino core:

 Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266
(Windows, Mac OS X, Linux Ubuntu)
Introducing ESP32 SPI
Communication Protocol
SPI stands for Serial Peripheral Interface, and it is a synchronous serial data protocol used by
microcontrollers to communicate with one or more peripherals. For example, your ESP32
board communicating with a sensor that supports SPI or with another microcontroller.
In an SPI communication, there is always a controller (also called master) that controls
the peripheral devices (also called slaves). Data can be sent and received simultaneously.
This means that the master can send data to a slave, and a slave can send data to the master at
the same time.

You can have only one master, which will be a microcontroller (the ESP32), but you can have
multiple slaves. A slave can be a sensor, a display, a microSD card, etc., or another
microcontroller. This means you can have an ESP32 connected to multiple sensors, but the
same sensor can’t be connected to multiple ESP32 boards simultaneously.

SPI Interface
For SPI communication you need four lines:

 MISO: Master In Slave Out


 MOSI: Master Out Slave In
 SCK: Serial Clock
 CS /SS: Chip Select (used to select the device when multiple peripherals are used on
the same SPI bus)
On a slave-only device, like sensors, displays, and others, you may find a different
terminology:

 MISO may be labeled as SDO (Serial Data Out)


 MOSI may be labeled as SDI (Serial Data In)

ESP32 SPI Peripherals


The ESP32 integrates 4 SPI peripherals: SPI0, SPI1, SPI2 (commonly referred to as HSPI),
and SPI3 (commonly referred to as VSPI).
SP0 and SP1 are used internally to communicate with the built-in flash memory, and you
should not use them for other tasks.

You can use HSPI and VSPI to communicate with other devices. HSPI and VSPI have
independent bus signals, and each bus can drive up to three SPI slaves.

ESP32 Default SPI Pins


Many ESP32 boards come with default SPI pins pre-assigned. The pin mapping for most
boards is as follows (it is different for an ESP32-S3):
SPI MOSI MISO SCLK CS

VSPI GPIO 23 GPIO 19 GPIO 18 GPIO 5

HSPI GPIO 13 GPIO 12 GPIO 14 GPIO 15


Warning: depending on the board you’re using, the default SPI pins might be different. So,
make sure you check the pinout for the board you’re using. Additionally, some boards don’t
have pre-assigned SPI pins, so you need to set them on code.
Note: usually, when not specified, the board will use the VSPI pins when initializing an SPI
communication with the default settings.
Whether your board comes with pre-assigned pins or not, you can always set them on code.

Finding your ESP32 Board’s Default SPI Pins


If you’re not sure about your board’s default SPI pins, you can upload the following code to
find out.

/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-
spi-communication-arduino/

Permission is hereby granted, free of charge, to any person


obtaining a copy
of this software and associated documentation files.

The above copyright notice and this permission notice shall be


included in all
copies or substantial portions of the Software.
*/

//Find the default SPI pins for your board


//Make sure you have the right board selected in Tools > Boards
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.print("MOSI: ");
Serial.println(MOSI);
Serial.print("MISO: ");
Serial.println(MISO);
Serial.print("SCK: ");
Serial.println(SCK);
Serial.print("SS: ");
Serial.println(SS);
}

void loop() {
// put your main code here, to run repeatedly:
}
View raw code
Important: make sure you select the board you’re using in Tools > Board, otherwise, you
may not get the right pins.
After uploading the code, open the Serial Monitor, RST your board and you’ll see the SPI
pins.

Using Custom ESP32 SPI Pins


When using libraries to interface with your SPI peripherals, it’s usually simple to use custom
SPI pins because you can pass them as arguments to the library constructor.
For example, take a quick look at the following example that interfaces with a BME280
sensor using the Adafruit_BME280 library.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-
spi-communication-arduino/
Based on the Adafruit_BME280_Library example:
https://github.com/adafruit/Adafruit_BME280_Library/blob/master/exam
ples/bme280test/bme280test.ino

Permission is hereby granted, free of charge, to any person


obtaining a copy
of this software and associated documentation files.

The above copyright notice and this permission notice shall be


included in all
copies or substantial portions of the Software.
*/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#include <SPI.h>
#define BME_SCK 25
#define BME_MISO 32
#define BME_MOSI 26
#define BME_CS 33
#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C


//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); //
software SPI

unsigned long delayTime;

void setup() {
Serial.begin(9600);
Serial.println(F("BME280 test"));

bool status;

// default settings
// (you can also pass in a Wire library object like &Wire2)
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check
wiring!");
while (1);
}

Serial.println("-- Default Test --");


delayTime = 1000;

Serial.println();
}

void loop() {
printValues();
delay(delayTime);
}

void printValues() {
Serial.print("Temperature = ");
Serial.print(bme.readTemperature());
Serial.println(" *C");

// Convert temperature to Fahrenheit


/*Serial.print("Temperature = ");
Serial.print(1.8 * bme.readTemperature() + 32);
Serial.println(" *F");*/

Serial.print("Pressure = ");
Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");

Serial.print("Approx. Altitude = ");


Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");

Serial.print("Humidity = ");
Serial.print(bme.readHumidity());
Serial.println(" %");

Serial.println();
}
View raw code
You can easily pass your custom SPI pins to the library constructor.

Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);


In that case, I was using the following SPI pins (not default) and everything worked as
expected:

#define BME_SCK 25
#define BME_MISO 32
#define BME_MOSI 26
#define BME_CS 33
If you’re not using a library, or the library you’re using doesn’t accept the pins in the library
constructor, you may need to initialize the SPI bus yourself. In that case, you would need to
call the SPI.begin() method on the setup() and pass the SPI pins as arguments:
SPI.begin(SCK, MISO, MOSI, SS);
You can see an example of this scenario in this tutorial, in which we initialize an SPI LoRa
transceiver that is connected to custom SPI pins. Or this example showing how to use custom
SPI pins with a microSD card module.

ESP32 with Multiple SPI Devices


As we’ve seen previously, you can use two different SPI buses on the ESP32 and each bus
can connect up to three different peripherals. This means that we can connect up to six SPI
devices to the ESP32. If you need to use more, you can use an SPI multiplexer.

Multiple SPI Devices (same bus, different CS pin)


To connect multiple SPI devices, you can use the same SPI bus as long as each peripheral
uses a different CS pin.

To select the peripheral you want to communicate with, you should set its CS pin to LOW. For
example, imagine you have peripheral 1 and peripheral 2. To read from peripheral 1, make
sure its CS pin is set to LOW (here represented as CS_1):
digitalWrite(CS_1, LOW); // enable CS pin to read from peripheral 1

/*
use any SPI functions to communicate with peripheral 1
*/
Then, at same point, you’ll want to read from peripheral 2. You should disable peripheral
1 CS pin by setting it to HIGH, and enable peripheral 2 CS pin by setting it to LOW:
digitalWrite(CS_1, HIGH); // disable CS pin from peripheral 1
digitalWrite(CS_2, LOW); // enable CS pin to read from peripheral 2

/*
use any SPI functions to communicate with peripheral 2
*/

ESP32 Using Two SPI Bus Interfaces (Use HSPI and VSPI
simultaneously)
To communicate with multiple SPI peripherals simultaneously, you can use the ESP32 two
SPI buses (HSPI and VSPI). You can use the default HSPI and VSPI pins or use custom pins.

Briefly, to use HSPI and VSPI simultaneously, you just need to.

1) First, make sure you include the SPI library in your code.
#include <SPI.h>
2) Initialize two SPIClass objects with different names, one on the HSPI bus and another
on the VSPI bus. For example:
vspi = new SPIClass(VSPI);
hspi = new SPIClass(HSPI);
3) Call the begin() method on those objects.
vspi.begin();
hspi.begin();
You can pass custom pins to the begin() method if needed.
vspi.begin(VSPI_CLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
hspi.begin(HSPI_CLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
4) Finally, you also need to set the SS pins as outputs. For example:
pinMode(VSPI_SS, OUTPUT);
pinMode(HSPI_SS, OUTPUT);
Then, use the usual commands to interact with the SPI devices, whether you’re using a sensor
library or the SPI library methods.

You can find an example of how to use multiple SPI buses on the arduino-esp32 SPI library.
See the example below:

/* The ESP32 has four SPi buses, however as of right now only two of
* them are available to use, HSPI and VSPI. Simply using the SPI
API
* as illustrated in Arduino examples will use VSPI, leaving HSPI
unused.
*
* However if we simply initialize two instance of the SPI class for
both
* of these buses both can be used. However when just using these
the Arduino
* way only will actually be outputting at a time.
*
* Logic analyzer capture is in the same folder as this example as
* "multiple_bus_output.png"
*
* created 30/04/2018 by Alistair Symonds
*/
#include <SPI.h>

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

#ifdef ALTERNATE_PINS
#define VSPI_MISO 2
#define VSPI_MOSI 4
#define VSPI_SCLK 0
#define VSPI_SS 33

#define HSPI_MISO 26
#define HSPI_MOSI 27
#define HSPI_SCLK 25
#define HSPI_SS 32
#else
#define VSPI_MISO MISO
#define VSPI_MOSI MOSI
#define VSPI_SCLK SCK
#define VSPI_SS SS

#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_SCLK 14
#define HSPI_SS 15
#endif

#if !defined(CONFIG_IDF_TARGET_ESP32)
#define VSPI FSPI
#endif

static const int spiClk = 1000000; // 1 MHz

//uninitialized pointers to SPI objects


SPIClass *vspi = NULL;
SPIClass *hspi = NULL;

void setup() {
//initialize two instances of the SPIClass attached to VSPI and
HSPI respectively
vspi = new SPIClass(VSPI);
hspi = new SPIClass(HSPI);

//clock miso mosi ss

#ifndef ALTERNATE_PINS
//initialize vspi with default pins
//SCLK = 18, MISO = 19, MOSI = 23, SS = 5
vspi->begin();
#else
//alternatively route through GPIO pins of your choice
vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS); //SCLK,
MISO, MOSI, SS
#endif

#ifndef ALTERNATE_PINS
//initialize hspi with default pins
//SCLK = 14, MISO = 12, MOSI = 13, SS = 15
hspi->begin();
#else
//alternatively route through GPIO pins
hspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_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->pinSS(), OUTPUT); //VSPI SS
pinMode(hspi->pinSS(), OUTPUT); //HSPI SS
}

// the loop function runs over and over again until power down or
reset
void loop() {
//use the SPI buses
spiCommand(vspi, 0b01010101); // junk data to illustrate usage
spiCommand(hspi, 0b11001100);
delay(100);
}

void spiCommand(SPIClass *spi, byte data) {


//use it as you would the regular arduino SPI API
spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end
for transfer
spi->transfer(data);
digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end
of data transfer
spi->endTransaction();
}
View raw code

Wrapping Up
This article was a quick and simple guide showing you how to use SPI communication with
the ESP32 using the Arduino core—with the ESP32 acting as a controller (master).
In summary, the ESP32 has four SPI buses, but only two can be used to control peripherals,
the HSPI and VSPI. Most ESP32 have pre-assigned HSPI and VSPI GPIOs, but you can
always change the pin assignment in the code.

You can use the HSPI and VSPI buses simultaneously to drive multiple SPI peripherals, or
you can use multiple peripherals on the same bus as long as their CS pin is connected to a
different GPIO.

We didn’t dive deeply into examples, because each sensor, library, and case scenario is
different. But, now you should have a better idea of how to interface one or multiple SPI
devices with the ESP32.

For more detailed information about the SPI Master driver on the ESP32, you can check the
espressif official documentation.
We didn’t cover setting the ESP32 as an SPI slave, but you can check these examples.
We hope you find this tutorial useful. We have a similar article, but about I2C communication
protocol. Check it out on the following link:

 ESP32 I2C Communication: Set Pins, Multiple Bus Interfaces and Peripherals
(Arduino IDE)
Learn more about the ESP32 with our resources:

 Learn ESP32 with Arduino IDE


 Build Web Servers with ESP32 and ESP8266
 Firebase Web App with ESP32 and ESP8266
 Free ESP32 Projects and Tutorials
Thanks for reading.

SMART HOME with Raspberry Pi, ESP32, ESP8266 [eBook]


Learn how to build a home automation system and we’ll cover the following main subjects:
Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB
database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino,
and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home
automation projects.
Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no
prior experience!

What to Read Next…

ESP32 Datalogger: Download Data File via Web Server (Arduino IDE)

ESP32: 26 Free Guides for Sensors and Modules

ESP32/ESP8266 MicroPython Web Server – Control Outputs

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy