Read adc (SPI) and control a motor at the same time with esp32-s2

Hi i'm a little bit new programming on arduino. I am programming an esp32-s2 to control the energy consumption of a motor and move the motor at the same time. To do that i want to read the adc (ADS131M03IRUKT). That adc meassures voltage, current and 1 encoder that determinate the position of the motor using 3 channels. This adc sends data using SPI. I want to read the SPI each ms to integrate the multiplication of current and voltage and meassure the energy each second. At the same time i want to move the motor to meassure the difference on consumption when the motor is working or not.

I have developed one routine to read the SPI using digitalwrite() to modified the value of sclk and cs to read values on miso when drdy is active and data is ready to get readed. But i think i can read SPI using SPI master in esp32-s2-SOLO-N4R2 in an easier way. The problem is that i don't know how i can configurate the SPI master and which are the pins that i can use for the signals (MOSI,MISO,SCLK,CS,SYNC/RESET and DRDY). Also i dont know how can i generate the pulses to move my step by step motor and the pulses for reading SPI at the same time.

Here is my code:

//Variables globales
int i=0;
long ReadData[3];
long TData;
int EnergiaLeido = 0;
int EnergiaEnvio = 0;
int MuestrasEnergia = 0;
int Multiplicacion = 0;
int Energia = 0;
double Total = 0;
int velocidad = 120;

//Configuración del motor
const int MODE= 6;
const int MODE1= 7; 
const int STEP= 8;
const int MODE0= 15;
const int ENABLE= 16;
const int CW_CCW= 17;
const int RESET= 18;
const int pasomaximo = 5000; //max number of steps

//Pines de los sensores
const int CS_ENERGIA = 3;   //CS_ENERGIA
const int DIN = 9;          //MOSI
const int CS = 10;          //CS
const int DOUT = 11;        //MISO
const int SCLK = 12;        //SCLK
const int CS2 = 21;         //CS2
const int DRDY = 35;        //DRDY
const int SYNC_RESET = 36;  //SYNC/RESET

//////////////////////////////////////////////////////////////////////////////
void leerADS131M03(){
  int bitleido = 0;
  digitalWrite(SCLK,LOW);
  digitalWrite(CS,HIGH);
  while(digitalRead(DRDY)==0){
    //Serial.println("Esperando datos");
  }
  digitalWrite(CS_ENERGIA,LOW);
  for(int p=0;p<3;p++){
    ReadData[p] = 0;
    i = 24;
    while (i > 0) {
      delayMicroseconds(2);
      digitalWrite(SCLK,HIGH);
      delayMicroseconds(2);
      digitalWrite(SCLK,LOW);
      bitleido=digitalRead(DOUT);
      if (i>1){
        if (bitleido == 1) {
          bitSet(ReadData[p],(i-1));
        }
      }
      i--;
    }
    //Serial.println(ReadData[p]);
  }
  digitalWrite(CS_ENERGIA,HIGH);
}

//////////////////////////////////////////////////////////////////////////////////
void leerMAX6682MUAT(){
  int negativo =  0;
  int bitleido = 0;
  digitalWrite(SCLK,LOW);
  digitalWrite(CS_ENERGIA,HIGH);
  digitalWrite(CS,LOW);
  TData = 0;
  i = 11;
  while (i > 0) {
    delayMicroseconds(10);
    digitalWrite(SCLK,HIGH);
    delayMicroseconds(10);
    digitalWrite(SCLK,LOW);
    bitleido=digitalRead(DOUT);
    if (i==11 && bitleido == 1){
      negativo = 1;
    }
    if (i>1 && i<11){
      if(negativo == 1){
        if (bitleido == 0) {
          bitSet(TData,(i-1));
        }
      }
      else{
        if (bitleido == 1) {
          bitSet(TData,(i-1));
        }
      }
    }
    i--;
  }
  if (negativo == 1){
    TData = TData * (-1);
  }
  //Serial.println(TData*0.1+17);
  digitalWrite(CS,HIGH);
}

