Using two DACs with Arduino

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Using two DACs with Arduino

Post by holdy97 »

Hello,

Currently I am using the MCP4725 12-Bit DAC on my arduino. I now need to use a second one. 2 questions.

Does the A0 pin get tied to high for both the DACs?

Second, when using the command setVoltage(), how do I configure which DAC it is referring to?

Thanks

User avatar
adafruit_support_carter
 
Posts: 29056
Joined: Tue Nov 29, 2016 2:45 pm

Re: Using two DACs with Arduino

Post by adafruit_support_carter »

Does the A0 pin get tied to high for both the DACs?
Nope. Just on one. That way each will have a unique I2C address, which is required.
Second, when using the command setVoltage(), how do I configure which DAC it is referring to?
You'll end up creating two separate instances. So you'd just call setVoltage on whichever one you want, or both, etc.

Also, don't forget to pass in the non-default I2C address in the call to begin() for the board with the A0 jumper set.

I2C scanning might also be helpful at some point just to verify both DAC's can be seen and report the expected addresses:
https://learn.adafruit.com/scanning-i2c-addresses

User avatar
adafruit_support_bill
 
Posts: 88037
Joined: Sat Feb 07, 2009 10:11 am

Re: Using two DACs with Arduino

Post by adafruit_support_bill »

You need to configure the boards with 2 different addresses so they don't conflict on the i2c bus. Leave A0 unconnected on one for the default address of 0x62. tie the other one to VDD for and address of 0x63.

You will need to create two instances of the device in your code. Pass the i2c address to the begin() function for each one:

Code: Select all

dac1.begin(0x62);
dac2.begin(0x63);

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

Thank you guys very much for the response. I will work on getting this working

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

Hi again,

A strange error I am getting. Currently, I use the begin() command in the setup, and then use setVoltage() in the loop.

When I name it just 'dac' (ie dac.begin()), things work fine. When I change the name to, for instance, 'dac1' (ie dac1.begin()), I get an error that dac1 was not declared in the scope of the loop.

Why would it not let me change the name?

Thanks

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

Code: Select all

//////////////////////////////// INITIALIZATION /////////////////////////////////'
// Include Libraries
   #include <LiquidCrystal.h>
   #include <Wire.h>
   #include <Adafruit_MCP4725.h>

   #define DAC_RESOLUTION    (8)

   Adafruit_MCP4725 dac;

// Initialize Variables
   static char outstr[15]; // used to print float variables to monitor
   int tachPin = 2; // input pin on arduino of tachometer
   int count = 0; // stores number of tachometer pulses
   unsigned long preTime;
   unsigned long preTimeControl;
   unsigned long postTime;
   unsigned long postTimeControl;
   unsigned long simTime; // simulation time
   unsigned long startTime; // simulation start time
   float rpm; // sensed speed [rpm]
   float rpm_filt1 = 0; // filtered speed [rpm]
   float lastFiltered1 = 0; // initialize previous filtered output (control filter)
   float rpm_filt2 = 0; // filtered speed [rpm]
   float lastFiltered2 = 0; // initialize previous filtered output (lcd filter)
   float elapsedTime; // amount of time elapsed [us]
   float elapsedTimeControl; // elapsed time since last control
   float integralAdd; // amount to be added to integral error
   float integralSum = 0; // the integrated error
   float error = 0; // error signal
   float u; // control input
   float u_pwm; // control input in pwm units
   int u_bin; // control input in 12-bit binary
   //int controlPin = 3; // pin for control signal
   int valvePin = 4; // pin for valve on/off
   int iteration = 1; //
   float inp;
   float aveError = 0; // average error of previous iterations
   int counter = 0; // counter for adding to array
   bool converged = false; // intitialize converged boolean
   int inp1;
   int inp2;
   float speedVoltage; // analog voltage to spend speed to pixey chassey

// Instantiate LCD
   LiquidCrystal lcd(7,8,9,10,11,12);

