Should I Use SPITransaction to Interface Multiple Peripherals?

Hi all!

Please let me know if this is the wrong area to post this question.

I am currently successfully running LVGL on a SPI TFT display and am attempting to integrate an RFID module as well. The RFID module works flawlessly by itself but does not function if I am using the TFT screen with LVGL:

I narrowed down the issue to the invocation of lv_tft_espi_create(). Removing this function restores all functionality to the RFID reader, but obviously I need the SPI settings to create the display object.

Is there anyway I can get both of these modules to work in tandem? Someone suggested I look into SPITransactions but I'm completely stumped on how to apply it correctly.

This is my, very bad, initial attempt at implementation.

#include <Arduino.h>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <MFRC522.h>
#include <SPI.h>

#define DRAW_BUF_SIZE (TFT_HOR_RES * TFT_VER_RES / 10 * (LV_COLOR_DEPTH / 8))
void *draw_buf;

TFT_eSPI tft = TFT_eSPI();

// Define SPI settings for TFT and RFID
SPISettings tftSPISettings(20000000, MSBFIRST, SPI_MODE0); // Matched the SPI_FREQUENCY in my TFT config: 20MHz
SPISettings rfidSPISettings(10000000, MSBFIRST, SPI_MODE0);

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

  SPI.beginTransaction(tftSPISettings); // BEGIN TFT SPI TRANSACTION

  lv_init();
  lv_tick_set_cb(lv_millis);

  draw_buf = heap_caps_malloc(DRAW_BUF_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  // This is the problematic line:
  lv_display_t *disp = lv_tft_espi_create(TFT_HOR_RES, TFT_VER_RES, draw_buf, DRAW_BUF_SIZE);
  lv_display_set_rotation(disp, LVGL_SCREEN_ROTATION);

  lv_indev_t *indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  lv_indev_set_read_cb(indev, my_touchpad_read);

  calibrateTouch();
  tft.fillScreen(TFT_BLACK);

  lv_obj_t *label = lv_label_create(lv_scr_act());
  lv_label_set_text(label, LVGL_Arduino.c_str());
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

  SPI.endTransaction(); // END TFT SPI TRANSACTION

  SPI.beginTransaction(rfidSPISettings); // BEGIN RFID SPI TRANSACTION
  mfrc522.PCD_Init();
  SPI.endTransaction(); // END RFID SPI TRANSACTION
}

void loop()
{
  SPI.beginTransaction(tftSPISettings); // BEGIN TFT SPI TRANSACTION
  lv_task_handler();
  SPI.endTransaction(); // END TFT SPI TRANSACTION
}

An member at the LVGL forum seemed to have some recommendations for me but I had some trouble following...

Any help would be super appreciated; I'm not sure how to proceed here at all.

EDIT- It's worth mentioning that there was a pins conflict that was previously not allowing the RC522 module to read any data, even without initializing the TFT eSPI. The conflict was that the TFT's T_DO & MISO pins were using the MISO pin, along with the RC522's MISO pin. This was fixed by moving the T_DO to an unused pin.

Can you post an annotated schematic showing exactly how this is connected. Be sure to show all connections and note any leads over 10"/25cm. Show all power sources. What is T_CLK, I gather it is a clock of some type.

Hi!

I drew this sketch myself so I hope it's clear.
This is the my ESP32 pinout.

This is the TFT only schematic:

This is the TFT with the RC522:

I hope it's not too complicated and legible. Please let me know if I can provide anything else.

any leads over 10"/25cm

Nope.

Show all power sources

All currently powered by the USB header on the ESP. I don't think it's a power issue though; I double checked the supplied voltage and current.

What is T_CLK, I gather it is a clock of some type

You're not wrong! According to this wiki, T_CLK is the touch SPI bus clock signal.

It looks correct, try an external power supply. I am just taking a SWAG as I am not familiar with these parts. It appears you have all the MOSI connected, MISO connected Clock connected and separate chip selects. Be sure the processor is in master mode and the other devices in slave mode.

Hi!

I don't think it's a power supply issue. I checked the supplied current and made sure the draw from both modules isn't exceeding that.

I'm pretty sure it has to do with the SPI because I mentioned:

I narrowed down the issue to the invocation of lv_tft_espi_create() . Removing this function restores all functionality to the RFID reader, but obviously I need the SPI settings to create the display object.

But you've asked what we think. And knowing nothing about how you have become so confident in you opinion, perhaps you might just take a few minutes and…

… indulge us. Try an external power supply able to provide substantially in excess of the total peak current demands of all the components that take power.

a7

1 Like

