Help! ADE7758 and ESP32-S3

Hello everyone,

I'm a newcomer to this field and would like to ask for some guidance from all the experts here. I'm working on a project for a 3-phase energy meter using the ADE7758 and an ESP32-S3. I've hit a major roadblock with getting the chip to output accurate readings. The values I'm getting are often garbled or simply zero.

I've performed some initial troubleshooting and believe the fundamental communication signals are working correctly:


Troubleshooting Steps I've Taken

  1. Chip Select (!CS) & Clock (CLK): I've used an oscilloscope to measure the signals on the CS and CLK pins. I can confirm that the ESP32-S3 is correctly pulling the !CS pin LOW and sending a stable CLK signal. This suggests that my basic SPI connections are working as they should.
  2. Sine Wave Test: For a basic test, I've fed a 50Hz sine wave into the ADE7758's voltage channel (Phase A). However, the readings I get are still highly abnormal and inaccurate.

I suspect that the problem is more complex than a simple wiring mistake. I believe it lies within the code's protocol-level communication and chip configuration.

My Suspicions

  • Incomplete Chip Initialization: I am not confident that I have correctly written to the essential registers, such as OPMODE and MMODE, to enable the chip's measurement functions.
  • Incorrect SPI Mode: I am unsure if I've set the correct SPI mode (CPOL/CPHA) in my code to match the ADE7758's requirements.

I've attached the code I am using. Please bear with me, as I am a beginner, and some parts of my code might be frustrating to look at. I would greatly appreciate any advice on what I might be missing or what specific parts of my code I should be focusing on.


#include <Arduino.h>
#include <SPI.h>

// ESP32-S3 SPI pins
#define PIN_MISO 37
#define PIN_MOSI 35
#define PIN_SCK  36
#define PIN_CS   39

SPIClass vspi(FSPI);

SPISettings spiSettings(1000000, MSBFIRST, SPI_MODE1);

// ------------------- Function ------------------- //
uint32_t readRegister24(uint8_t reg) {
  vspi.beginTransaction(spiSettings);
  digitalWrite(PIN_CS, LOW);
  Serial.println("CS LOW");

  vspi.transfer(0x80 | reg); // bit7=1 → READ

  uint32_t value = 0;
  value |= ((uint32_t)vspi.transfer(0)) << 16;
  value |= ((uint32_t)vspi.transfer(0)) << 8;
  value |= ((uint32_t)vspi.transfer(0));

  digitalWrite(PIN_CS, HIGH);
  Serial.println("CS HIGH");
  vspi.endTransaction();

  return value;
}

uint8_t readRegister8(uint8_t reg) {
  vspi.beginTransaction(spiSettings);
  digitalWrite(PIN_CS, LOW);
  Serial.println("CS LOW");

  vspi.transfer(0x80 | reg);
  uint8_t value = vspi.transfer(0);

  digitalWrite(PIN_CS, HIGH);
  Serial.println("CS HIGH");
  vspi.endTransaction();

  return value;
}

// ------------------- Config ------------------- //
// Divider ratio (250k x4 + 1k)
const float dividerRatio = (1000000.0 + 1000.0) / 1000.0; // ≈ 1001
//calibration: 1 LSB = 1 mV
const float VRMS_LSB = 0.001; 
// ---------------------------------------------- //

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

  vspi.begin(PIN_SCK, PIN_MISO, PIN_MOSI, -1);
  pinMode(PIN_CS, OUTPUT);
  digitalWrite(PIN_CS, HIGH);

  Serial.println("ESP32-S3 ADE7758 Direct SPI Test");
}

// ------------------- Loop ------------------- //
void loop() {
  static unsigned long lastMillis = 0;
  if (millis() - lastMillis >= 1000) {
    lastMillis = millis();

    // VRMS Register
    uint32_t vA = readRegister24(0x17);
    uint32_t vB = readRegister24(0x18);
    uint32_t vC = readRegister24(0x19);

    // STATUS Register
    uint8_t status = readRegister8(0x0B);

    Serial.println("----------------------------------");
    Serial.print("STATUS Reg: 0x"); Serial.println(status, HEX);

    Serial.print("VRMS Phase A (raw): "); Serial.println(vA);
    Serial.print("VRMS Phase B (raw): "); Serial.println(vB);
    Serial.print("VRMS Phase C (raw): "); Serial.println(vC);

    Serial.println("VOLTAGE RMS readings (calculated V):");
    Serial.print("Phase A: "); Serial.println(vA * VRMS_LSB * dividerRatio, 2);
    Serial.print("Phase B: "); Serial.println(vB * VRMS_LSB * dividerRatio, 2);
    Serial.print("Phase C: "); Serial.println(vC * VRMS_LSB * dividerRatio, 2); } }

Thank you in advance for your help

which specific ESP32S3 module are you using? give a link?
how do you power the ADE7758?

I assume you have connected

  1. ESP32S3 MOSI GPIO37 to DIN
  2. ESP32S3 MISO GPIO35 to DOUT

does you oscilloscope show any signals on these pins?
anything on IRQ?

upload a copy of the serial monitor output (as text not a screen image)

Are you trying to read these registers (0x17 - 0x19)?

    uint32_t vA = readRegister24(0x17);
    uint32_t vB = readRegister24(0x18);
    uint32_t vC = readRegister24(0x19);

If you want to read the phase A, B and C voltage channel RMS Register, the AD7758 datasheet show this (page 60 - 61):

0x0D = Phase A Voltage Channel RMS Register

0x0E = Phase B Voltage Channel RMS Register

0x0F = Phase C Voltage Channel RMS Register

I also noticed that in the readRegister24 function you put this comment:

vspi.transfer(0x80 | reg); // bit7=1 → READ

however, table 16 shows this (page 60)

On page 57 you can see the following:

Is this question related to

If anyone has a code that works aswell as a picture of their circuit please send it to me. i am doing my final electrical engineering project and my ade7758 cant get SPI communication to work.