// SET DESIRED SET POINT [rpm]
   float ref = 104000;

// SAMPLE TIME [s]
   float del_t = .075; // measurement time [s]
   float f_s = 1/del_t; // sample frequency

// Control Time [s]
   float del_t_control = .15; // good value, 0.175
   int steps = round(del_t_control/del_t);

// INTEGRAL GAIN
   float k_i = 2.5e-5; // good value, 1.5e-5

// Filter parameters
   float f_c1 = 1/del_t_control; // control frequency (cutoff frequency for filter)
   float alpha1 = (2*3.14*del_t*f_c1) / (1 + 2*3.14*del_t*f_c1); // control filter time constant

   float del_t_lcd = 0.5; // how often to display speed on LCD
   float f_c2 = 1/del_t_lcd; // control frequency (cutoff frequency for filter)
   float alpha2 = (2*3.14*del_t*f_c2) / (1 + 2*3.14*del_t*f_c2); // control filter time constant

// Convergence Parameters
   const int numPast = 30; // number of iterations to store previous error for
   float pastErrors[numPast];  
   float tol = 60/del_t - 200; // tolerance for speed convergence (error per pulse - 200) 

//////////////////////////////////// SETUP //////////////////////////////////////

void setup() {

// Begin serial communication, 9600 bits/sec
   Serial.begin(9600);

// Attach interrupt
   attachInterrupt(digitalPinToInterrupt(tachPin), ISR_func, RISING);

// Turn on LCD
   lcd.begin(40, 8);

// Start DACs
   dac1.begin(0x62); // start DAC for control voltage signal
   //dacSpeedSend.begin(0x63); // start DAC for analog speed signal to Scott

// Initialize other variables
   for (int i = 0; i < numPast; i++) // initialize array of pastErrors
   {pastErrors[i] = tol;}
   pinMode(valvePin, INPUT);

// Reference Speed Input
   pinMode(6,OUTPUT);
   digitalWrite(6,LOW); //
    
// Initialize Timers
   preTime = micros();
   preTimeControl = micros();

}

//////////////////////////////////// MAIN LOOP ////////////////////////////////////