Since you are the expert you should be able to solve your problem in short order without out my help. You have one unit with one problem, there are thousands of units out there that are running OK. I wonder why yours does not is it something not to spec??? Good Luck and tell us where the problem was when you find it.

Hello.

I powered the ESP32 using a 5v/3000mA power supply.
I also changed the code to flash the onboard LED whenever the MFRC522 detects a tag.

No tag was detected when the code contained the lv_tft_espi_create() method. After removing this line, the RFID tags were being detected, indicated by a blinking onboard LED.

I don't understand the sudden hostility when I'm just attempting to supply ample information for debugging. All I said was that I double checked the power aspect of this issue, even before opening this thread.

As indicated in my initial post, I'm not an expert, don't claim to be an expert, and in fact explicitly mention my very bad skills at implementing this.

Just roll with it. Blame the heat. Do the best you can to fully answer questions posed, and to do (or explain why you won't) any experiments or tests helpers propose.


When you use the external power supply, how is power getting to all the components that need it?

I don't know that board, but ppl get into trouble trying to power things through the board instead of directly.


You have the serial monitor available, here's one place you might use it:

  draw_buf = heap_caps_malloc(DRAW_BUF_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  // This is the problematic line:
  lv_display_t *disp = lv_tft_espi_create(TFT_HOR_RES, TFT_VER_RES, draw_buf, DRAW_BUF_SIZE);
 

So.

What is the value of DRAW_BUF_SIZE?

Did the call to allocate draw_buf succeed?

I found this, so I ask where did you find the code you are presenting? Or the code you used to write it, because look at this different few lines:

/*Set to your screen resolution and rotation*/
#define TFT_HOR_RES   320
#define TFT_VER_RES   240
#define TFT_ROTATION  LV_DISPLAY_ROTATION_0

/*LVGL draw into this buffer, 1/10 screen size usually works well. The size is in bytes*/
#define DRAW_BUF_SIZE (TFT_HOR_RES * TFT_VER_RES / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4];

Explicit dimensions. Static compile-time allocated drawing buffer. Enough different to make me wonder where your variation came from.

HTH and stay cool.

a7

Did you measure the voltage? If so what was it.

Hello!
Apologies for the late reply! I'm working on this project after my day job which left me with limited time in the past 2 days.

What is the value of DRAW _BUF _SIZE ?

We define that size through calculations. The final value, in my case, is 30720 bytes:

#define TFT_HOR_RES 320
#define TFT_VER_RES 480

#define TFT_SCREEN_ROTATION 2
#define LVGL_SCREEN_ROTATION LV_DISPLAY_ROTATION_180

/*LVGL draw into this buffer, 1/10 screen size usually works well. The size is in bytes*/
#define DRAW_BUF_SIZE (TFT_HOR_RES * TFT_VER_RES / 10 * (LV_COLOR_DEPTH / 8))

I found this, so I ask where did you find the code you are presenting?

I'm just using the standard implementation of TFT_eSPI - I just renamed some of the definitions for my own preference, and changed some values for my specific implementation. But the overall implementation isn't really different than the standard one; Just different resolution and a rotated screen.

Thank you!

Hello!
Apologies for the late reply! I'm working on this project after my day job which left me with limited time in the past 2 days.

Did you measure the voltage? If so what was it.

I did measure the output voltage of the ESP32 and confirmed it is exactly 3.3V.

Thank you!

Is this the value the sketch prints, or what you figured it should if it did? Add a print statement if you just think that's what it would print.

Did the call to allocate draw _buf succeed?

That malloc call return value you store in draw_buf, was it non-null? Here again print the value, if it failed to make the buffer, you have to figure out why.

Or do what the original author prolly should

  if (!draw_buf) {
    // value is null
    Serial.println("buffer allocation failed!");
  }

The net effect of the two versions of "standard" code is the same, but they are different enough.

Please point to anywhere you went to find those lines of code you did not write, so we can see the version you are using in the context they were presented.

a7

Is this the value the sketch prints, or what you figured it should if it did?

Both!

That malloc call return value you store in draw _buf , was it non-null?

  Serial.print("draw_buf address: ");
  Serial.println((uintptr_t)draw_buf);

  Serial.print("DRAW_BUF_SIZE: ");
  Serial.println(DRAW_BUF_SIZE);

  if (!draw_buf) {
    // value is null
    Serial.println("buffer allocation failed!");
  }

draw_buf address: 1073557364
DRAW_BUF_SIZE: 30720

Please point to anywhere you went to find those lines of code you did not write

Here's the example code I based my code off of.

It's also worth mentioning that I can completely disconnect the TFT display and the RFID will still not accept any input if the lv_tft_espi_create() method is still invoked.

Does this confirm that this probably is/isn't a power issue?

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