Following the bare bones Arduino power supply with LCD of my previous post, I wanted to fix the problem that the load voltage (V_load) will vary when the current varies, because of the voltage drop over the shunt resistor V_shunt, as the DC/DC converter supplies a constant V_out = V_shunt + V_load. The ultimate goal is to make a power supply that can ‘lock in’ a constant voltage independent of current drawn.

The obvious solution is to let the Arduino microcontroller control the potentiometer on the DC/DC converter, with a digital potentiometer. I got the MCP4151-103, a 10K digital potentiometer with 256 steps over SPI. The connection with Arduino is quite standard as described here. I found out in these schematics that the original trim pot on the DC/DC converter is actually not using its 3 legs independently, so that would call for a digital rheostat rather than a potentiometer, but the MCP4151 does the job too. DC/DC converter on the left with digital potentiometer on breadboard connected to an Arduino in the back. Output voltage is divided over a shunt 5ohm resistor (to be able to measure current later) and a simulated load of 40ohm. The load voltage goes into a voltage divider ; 1/3 of the load voltage goes into an analog pin of the Arduino (Aref = 5V).

The DC/DC converter is quite stable, so if we would map the digital potentiometer values to the output voltages, we could just use a table to set the pot value corresponding with the target voltage. However, if we want to measure current (with a shunt resistor), then the voltage over the shunt resistor V_shunt will vary according to the current, and also V_load will vary (V_out remaining stable). If we try to keep V_load stable, we can use a typical PID controller setup. Arduino has an excellent PID library. It uses 3 variables:

• input: output_voltage (in Volts)
• setpoint: target_voltage (in Volts)
• output: pot_level (to send to the digital potentiometer 0-255)

There are 3 parameters to tune the PID controller: Kp, Ki, Kd. The PID did work with the default values in the library example sketch, but it was very slow. I tried the PIDautotune library to find the optimal values for these 3 parameters, but couldn’t get that to work. To experiment with different values i really needed to see what was happening in a real-time graph. So i used a simple Processing sketch to visualise the output of the Arduino sketch (output_voltage).

The Arduino sketch changes the target_voltage every 5 seconds to a random integer value between 3V and 9V. With a good set of K parameters the transitions are very short, less than 1 second. The graph shows that increasing the voltage goes a lot faster than decreasing it.

Next step is to see how the PID control reacts to a varrying load when we use a shunt resistor. To keep the V_load constant, the PID will need to adjust the V_out. I used a 5V target with a load of 40ohm, drawing a 130mA current, and switching this load on and off quickly, causing the spikes. And for reference the current version of the Fritzing schematics of the above project.

I used an Industruino PROTO to give this project a nice permanent home and i am using it frequently as my testing power supply. Below the code for the basic PID sketch (without shunt):

```/* dig pot MCP4151
create voltages of 0-1-2-3-4-5V over wiper-GND
1: CS      D4
2: SCLK    D13 (on leonardo use ICSP header!! SCK)
3: SI      D11 (on leonardo use ICSP header!! MOSI)
4: GND
5: 5V
6: wiper
7: GND
8: 5V
Tom Tobback March 2015
*/
#include <SPI.h>
#include <PID_v1.h>

// Set digital pin 4 as slave select for digital pot:
const int pot_pin = 4;
double pot_level = 0;    // between 0-255                PID OUTPUT  (default output is 0-255 = correct)
double output_voltage;   // measured output voltage      PID INPUT
double target_voltage = 5;   // target output voltage        PID SETPOINT
long last_send = 0;      // for processing graph

// PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
PID myPID(&output_voltage, &pot_level, &target_voltage,2,5,1, DIRECT);

void setup()
{
//  analogReference(EXTERNAL);   // put 5V on AREF
pinMode(pot_pin, OUTPUT);
pinMode(3, INPUT);
SPI.begin();
Serial.begin(9600);
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(50);
myPID.SetTunings(10,200,0);
}
void loop()
{
if (Serial.available() > 0)
{
target_voltage = Serial.parseInt();
Serial.println(target_voltage);
}

if (digitalRead(3) == HIGH)   // manual switch during processing graph
{ target_voltage = 5; }
else
{ target_voltage = 3; }

output_voltage = 3 * 3.3 * float(read_voltage) / 1023;

myPID.Compute();
digitalPotWrite(pot_level);

if (millis() - last_send > 50)   // don't send to often to Serial for processing graph
{
Serial.println(output_voltage);
last_send = millis();
}
//    Serial.print("V\t");
//    Serial.println(pot_level);
//    delay(100);
}
int digitalPotWrite(int value)
{
// Take the SS/CS pin low to select the chip:
digitalWrite(pot_pin, LOW);
// Send in the address and value via SPI:
SPI.transfer(0);
SPI.transfer(value);
// Take the SS/CS pin high to de-select the chip:
digitalWrite(pot_pin, HIGH);
}

```
Digital power supply with PID control

### 4 thoughts on “Digital power supply with PID control”

• 17/11/2016 at 01:26

Hello!
Are you willing to share your sketch?
I am working on a very similar project and am having trouble getting the code to work the way I want it to.
The PID library seems to need the input to be directly from an input pin, but I need it to do math to the value read from the input pin first and it just gives an output of 0 that way.

• 18/11/2016 at 08:17
• 