Trouble with ESP32 + external ADC

Hello all,
I am working on a load cell project for obtaining measurement data from 4 cells at ~1000Hz. I have so far been successful using an Arduino Uno but I am trying to move over to an ESP32 so that I can attempt to pass the data onto my computer using the in-built bluetooth. These are the parts I am using:

I have built the circuit on breadboard and double checked it was functional with the Arduino Uno. I have then replaced the Uno with the ESP32 and using a level shifter for the SPI channels since the ADC is supplied 5V. For the moment I am using the Uno to provide the 5V source, with hopes of a better power source when I can get the ESP32 up and running.

The issue that I am encountering (or so I think), is that I cannot get the SPI communication working because the ADC's DRDY line (for when data is ready) never goes low and I get an infinite loop in the wait() function. I am very new to the ESP32 and I could not find many examples on SPI so I am fairly sure I am implementing it wrong.
I have seen the ESP32 SPI class and tried to follow their example however when I instantiate the class like this:

SPIClass SPI1(VSPI);

The ESP32 reboots periodically without anything happening.

Below I have attached the initialise function within the .cpp file for the ADS1262 implementation that starts the SPI communication. I unfortunately do not have access to an oscilloscope to know what the SPI is outputting, but the exact same implementation worked on the Arduino Uno (minus the level shifter circuitry for 3.3V <---> 5V).

P.S. I can post more of the code including the .ino file if that will help my chances

Working .cpp file for Arduino UNO:

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

int32_t ads1262::ads1262_Read_Data()
{
  int32_t regData;

  //digitalWrite(ADS1262_CS_PIN, LOW);

  regData |= SPI.transfer(CONFIG_SPI_MASTER_DUMMY);
  regData <<= 8;
  regData |= SPI.transfer(CONFIG_SPI_MASTER_DUMMY);
  regData <<= 8;
  regData |= SPI.transfer(CONFIG_SPI_MASTER_DUMMY);
  regData <<= 8;
  regData |= SPI.transfer(CONFIG_SPI_MASTER_DUMMY);

  digitalWriteFast(ADS1262_CS_PIN, HIGH);
  return regData;
}

void ads1262::ads1262_Init()
{

  // start the SPI library:
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  //CPOL = 0, CPHA = 1
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV2); 

  ads1262_Reset();
  delay(100);

  ads1262_Hard_Stop();
  delay(350);

  ads1262_Enable_Start();

  // SPI.endTransaction();
}

Not -working code on ESP32:

#include <Arduino.h>
#include <ads1262.h>
#include <SPI.h>
// #include <digitalWriteFast.h>

// SPIClass SPI1(VSPI);

void ads1262::ads1262_Init()
{
  // start the SPI library:
  SPI.begin(18, 19, 23, D3);
  SPI.setBitOrder(MSBFIRST);
  //CPOL = 0, CPHA = 1
  SPI.setDataMode(SPI_MODE1);
  // SPI.setClockDivider(SPI_CLOCK_DIV2); 
  SPI.setFrequency(8000000);  // 8MHz upper limit of ADS1262
  // int SPISpeed = 8000000;
  // SPI.beginTransaction( SPISettings( SPISpeed, MSBFIRST, SPI_MODE1) );

  ads1262_Reset();
  delay(100);

  ads1262_Hard_Stop();
  delay(350);

  ads1262_Enable_Start();

  // SPI.endTransaction();
}

Is the SPI working on the Uno board ?
The ESP32 is more and more compatible with the Arduino libraries. It should be same.

Here is an example that uses the ESP32 with SPI : https://randomnerdtutorials.com/esp8266-nodemcu-bmp388-arduino/

Can you make a photo with all the wiring or make a drawing of the wiring ?
The level shifter must have a low power voltage to the low side and a high power voltage to the high side, or else it does not work. Is the level shifter a module ? Can you give a link to where you bought it ?

Your level shifter is a bi-directional level shifter that relies on a pullup resistor to slowly whirl to a high level some day if you are lucky. That might be too slow for the SPI bus[EDIT] The TXS0108E is not just a bidirectional voltage translator, it can do more.
Can you replace the ADS1262 with a 3.3V type ADC ? Can you find a normal digital level shifter ? The ESP32 does not have 5V tolerant pins.

Do you use a breadboard ? Breadboard have often bad contacts and jumper wires can be broken.

The Arduino Uno might not be able to provide enough current for the ESP32. Use a good quality USB cable. If I remember it well, then the ESP32 might need a peak of 250mA.

A 24MHz 8 channel Logic Analyzer with PulseView/sigrok costs 15 euros/dollars. I am very fond of the LHT00SU1 which is 30 or 35 euros/dollars (turn off the analog channel to be able to sample the digital inputs at a high rate).

Thank you for your reply Koepel,

I can get reliable measurements using the Uno around 1000Hz by dumping the binary data from the ADC to the serial. I am using this level shifter module and the connection is as per the photos of the circuit diagram. I have placed a 4.7kOhm pullup between the OE enable pin and the 3.3V source. As far as I could tell from the datasheet it should be able to handle the 8MHz SPI speed... is this level shifter likely the source of my problems?

I have rewired the breadboard and double checked the Uno circuit was still working, then connected for the ESP32 as I have drawn in the diagram. When I measure the data lines at the ADC side – START and PWDN are 5V High, CS is Low and confusingly DRDY is Low as well (~0.10V). I say this because in the program I am printing the digitalRead() of DRDY and it shows up as High.

The Uno is only powering the ADC and the high-side of the level-shifter, the ESP32 and Uno have their own USB power source (connected to my laptops). I measure fairly stable 5V and 3.3V on either side – do you think the reboot current draw of the ESP32 could be affecting the SPI communication?

I am somewhat constrained to the ADS1262 (32-bit) because my load cells are 500kg rated (10mV/V sensitivity) and trying to squeeze out at least 0.1kg effective noise-free resolution with the 5V excitation (impossible with my breadboard setup but that is a problem for later).

My alternative is the ADS1256 with better multiplexing speed but same 5V logic... will have to see what else I can source from Australia!


UPDATE: I have fixed my problems by changing the DRDY pin from D11 to D12 of the ESP32 (must be reserved on the Firebeetle board) and achieved a much faster throughput of 4kHz with the esp32. Hopefully this thread will be helpful to someone else in the future!

1 Like

Manufacturer's page of the TXS0108E : https://www.ti.com/product/TXS0108E with datasheet.

Port A is the low side, Port B is the high side.
No external pullup resistors are needed. It can do both open-drain and push-pull.
What I wrote before is not correct. Sorry. It can do the SPI bus.

A resistor at OE is only needed to make it inactive during startup. I think you don't need that resistor, you may connect it directly to 3.3V.
I don't understand the 47Ω resistors, I think you don't need them.
The high side must be powered with 5V. You need 5V to pin VB.

1 Like

Good spot surprised it is working without the 5V connected on the high side.

I will remove the pullup resistor and see how it goes. The ADS1262 datasheet suggests the following on page 113:

Place a 47-Ω resistor in series with all digital input and output pins (CS, SCLK, DIN, DOUT/DRDY, and DRDY).
The resistors match the characteristic impedance of the PCB trace by source termination, helping reduce overshoot and ringing

I will hopefully get to PCB design sometime soon :smiley:

Thanks for the explanation
The "characteristic impedance of the PCB trace by source termination" is somewhat vague.
I assume that it is to keep the ADS1262 as quiet as possible, because it can do 32-bit.