Skip to content

ESP 32 S3 - ST 7789 display, Multiple SPI connection Issue #3890

@Nethan325

Description

@Nethan325

Hi, I am using an ESP32S3 N16R8 module, and the display is ST7789, I am finding it difficult to print the angle values obtained from the encoder, which uses SPI communication to the display. I am using Arduino IDE by the way, both the display and encoder use the same MOSI and SCK I tried defining different modes for the encoder. What i feel is that the display seems to hold the SPI communication all the time, (my display does not have a CS pin).

These were my pin configurations

// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins

#define TFT_MISO 13
#define TFT_MOSI 11
#define TFT_SCLK 12
#define TFT_CS   9  // Chip select control pin
#define TFT_DC   16  // Data Command control pin
#define TFT_RST  17  // Reset pin (could connect to RST pin)
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

This was the code i used to display angle on to the display

#include <SPI.h>
#include <TFT_eSPI.h>


/* ---------------- TFT Setup ---------------- */
TFT_eSPI tft = TFT_eSPI();
#define SCREEN_W 240
#define SCREEN_H 240

/* ---------------- AS5048A Encoder Setup ---------------- */
#define PIN_CS    10
#define PIN_SCK   12
#define PIN_MOSI  11
#define PIN_MISO  13
#define AS5048_ANGLE_REG  0x3FFF

SPISettings as5048SPI(1000000, MSBFIRST, SPI_MODE1);

/* ---------------- Filter Parameters ---------------- */
const float ALPHA = 0.10;
const float DEAD_BAND = 0.05;

float filteredAngle = 0.0;
float stableAngle   = 0.0;
bool firstSample    = true;

/* ---------------- Utility: Even Parity ---------------- */
uint16_t addEvenParity(uint16_t v) {
  uint8_t ones = 0;
  for (int i = 0; i < 15; i++) {
    if (v & (1 << i)) ones++;
  }
  if (ones % 2) v |= 0x8000;
  return v;
}

/* ---------------- Read Raw Angle ---------------- */
uint16_t readRawAngle() {
  uint16_t cmd = addEvenParity(0x4000 | AS5048_ANGLE_REG);
  uint16_t resp;

  SPI.beginTransaction(as5048SPI);

  digitalWrite(PIN_CS, LOW);
  SPI.transfer16(cmd);
  digitalWrite(PIN_CS, HIGH);

  delayMicroseconds(2);

  digitalWrite(PIN_CS, LOW);
  resp = SPI.transfer16(0x0000);
  digitalWrite(PIN_CS, HIGH);

  SPI.endTransaction();

  return resp & 0x3FFF;  // 14-bit angle
}

/* ---------------- Convert to Degrees ---------------- */
float readAngleDegrees() {
  return (readRawAngle() * 360.0f) / 16384.0f;
}

/* ---------------- Filters ---------------- */
float lowPassFilter(float angle) {
  if (firstSample) {
    filteredAngle = angle;
    firstSample = false;
  } else {
    filteredAngle = ALPHA * angle + (1.0f - ALPHA) * filteredAngle;
  }
  return filteredAngle;
}

float deadbandFilter(float angle) {
  if (fabs(angle - stableAngle) < DEAD_BAND) return stableAngle;
  stableAngle = angle;
  return angle;
}

/* ---------------- Setup ---------------- */
void setup() {
  Serial.begin(115200);

  pinMode(PIN_CS, OUTPUT);
  digitalWrite(PIN_CS, HIGH);
  SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, PIN_CS);

  tft.init();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  // Display logo/brand first
  const char* brand = "LUSTREJ";
  const char* tagline = "where craft meets precision";
  int brandFont = 4;
  int taglineFont = 2;

  int brandWidth = tft.textWidth(brand, brandFont);
  int taglineWidth = tft.textWidth(tagline, taglineFont);
  int brandX = (tft.width() - brandWidth) / 2;
  int brandY = (tft.height() / 2) - 18;
  int taglineX = (tft.width() - taglineWidth) / 2;
  int taglineY = brandY + 32;

  tft.setCursor(brandX, brandY, brandFont);
  tft.println(brand);
  delay(200);
  tft.setCursor(taglineX, taglineY, taglineFont);
  tft.println(tagline);
  delay(1500);

  tft.fillScreen(TFT_BLACK);  // Clear screen for angle display
  tft.setTextSize(3);
  tft.setCursor(20, SCREEN_H / 2 - 10);
  tft.println("Angle:");
}

/* ---------------- Main Loop ---------------- */
void loop() {
  float angle = readAngleDegrees();

  // Wrap angle to 0-360
  if (angle < 0.0f) angle += 360.0f;
  if (angle >= 360.0f) angle -= 360.0f;

  angle = lowPassFilter(angle);
  angle = deadbandFilter(angle);

  // Print to Serial
  Serial.print("Angle: ");
  Serial.println(angle, 2);

  // Display on TFT
  tft.fillRect(20, SCREEN_H / 2 + 20, 200, 40, TFT_BLACK);  // Clear previous value
  tft.setCursor(20, SCREEN_H / 2 + 20);
  tft.printf("%.2f°", angle);

  delay(50);  // 20 Hz update rate
}

Can you please help me find out what went wrong

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions