Trying to use AD8400 with Metro ESP32-S2

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
muttstang
 
Posts: 86
Joined: Mon May 10, 2021 3:24 pm

Trying to use AD8400 with Metro ESP32-S2

Post by muttstang »

I'm trying to use the AD8400 digital potentiometer with a Metro ESP32-S2. I was able to use it with an Uno with the AD520X library but have not figured out how to make it work on the Metro. I am not so great at figuring out how to use different parts of a library if I don't have an example already set up to pull from. I'm hoping it's a pretty easy thing for someone more experienced then I am. I just want to be able to run this potentiometer in a bigger piece of code but this is a simplified version in order to just run a basic hand controller for my trolling motor. I want to incorporate it into a gps driven controller instead and have much of that functionality all figured out. If I can get the digital pot working then I should be good to go.

How do I set this guy up, I don't know if I'm close or not, I keep getting the following error:

Code: Select all

Arduino: 1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board: "Adafruit Metro ESP32-S2, Enabled, Disabled, Disabled, Internal USB, Enabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi), QIO, 80MHz, 4MB (32Mb), 921600, None"





















C:\Users\aerejb\Documents\Arduino\libraries\AD520X\AD520X.cpp: In member function 'void AD520X::begin(uint8_t)':

C:\Users\aerejb\Documents\Arduino\libraries\AD520X\AD520X.cpp:61:28: error: 'VSPI' was not declared in this scope

       mySPI = new SPIClass(VSPI);

                            ^~~~

C:\Users\aerejb\Documents\Arduino\libraries\AD520X\AD520X.cpp:61:28: note: suggested alternative: 'SPI'

       mySPI = new SPIClass(VSPI);

                            ^~~~

                            SPI

exit status 1

Error compiling for board Adafruit Metro ESP32-S2.



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
Here's my sketch:

Code: Select all

#include "AD520X.h"

uint32_t start, stop;
// select, reset, shutdown, data, clock
AD8400 pot(15, 255, 255, 16, 42);  // SW SPI

// define inputs
const byte right_turn_input = A1;
const byte left_turn_input = 5;
const byte on_off_input = A3;
const byte speed_input = A2;

// define outputs
const byte right_turn_output = 2;
const byte left_turn_output = 4;
const byte on_off_output = 6;
const byte speed_output = 3;

// define variables

int speed_value = 0;
int satelite_count = 0;

bool motor_state = false;

float motor_offset_angle = 0;
float magnetic_declination = 0;
float boat_heading = 0;
float desired_heading = 0;

double actual_lattitude = 0;
double actual_longitude = 0;
double desired_lattitude = 0;
double desired_longitude = 0;





void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Begin program");
  pot.selectHSPI();
  pot.setGPIOpins(42, 0, 16, 15); //pot.setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
  pot.begin(0); // set initial potentiometer value to zero (this gives you the wiper resistance 50-100 ohms)

  // define pin inputs
  pinMode(right_turn_input, INPUT);
  pinMode(left_turn_input, INPUT);
  pinMode(on_off_input, INPUT);
  pinMode(speed_input, INPUT);

  // define pin outputs
  pinMode(right_turn_output, OUTPUT);
  pinMode(left_turn_output, OUTPUT);
  pinMode(on_off_output, OUTPUT);
  pinMode(speed_output, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  delay(10);
  on_off();
  
  if (motor_state == true) {
    speed_calculation();
    steering_calculation();
  }
  //Serial.println(" ");
}

void speed_calculation() {
  // figure out what the speed value is
  
  speed_value = analogRead(speed_input) / 4;
  if (speed_value > 256) { speed_value = 256; }
  if (speed_value < 20) { speed_value = 0; }
  pot.setValue(0,speed_value);  // Set digital potentiometer value for the motor to read
  //analogWrite(speed_output, speed_value);
  Serial.print("Output speed value = "); Serial.print(speed_value); Serial.print(", ");
}

void steering_calculation() {
  // figure out what the steering should change
  if (digitalRead(right_turn_input) == 1) {
    digitalWrite(left_turn_output, 0);
    digitalWrite(right_turn_output, 1);
    Serial.print("Turn Right,  ");
  }
  delay(5);
  
  if (digitalRead(right_turn_input) == 0) {
    digitalWrite(right_turn_output, 0);
    Serial.print("deactivate right turn,  ");
  }
  delay(5);
  
  if (digitalRead(left_turn_input) == 1) {
    digitalWrite(right_turn_output, 0);
    digitalWrite(left_turn_output, 1);
    Serial.print("Turn Left,  ");
  }
  delay(5);
  
  if (digitalRead(left_turn_input) == 0) {
    digitalWrite(left_turn_output, 0);
    Serial.print("deactivate left turn,  ");
  }
  delay(5);
}

void on_off() {
  motor_state = digitalRead(on_off_input);
  digitalWrite(on_off_output, motor_state);
  
  if (motor_state == true) {
    Serial.println(", Motor on");
  }
  else {
    Serial.println(", Motor off");
  }
}
And here is the library
AD502x.h:

Code: Select all

#pragma once
//
//    FILE: AD520X.h
//  AUTHOR: Rob Tillaart
//    DATE: 2020-07-24
// VERSION: 0.2.1
// PURPOSE: Arduino library for AD5204 and AD5206 digital potentiometers (+ older AD8400, AD8402, AD8403)
//     URL: https://github.com/RobTillaart/AD520X
//
// HISTORY:
// see AD520X.cpp file
//


#include "Arduino.h"
#include "SPI.h"


#define AD520X_LIB_VERSION              (F("0.2.1"))

#define AD520X_MIDDLE_VALUE             128


class AD520X
{
public:
  AD520X(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock);  

  void     begin(uint8_t value = AD520X_MIDDLE_VALUE);
  bool     setValue(uint8_t pm = 0, uint8_t value = AD520X_MIDDLE_VALUE);
  void     setAll(uint8_t value = AD520X_MIDDLE_VALUE);
  uint8_t  getValue(uint8_t pm = 0);

  bool     setPercentage(uint8_t pm = 0, float percentage = 50);
  float    getPercentage(uint8_t pm = 0);

  void     reset(uint8_t value = AD520X_MIDDLE_VALUE);
  uint8_t  pmCount()   { return _pmCount; };

  void     powerOn()   { digitalWrite(_shutdown, LOW); };
  void     powerOff()  { digitalWrite(_shutdown, HIGH); };
  void     powerDown() { powerOff(); };             // obsolete, remove in 0.3.0
  bool     isPowerOn() { return digitalRead(_shutdown) == LOW; };

  //       speed in Hz
  void     setSPIspeed(uint32_t speed);
  uint32_t getSPIspeed() { return _SPIspeed; };

  // debugging
  bool     usesHWSPI() { return _hwSPI; };

  // ESP32 specific
  #if defined(ESP32)
  void     selectHSPI() { _useHSPI = true;  };
  void     selectVSPI() { _useHSPI = false; };
  bool     usesHSPI()   { return _useHSPI;  };
  bool     usesVSPI()   { return !_useHSPI; };

  // to overrule ESP32 default hardware pins
  void     setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
  #endif


protected:
  uint8_t  _dataOut;
  uint8_t  _clock;
  uint8_t  _select;
  uint8_t  _reset;
  uint8_t  _shutdown;
  bool     _hwSPI = 3;
  uint32_t _SPIspeed = 16000000;

  uint8_t  _value[6];
  uint8_t  _pmCount = 6;

  void     updateDevice(uint8_t pm);
  void     swSPI_transfer(uint8_t value);

  SPIClass    * mySPI;
  SPISettings _spi_settings;

  #if defined(ESP32)
  bool        _useHSPI = true;
  #endif
};


/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
class AD5206 : public AD520X
{
public:
  AD5206(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut = 255, uint8_t clock = 255);
};


