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
Using two DACs with Arduino
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_carter
- Posts: 29473
- Joined: Tue Nov 29, 2016 2:45 pm
Re: Using two DACs with Arduino
Nope. Just on one. That way each will have a unique I2C address, which is required.Does the A0 pin get tied to high for both the DACs?
You'll end up creating two separate instances. So you'd just call setVoltage on whichever one you want, or both, etc.Second, when using the command setVoltage(), how do I configure which DAC it is referring to?
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
- adafruit_support_bill
- Posts: 88145
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using two DACs with Arduino
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:
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);
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
Thank you guys very much for the response. I will work on getting this working
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
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
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
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
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;
}
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
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
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
- adafruit_support_bill
- Posts: 88145
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using two DACs with Arduino
Code: Select all
Adafruit_MCP4725 dac;
As Carter said above, you need create 2 separate instances of the dac object.
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
I'm dumb for missing that,
Sorry and thank you for catching it
Sorry and thank you for catching it
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
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.
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.
- adafruit_support_bill
- Posts: 88145
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using two DACs with Arduino
Please post a photo or two showing all your connections - and also the code you are using.
- holdy97
- Posts: 19
- Joined: Wed Sep 28, 2022 5:45 pm
Re: Using two DACs with Arduino
Another small bug, working properly now. Thanks for all the help!
- adafruit_support_bill
- Posts: 88145
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using two DACs with Arduino
Good to hear you've got it going. Thanks for the update.
Please be positive and constructive with your questions and comments.