void loop() {

// Check if system is running
  int check = digitalRead(valvePin); // check if system is running

  if (check == 1) { // if system is running

    if ( analogRead(A2) < 100)
       {digitalWrite(6,LOW);}

    if (iteration == 1) // reset clock on first iteration
       {startTime = micros();}

    if (iteration % (round(0.5 / del_t)) == 0) // print speed to LCD
       {lcd.clear(); lcd.print(round(rpm_filt2));}
      
    if (counter > (numPast - 1)) // reset array index
       {counter = 0;}

// Delay
    delay(del_t * 1000); // sampling delay [ms]
    postTime = micros();

// Calculate sensed speed
    elapsedTime = (postTime - preTime) / 1e6; // elapsed time since last measurement [s]
    rpm = ((count) / elapsedTime) * 60; // sensed speed [rpm], use this if using flip flop
    preTime = postTime; // update time
    count = 0; // reset tachometer count
    simTime = micros() - startTime; // simulation time stamp

// Filter speed
   rpm_filt1 = alpha1*rpm + (1-alpha1)*lastFiltered1;
   rpm_filt2 = alpha2*rpm + (1-alpha2)*lastFiltered2;
   lastFiltered1 = rpm_filt1; // update
   lastFiltered2 = rpm_filt2; // update

// Only Perform Control on iteration 1 and then del_t_control
   if ( (iteration % steps == 0 ) || (iteration == 1) )
   {
   postTimeControl = micros();
// Calculate Error Signal
   error = ref - rpm_filt1; // error signal
   //error = ref - rpm; // error signal
   pastErrors[counter] = error; // add to previous errors
   if (converged == false)
      {
      aveError = 0;
      for (int i = 0; i < numPast; i++) // initialize array of pastErrors
      {aveError += abs(pastErrors[i])/numPast;}
      } // calculate the average error of the last 'numPast' readings
   else
      {aveError = 0;}

// Calculate Control Input
   elapsedTimeControl = (postTimeControl - preTimeControl) / 1e6;
   integralAdd = error * elapsedTimeControl; // amount to add for current step
   if (integralAdd > .5 / k_i)
       {integralAdd = .5 / k_i;} // cap the integrated error for current step to represent ~1V of added control input
       
   integralSum += integralAdd; // integrated error
    
   if (aveError < tol)
       {u = u; converged = true;}
    
   else
       {u = inputSat(k_i * integralSum);} // control input

// Apply control input
   u_bin = round((u / 5) * 4095); // convert to 12-bit
   dac1.setVoltage(u_bin, false);

   preTimeControl = postTimeControl; // reset control time 

// Save Data
//   inp = analogRead(A1);//*5/1023; // read input control voltage
//   float inpV = inp * 5 / 1023;
//   Serial.print(simTime / 1e6); Serial.print("\t"); // A
//   Serial.print(dtostrf(u ,2, 4, outstr)); Serial.print("\t"); // B
//   Serial.print(rpm); Serial.print("\t");           // C
//   Serial.print(error); Serial.print("\t");         // D
//   Serial.print(aveError); Serial.print("\t");      // E
//   Serial.print(integralSum); Serial.print("\t");   // F
//   Serial.print(inpV); Serial.print("\t");          // G
//   Serial.print(ref); Serial.print("\t");           // H
//   Serial.print(rpm_filt1); Serial.print("\t");     // I
//   Serial.print(rpm_filt2); Serial.print("\t");     // J
//   Serial.println(iteration);                       // K

   counter++; // update array counter
      
   } // end of control operations

// Update Variables for next iteration
   iteration++; // update iteration number

  } // end of system running

  else // else system is not running
     {integralSum = 0;
      float val = analogRead(A2);
      Serial.println(val);
      if ( val > 100 )
         {ref = val/1023*200000 ; digitalWrite(6,HIGH);}
     }

} // end of void loop

//////////////////////////////////// FUNCTIONS ////////////////////////////////////

void ISR_func() { // interrupt function to increase counter

  count += 1;

}

float inputSat (float u) { // function for input saturation
  if (u > 3.5) // check saturation limits
  {
    u = 3.5;
  }
  else if (u < 0)
  {
    u = .1;
  }

  return u;
}

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

If you run this code as is, it will not compile.

If you change the name back to just 'dac', it compiles. How do I change the name so I can use both dacs and not get an error? Thanks

User avatar
adafruit_support_bill
 
Posts: 88037
Joined: Sat Feb 07, 2009 10:11 am

Re: Using two DACs with Arduino

Post by adafruit_support_bill »

Code: Select all

   Adafruit_MCP4725 dac;
You have not declared a 'dac1'. You have only declared one MCP4725 object named "dac".

As Carter said above, you need create 2 separate instances of the dac object.

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

I'm dumb for missing that,

Sorry and thank you for catching it

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

Are there limitations on when setVoltage() can be used?

I have both connected now, both show up on the 12C scanning at the correct addresses, but the 2nd one does not output any voltage despite me calling it to. Wiring is correct, I cannot find what the source of this issue could be.

User avatar
adafruit_support_bill
 
Posts: 88037
Joined: Sat Feb 07, 2009 10:11 am

Re: Using two DACs with Arduino

Post by adafruit_support_bill »

Please post a photo or two showing all your connections - and also the code you are using.

User avatar
holdy97
 
Posts: 19
Joined: Wed Sep 28, 2022 5:45 pm

Re: Using two DACs with Arduino

Post by holdy97 »

Another small bug, working properly now. Thanks for all the help!

User avatar
adafruit_support_bill
 
Posts: 88037
Joined: Sat Feb 07, 2009 10:11 am

Re: Using two DACs with Arduino

Post by adafruit_support_bill »

Good to hear you've got it going. Thanks for the update.

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

Return to “Other Arduino products from Adafruit”