////////////////////////////////////////////////////////////////////////////
void desplazaalasalida() { 
  digitalWrite (RESET, LOW);
  digitalWrite (ENABLE, HIGH); //enciendo el motor
  for (int i=0; i<3; i++) {
    digitalWrite(STEP,HIGH);
    delayMicroseconds(velocidad);
    digitalWrite(STEP,LOW);
    delayMicroseconds(velocidad);
  }
  digitalWrite (RESET, HIGH);
  for (int i=0; i<2; i++) {
    digitalWrite(STEP,HIGH);
    delayMicroseconds(velocidad);
    digitalWrite(STEP,LOW);
    delayMicroseconds(velocidad);
  }
  delay (200);
  digitalWrite (MODE0, HIGH); // 
  digitalWrite (MODE1, HIGH); // 
  digitalWrite (MODE, LOW); //
  delay (200);
  digitalWrite (CW_CCW, LOW);
  for (int i=0; i<pasomaximo; i++){   //Forward pasomaximo steps o hasta detectar que ha llegado al fin***
    digitalWrite(STEP,HIGH);
    delayMicroseconds(velocidad);
    digitalWrite(STEP,LOW);
    delayMicroseconds(velocidad);
  }
  vuelvealcomienzo();
}

//////////////////////////////////////////////////////////////////////////////////
bool vuelvealcomienzo() {
  digitalWrite (CW_CCW, HIGH);
  delay (200);
  for (int i=0; i<pasomaximo; i++){
    digitalWrite(STEP,HIGH);
    delayMicroseconds(velocidad);
    digitalWrite(STEP,LOW);
    delayMicroseconds(velocidad);
  }
  para();
  return false;
}

//////////////////////////////////////////////////////////////////////////////////
bool para() {
  digitalWrite (RESET, LOW); //Posición inicial
  digitalWrite (ENABLE, HIGH); //Posición inicial final 
  delay(100);
  digitalWrite (RESET, LOW);
  digitalWrite(ENABLE,LOW); //apago el motor
  digitalWrite (MODE0, LOW); // 
  digitalWrite (MODE1, LOW); // 
  digitalWrite (MODE, LOW); //
  return true;
}

/////////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  pinMode(ENABLE, OUTPUT);
  pinMode(CW_CCW, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(RESET, OUTPUT);
  pinMode(MODE0, OUTPUT);
  pinMode(MODE1, OUTPUT);
  pinMode(MODE, OUTPUT);
  
  digitalWrite (MODE, LOW); //Esta combinacion pone el motor en full step 
  digitalWrite (ENABLE, HIGH); //enciendo el motor
  digitalWrite (RESET, LOW); //Posición inicial
  delay(100);
  digitalWrite (ENABLE, LOW); //apago el motor
  
  pinMode(DOUT, INPUT);
  pinMode(DRDY, INPUT);
  pinMode(DIN, OUTPUT);
  pinMode(SYNC_RESET, OUTPUT);
  digitalWrite(SYNC_RESET,HIGH);
  pinMode(CS, OUTPUT);
  digitalWrite(CS,HIGH);
  pinMode(CS2, OUTPUT);
  digitalWrite(CS2,HIGH);
  pinMode(CS_ENERGIA, OUTPUT);
  digitalWrite(CS_ENERGIA,HIGH);
  pinMode(SCLK, OUTPUT);
  digitalWrite(SCLK,LOW);

  digitalWrite(SYNC_RESET,LOW);
  delayMicroseconds(300);
  digitalWrite(SYNC_RESET,HIGH);

  digitalWrite(CS_ENERGIA,LOW);

  //desplazaalasalida();
}

/////////////////////////////////////////////////////////////////////////////
void loop() {
  if(millis() - EnergiaLeido >= 1 && millis() - EnergiaEnvio < 1000){
    EnergiaLeido=millis();
    leerADS131M03();
    Multiplicacion = ReadData[0] * ReadData[1];
    Total = Total + Multiplicacion;
    MuestrasEnergia++;
  }
  if (millis() - EnergiaEnvio > 1000){
    EnergiaLeido=millis();
    leerADS131M03();
    Multiplicacion = ReadData[0] * ReadData[1];
    Total = Total + Multiplicacion;
    MuestrasEnergia++;
    Energia = Total / MuestrasEnergia;
    Serial.println(Energia);
    Serial.println(MuestrasEnergia);
    Total = 0;
    MuestrasEnergia = 0;
    delayMicroseconds(50);
    leerMAX6682MUAT();
    EnergiaEnvio=millis();
  }
  desplazaalasalida();
}