class AD5204 : public AD520X
{
public:
  AD5204(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut = 255, uint8_t clock = 255); 
};


class AD8400 : public AD520X
{
public:
  AD8400(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut = 255, uint8_t clock = 255); 
};


class AD8402 : public AD520X
{
public:
  AD8402(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut = 255, uint8_t clock = 255); 
};


class AD8403 : public AD520X
{
public:
  AD8403(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut = 255, uint8_t clock = 255); 
};

// -- END OF FILE -- 
AD520X.cpp

Code: Select all

//
//    FILE: AD520X.cpp
//  AUTHOR: Rob Tillaart
//    DATE: 2020-07-24
// VERSION: 0.2.1
// PURPOSE: Arduino library for AD5204 and AD5206 digital potentiometers (+ older AD8400, AD8402, AD8403)
//     URL: https://github.com/RobTillaart/AD520X
//
// HISTORY:
//  0.0.1   2020-07-24  initial version
//  0.0.2   2020-07-25  support for AD8400 series in documentation.
//  0.1.0   2020-07-26  refactor, fix #2 select pin for HW SPI; add shutdown.
//  0.1.1   2020-12-08  Arduino-CI + unit test + isPowerOn()
//  0.1.2   2021-08-19  VSPI / HSPI support for ESP32 only
//                      add setGPIOpins for ESP32 only
//                      add SetSPIspeed (generic)
//  0.2.0   2021-10-16  update build-CI
//                      add get- and setPercentage()
//  0.2.1   2021-12-10  update library.json, licence
//                      default value for setAll()


#include "AD520X.h"


AD520X::AD520X(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
{
  _pmCount  = 6;
  _select   = select;
  _dataOut  = dataOut;
  _clock    = clock;
  _reset    = reset;
  _shutdown = shutdown;
  _hwSPI    = (dataOut == 255) && (clock == 255);
}


//  initializes the pins and starts SPI in case of hardware SPI
void AD520X::begin(uint8_t value)
{
  pinMode(_select, OUTPUT);
  digitalWrite(_select, HIGH);
  pinMode(_reset, OUTPUT);
  digitalWrite(_reset, LOW);
  pinMode(_shutdown, OUTPUT);
  digitalWrite(_shutdown, LOW);

  _spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE1);

  if(_hwSPI)
  {
    #if defined(ESP32)
    if (_useHSPI)      //  HSPI
    {
      mySPI = new SPIClass(HSPI);
      mySPI->end();
      mySPI->begin(14, 12, 13, _select);   //  CLK=14 MISO=12 MOSI=13
    }
    else               //  VSPI
    {
      mySPI = new SPIClass(VSPI);
      mySPI->end();
      mySPI->begin(18, 19, 23, _select);   //  CLK=18 MISO=19 MOSI=23
    }
    #else              //  generic hardware SPI
    mySPI = &SPI;
    mySPI->end();
    mySPI->begin();
    #endif
    delay(1);
  }
  else
  {
    pinMode(_dataOut, OUTPUT);
    pinMode(_clock,   OUTPUT);
    digitalWrite(_dataOut, LOW);
    digitalWrite(_clock,   LOW);
  }

  setAll(value);
}


#if defined(ESP32)
void AD520X::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)
{
  _clock   = clk;
  _dataOut = mosi;
  _select  = select;
  pinMode(_select, OUTPUT);
  digitalWrite(_select, HIGH);

  mySPI->end();                 //  disable SPI and restart
  mySPI->begin(clk, miso, mosi, select);
}
#endif


bool AD520X::setValue(uint8_t pm, uint8_t value)
{
  if (pm >= _pmCount) return false;
  _value[pm] = value;
  updateDevice(pm);
  return true;
}


void  AD520X::setAll(uint8_t value)
{
  for (uint8_t pm = 0; pm < _pmCount; pm++)
  {
    setValue(pm, value);
  }
}


