I'm trying to get an MCP4725 to set the voltage on a power supply which as an 0-20.00V output and at the moment it uses potentiometer's to set the voltage and current, My idea is just to use one rotary encoder to set both and have a few memory buttons. Only working on the voltage side at the moment, Current will be looked at later once I've done the voltage side. The MCP4725 and the ADS1115 are working correctly.
The potentiometer gives a voltage reading of 1.255V (0V) to 4.985V (20.00V)to set the output voltage from 0-20.00V.
Example1 Dac value of 1893 gives a voltage of 2.1118 setting the output of the power supply to 5.013V and then I press the output on button to give the 5.01V output.
Example2 Dac value of 2632 gives a voltage of 2.942 setting the output of the power supply to 10.02V and then I press the output on button to give the 10.02V output.
What I'm trying to achieve is so when I turn the Rotary encoder instead of showing the dac value of 1893 (5.01V out)I'm trying to get the set value to display 5.00V so I know what the output voltage will be before I turn it on.
I've tried so many ways by using the Dac value, using the second channel on the ADC to read the dac output voltage I've got a little lost and may be over thinking it.
Is there away I could work this out ?
Here's the code
#include <Wire.h>
#include <TimedAction.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7); //0x27 is the default address of the LCD with I2C bus module
#include <SPI.h>
#include <Encoder.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
Adafruit_MCP4725 dacB; // constructor
#include <Adafruit_ADS1015.h> //Include the libarary for 16Bit A/D converter
#define VOLTS_CHAN0 0 //channel 1 value
#define VOLTS_CHAN1 1 //chanel2 value
Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
uint16_t err1; //ADC0 variable
uint16_t err2; //ADC1 variable
float Vmultiplier = 0.0001875F; // used to convet readings this is calculated
float Vmultiplier1 = 0.0001875F; // used to convet readings this is calculated
float Vresults0; // Holds raw battery voltage value
float Vresults1; // Holds raw battery current value
float Voltage1 = 0.0;
float Voltage2 = 0.0;
const int pinBtnEncV = 8;
const int pinBtnEncC = 7;
int DAC8574_Ch2_Val = 0;
const int pinEncV1 = 2;
const int pinEncV2 = 3;
const int pinEncI1 = 6;
const int pinEncI2 = 9;
float r1 = 47000.0;
float r2 = 6200.0;
const int pinCSV = 10;
const int pinCSI = 18;
float Actual_volt = 0;
float Set_volt = 0;
int buttonPins[] = {
pinBtnEncV, pinBtnEncC
};
int buttonReadings[1];
int lastButtonStates[] = {
HIGH, HIGH
};
int currentButtonStates[] = {
HIGH, HIGH
};
long lastDebounceTime[1];
long oldEncPositions[] = {
-999, -999
};
long curEncPositions[] = {
0, 0
};
long encoderValues[] = {
0, 0
};
int DACSetSteps[] = {
1, 1
};
int loopCounter = 0;
Encoder VEnc(pinEncV1, pinEncV2);
Encoder IEnc(pinEncI1, pinEncI2);
void TimerService01();
TimedAction Timedact01 = TimedAction(80, TimerService01); // mS
void TimerService02();
TimedAction Timedact02 = TimedAction(250, TimerService02); // mS
void getCurrentEncPositions()
{
curEncPositions[0] = VEnc.read();
curEncPositions[1] = IEnc.read();
for (int i = 0 ; i < 2 ; i++) {
if (curEncPositions[i] != oldEncPositions[i])
{
if (curEncPositions[i] > oldEncPositions[i]) {
encoderValues[i] += DACSetSteps[i];
if (encoderValues[i] > 4095) encoderValues[i] = 4095;
}
else {
encoderValues[i] -= DACSetSteps[i];
if (encoderValues[i] < 0) encoderValues[i] = 0;
}
oldEncPositions[i] = curEncPositions[i];
}
}
}
void setup() {
for (int V = 0 ; V < 2 ; V++) {
pinMode(buttonPins[V], INPUT);
digitalWrite(buttonPins[V], HIGH);
}
dacB.begin(0x62); // The I2C Address: Run the I2C Scanner if you're not sure
DAC8574_Ch2_Val = 1763;
dacB.setVoltage(DAC8574_Ch2_Val, false);
lcd.begin(20, 4);
lcd.setBacklightPin(3, POSITIVE); // BL, BL_POL
lcd.setBacklight(HIGH); //set LCD backlight on
lcd.clear();
ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
ads.begin(); //start the 16bit A/D converter
pinMode(pinCSV, OUTPUT);
digitalWrite(pinCSV, HIGH);
pinMode(pinCSI, OUTPUT);
digitalWrite(pinCSI, HIGH);
}
void loop() {
getCurrentEncPositions();
Timedact01.check();
// check the dac button with debonce and double the gain
for (int i = 0; i < 2; i++) {
buttonReadings[i] = digitalRead(buttonPins[i]);
if (buttonReadings[i] != lastButtonStates[i]) lastDebounceTime[i] = millis();
if (millis() - lastDebounceTime[i] > 50) {
if (currentButtonStates[i] != buttonReadings[i]) {
currentButtonStates[i] = buttonReadings[i];
if (currentButtonStates[i] == LOW) {
DACSetSteps[i] *= 10;
if (DACSetSteps[i] > 100) DACSetSteps[i] = 1;
}
}
}
lastButtonStates[i] = buttonReadings[i];
}
Timedact02.check();
DAC8574_Ch2_Val = encoderValues[0];
dacB.setVoltage(DAC8574_Ch2_Val, false);
}
void TimerService01() {
//#################################################################
//# Read both ADC channels #
//#################################################################
//Read BAttery volatage
err1 = ads.readADC_SingleEnded(VOLTS_CHAN0) ; // Ch.0 (3) 16bit
Voltage1 = err1 * Vmultiplier ; //conert to float
Actual_volt = Voltage1 / (r2 / (r1 + r2)); //convert to real time reading
err2 = ads.readADC_SingleEnded(VOLTS_CHAN1) ; // Ch.1 (3) 16bit
Voltage2 = err2 * Vmultiplier1 ;// Convert to actual input v
Voltage2 -= 0.811; //set the reading to zero but show a minius
Set_volt = Voltage2 * 4.096; ///this is wherer I've tried differtn methods to set voltage to read saem as actual voltage
}
void TimerService02() {
lcd.setCursor(0, 0);
lcd.print("V Set = ");
lcd.print(Set_volt, 2);
lcd.print(" V");
lcd.setCursor(0, 1);
lcd.print("V ACT = ");
if ( Actual_volt >= 6.5) {
lcd.print(Actual_volt, 2);//DAC8574_Ch2_Val
} else {
lcd.print(Actual_volt, 3);//DAC8574_Ch2_Val
}
lcd.setCursor(0, 2);
lcd.print("D VAL = ");
lcd.print(DAC8574_Ch2_Val);//DAC8574_Ch2_Val
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(Voltage2);//DAC8574_Ch2_Val DACSetSteps[i]
lcd.print(" : ");
lcd.print(err2);//display channel 1 raw value
lcd.print(" ");
}