Thanks you for your time and assistance. Any help is wellcomed.

why aren't you using the Wire library?

@gcjr. One reason I do not use the Wire or SPI library with a ESP32 is that using the ESP32's API nets faster I2C and SPI performance without the added layer of the limiting Arduino core. Also, access to many operational SPI/I2C parameters that are preset by the Arduino Core. Those presets often are not the most optimized.

Also, by using the ESP32's OS SPI/I2C can operate in the background on a ESP32. For instance a read can be initiated on a SPI device then other instructions can be done and when the SPI device read is done trigger a data use.

On the other hand, @lucasaenz, why aren't you using the Wire library? And if you want to do 2 things at the same time with an ESP32 then use freeRTOS, the built in multi-taking, multi-processing OS of the ESP32. The Arduino core runs on top of the ESP32's OS.

@Idahowalker It's the first time i read an SPI device, so when i see how it works i try to read it in the form it makes more sense for me. I didn't know that there are libraries that helps me with this. That's why i didn't use them. Usually i try to not use many libraries because people explain me that in many cases ESP32's API nets faster but i am new programming and i'm not sure on how to program this kind of codes correctly.

Using a already written library would allow you to develop your code faster when someone has already done the work for you.

Consider using words like "arduino ADS131 library" in a internet search engine to get results like:

or

But wait there is more! Just give it a try.

Honestly, before buying a device to attach to a MCU first look up to see if a library for talking to the device already exists.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/index.html

Thanks you very much @Idahowalker, i am gonna try to use this libraries and hope that it works for me.

@Idahowalker Hi I've seen the SPI.h library for arduino and i have implemented this code:

#include <SPI.h>

long RealData[3];
byte ReadData[9];
int EnergiaEnvio = 0;

//Pines de los sensores
const int CS_ENERGIA = 3;   //CS_ENERGIA
const int DIN = 9;          //MOSI
const int DOUT = 38;        //MISO
const int SCLK = 12;        //SCLK
const int DRDY = 35;        //DRDY
const int SYNC_RESET = 36;  //SYNC/RESET

//////////////////////////////////////////////////////////////
void readADS131M03(){
  while(digitalRead(DRDY)==0){
    //Serial.println("wait for data");
  }
  digitalWrite(CS_ENERGIA,LOW);
  for(int i=0;i<9;i++){
  ReadData[i] = SPI.transfer(0x000000);
  }
  digitalWrite(CS_ENERGIA,HIGH);
  for(int i=0;i<9;i++){
  Serial.println(ReadData[i]);
  }
}
////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  pinMode(DOUT, INPUT);
  pinMode(DRDY, INPUT);
  pinMode(DIN, OUTPUT);
  pinMode(CS_ENERGIA, OUTPUT);
  digitalWrite(CS_ENERGIA,HIGH);
  pinMode(SCLK, OUTPUT);
  digitalWrite(SCLK,LOW);
  pinMode(SYNC_RESET, OUTPUT);
  digitalWrite(SYNC_RESET,HIGH);

  digitalWrite(SYNC_RESET,LOW);
  delayMicroseconds(300);
  digitalWrite(SYNC_RESET,HIGH);

  SPI.begin(SCLK, DOUT, DIN, CS_ENERGIA);
}

void loop() {
  if (millis() - EnergiaEnvio > 1000){
    readADS131M03();
    EnergiaEnvio=millis();
  }

}

It works as i want but in the function void readADS131M03() when i print the ReadData variables their values are 0. In the waveform seen on my logic analyzer i can see that in MISO pin its receiving data so i don't know why it's not being saved on ReadData variables.
My logic analyzer:

why don't you use a library for the device?

Already premade and contains the code to setup the device for proper operations. And at least you could look at their code to see how you are doing it wrong.

that's the problem you should be trying to solve and not how to write a SPI device driver from scratch.

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