uint8_t AD520X::getValue(uint8_t pm)
{
  if (pm >= _pmCount) return 0;
  return _value[pm];
}


bool AD520X::setPercentage(uint8_t pm, float percentage)
{
  if ((percentage < 0) || (percentage > 100.0)) return false;
  return setValue(pm, round(percentage * (255.0 / 100.0)));
}


float AD520X::getPercentage(uint8_t pm)
{
  if (pm >= _pmCount) return 0;
  uint8_t v = _value[pm];
  if (v == 0) return 0.0;
  return (100.0 / 255.0) * v;
}


void AD520X::reset(uint8_t value)
{
  digitalWrite(_reset, HIGH);
  digitalWrite(_reset, LOW);
  setAll(value);
}


void AD520X::setSPIspeed(uint32_t speed)
{
  _SPIspeed = speed;
  _spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE1);
};


/////////////////////////////////////////////////////////////////////////////
//
// PROTECTED
//
void AD520X::updateDevice(uint8_t pm)
{
  digitalWrite(_select, LOW);
  if (_hwSPI)
  {
    mySPI->beginTransaction(_spi_settings);
    mySPI->transfer(pm);
    mySPI->transfer(_value[pm]);
    mySPI->endTransaction();
  }
  else      //  Software SPI
  {
    swSPI_transfer(pm);
    swSPI_transfer(_value[pm]);
  }
  digitalWrite(_select, HIGH);
}


//  simple one mode version
void AD520X::swSPI_transfer(uint8_t val)
{
  uint8_t clk = _clock;
  uint8_t dao = _dataOut;
  for (uint8_t mask = 0x80; mask; mask >>= 1)
  {
    digitalWrite(dao,(val & mask));
    digitalWrite(clk, HIGH);
    digitalWrite(clk, LOW);
  }
}


/////////////////////////////////////////////////////////////////////////////
//
//  DERIVED CLASSES
//
AD5206::AD5206(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
             : AD520X(select, reset, shutdown, dataOut, clock)
{
  _pmCount = 6;
}


AD5204::AD5204(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
             : AD520X(select, reset, shutdown, dataOut, clock)
{
  _pmCount = 4;
}


AD8403::AD8403(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
             : AD520X(select, reset, shutdown, dataOut, clock)
{
  _pmCount = 4;
}


AD8402::AD8402(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
             : AD520X(select, reset, shutdown, dataOut, clock)
{
  _pmCount = 2;
}


AD8400::AD8400(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
             : AD520X(select, reset, shutdown, dataOut, clock)
{
  _pmCount = 1;
}

// -- END OF FILE --

User avatar
mikeysklar
 
Posts: 14180
Joined: Mon Aug 01, 2016 8:10 pm

Re: Trying to use AD8400 with Metro ESP32-S2

Post by mikeysklar »

The library you are using likely needs some patching for esp32-s2 support.

This is digital pot will probably be easier for you to use with Metro ESP32-S2 with the Arduino IDE or CircuitPython.

product:
https://www.adafruit.com/product/4286

guide:
https://learn.adafruit.com/ds3502-i2c-potentiometer

User avatar
muttstang
 
Posts: 86
Joined: Mon May 10, 2021 3:24 pm

Re: Trying to use AD8400 with Metro ESP32-S2

Post by muttstang »

Thanks. I saw that one. It has to be 1k though for this application and run at 3.9v on one end to ground on the other. I’m going to try to use an i2c pot and just issue the commands without a specific library. If that fails then I’ll use an incremental pot.

I was just hoping to get it working with the ad8400 since I made a custom board for it

User avatar
muttstang
 
Posts: 86
Joined: Mon May 10, 2021 3:24 pm

Re: Trying to use AD8400 with Metro ESP32-S2

Post by muttstang »

Yay, I got the AD5273 digipot working using just the Wire.h library. I can read and write to it and the multimeter is getting proper readings from the wiper. :)

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”