Variable Power Supply from Targus PA350

IMG_20160316_084114Continuing on the theme of power supplies and related, I thought I would try my hand at making a bench top variable power supply based on a universal laptop adapter. My rationale is that these adapters are made to run on 11-16V, so I could run it off whatever power is available (the 12V bus on my workbench, a battery, from mains by using another power adapter upstream, or even off the car); considering where I live and the reliability of electrical power, this seemed like a good idea. Also, these brick power supplies are, well, built like a brick, and are designed to tolerate abuse.

I originally came across a posting about converting a Kensington model 33197, which seems idea for this purpose because it has two wires for power/ground, and one each for sensing voltage and current that are set by resistors to a fifth wire that carries 5V. Since then, I’ve seen other articles along similar lines.

My plan was to do something similar, but I wanted to add the twist of being able to set a current limit above which power would be entirely cut to the load until reset. I anticipated using a microprocessor and thought the project wouldn’t be to complicated… but that turned out not to be the case. The power adapter is finicky about turning on into loads, doesn’t like being reset, and I haven’t managed to get more than 15W output from it. That said, I now have it working, but its capabilities fall short of what I had anticipated.

Screen Shot 2016-05-08 at 11.21.33 AMUnlike the Kensington supply described above, there are only four wires in the output from the supply – power (yellow), ground (shield), voltage select (grey), and a red wire, which I assume relates to current (or total power), but which does not seem as straightforward to manipulate.

Testing into a 0.5A load, with the grey wire unconnected, its voltage is 5.12V and output voltage is 16. 1V. If the grey wire is pulled up or down, voltage output varies linearly from 3 volts to 23.2V. No problem with setting voltage.

Unconnected, the red wire’s voltage measures 4.66V. Pulling down the voltage on the red wire, the supply rolls voltage at different loads – the lower the voltage on red, the lower the load limit. Pulling up the voltage doesn’t seem to matter, though. In testing the supply, it looks like there is a hard limit of total power of 15W regardless of what is going on with the red wire. I tested at various voltage settings – voltage rolls off (and in some cases, the supply quits) when load goes above 1A at 15V, 1.5A at 10V, 2A at 7.5V, etc. This has me scratching my head, because the supply is labeled “70W” continuous. The input voltage and current look consistent with this, but I can’t coax more than 15W from the supply. Clearly, I’m missing something.

Setting that aside for the moment, I wanted to set up a means of setting the current limit (without having any load attached). I had a couple small value resistors left over from another project, so I built the circuit around them as a shunt. The voltage above the resistor is amplified by an LM324 op-amp, with the gain set such that the desired current range would fall between ground and vcc – 1.5 (the output limits of this op-amp). Another sub-unit of the op-amp is used to set the current limit. A third sub-unit is simply a comparator, which weighs the current sensed versus the current limit, and if the sensed current exceeds the limit, it goes high, signaling the microprocessor that there is an over-current condition.

targuspa350v5jjw2-38

When that occurs, the microprocessor sends a disable signal that cuts voltage, and literally disables output by opening a relay on the power supply output. The current limit is constantly updated on an LED display, but when an over-current condition occurs, it reads “HI C”. That was the best I could come up with for a 7-segment display. The processor then holds this state until it is reset.

IMG_20160507_130609

Resetting the processor involves more than turing it on and off. After the reset pin in brought low, when it starts up, it sends a disable signal for a quarter second to give the supply a bit of time to come up. If a load is immediately applied, the supply puts out a fraction of a volt and stays stuck in that mode. I presume that this period is needed to charge capacitors in the supply. After the relay closes and the power supply is connected to the load, there is another short wait state to allow the relay to mechanically close and for current to stabilize. This period is very short, about ten milliseconds, and then the microprocessor enters its event loop, waiting for detection of an over-current signal and update the current limit display.

IMG_20160507_130617

For microprocessor, I prototyped with an arduino duemilanove, but in the final version I used an ATTINY 85. This mean adding the ATTINY core to my Arduino IDE. Since I had fewer I/O pins, I used a 7-segment display with I2C backpack from Adafruit. In order to drive the display I included the TinyWireM.h library and the Tiny_LedBackpack.h. The first library facilitates the two-wire interface, and the latter adapts a graphics library to the smaller resources available on an ATTINY. Fuses are set to use the 8Mhz internal clock. The code size is just a hair too large to fit on an ATTINY45, but I didn’t worry about optimizing this because when I bought ATTINYs the 45 cost more than the 85.

For this project, I used a red volt/amp display similar to the red/blue I had incorporated into the previous power supply and electronic load. Of the two, I prefer the red/blue version. The red-only unit takes a second to start display (presumably, its internal MPU booting). Also, I had to adjust the calibrate the current by turning the potentiometer near R13, below, where as the red/blue units were accurately calibrated for voltage and current right out of the box. Finally, the red/blue units look better and are brighter at a given voltage. Functionally, though, they seem equivalent.

IMG_20160507_130058

The current limit is polled periodically and displayed, but the number would jump around somewhat erratically if not smoothed in some manner. There is a lot of commentary about getting consistent values from ADC reads, and techniques to mitigate this include changing ADC acquisition time, reducing system and MPU noise, and numerical techniques for filtering. I went with the simplest approach: data averaging. I read the ADC 100 times and then average over a 200 ms period. The reads are not blocking; the new number to display is calculated after the 100th read and displays.

A fudge factor is needed to adjust the current limit displayed versus the voltage measured above the shunt. This factor cannot be precisely calculated because of component variances, i.e., the exact resistance of the shunt including all connections, the precise gain of the op-amp (which relies on 1% tolerance resistors), etc. I determined the fudge factor for my unit empirically and observe that the current limit relationship seems linear over the range of currents tested, i.e., about 0 to 2.5A.

For maximum flexibility in terms of power sources, AC-adapter and battery inputs are OR’d together through some hefty Schottky diodes on a small board. Which ever is higher voltage ends up supplying the Targus brick, so I chose an adapter that outputs 15VDC. My lead acid batteries never get above 14V, so I can leave them attached to provide seamless backup power without having to worry that they will discharge. As usual, I used Anderson power pole connectors for battery power input.

IMG_20160508_103817

I have not yet boxed up the project because I still want to play with it and see if I get find a way to get more current / power out. Any suggestions are welcome.

Here’s the sketch:

/*
Monitor targus power supply for over current condition
*/

#include <TinyWireM.h>
#include <Tiny_LEDBackpack.h>

/* for ATTINY 85 */
#define CURRENT_LIMIT  A2
#define OVER_CURRENT   1           // hi means over current condition exists
#define DISABLE        3           // setting high will kill output voltage
#define FUDGEFACTOR    17120       // about 200*NUMBER_SAMPLES

#define NUMBER_SAMPLES 100

Tiny_7segment matrix = Tiny_7segment();

boolean overLoaded = false;
int currentLimitSampled[NUMBER_SAMPLES];
unsigned long lastSampleTime = 0;
unsigned long sampleDelayTime = 2;
int sampleIndex = 0;
float amps = 0;

void setup() {
  matrix.begin(0x70);
  matrix.clear();
  matrix.writeDisplay();
  pinMode(OVER_CURRENT, INPUT);
  pinMode(DISABLE, OUTPUT);
  digitalWrite(DISABLE, HIGH);
  delay(250);
  digitalWrite(DISABLE, LOW);
  delay(10);
}

void loop() {

  if (!overLoaded) {
    if (digitalRead(OVER_CURRENT)) {
      digitalWrite(DISABLE, HIGH);
      overLoaded = true;
      matrix.writeDigitRaw(0, 118);
      matrix.writeDigitRaw(1, 6);
      matrix.writeDigitRaw(3, 0);
      matrix.writeDigitRaw(4, 57);
      matrix.writeDisplay();
      while(true){;}
    }
    if ((millis() - lastSampleTime) > sampleDelayTime) {
      if (sampleIndex < NUMBER_SAMPLES) {
        currentLimitSampled[sampleIndex] = analogRead(CURRENT_LIMIT);
        sampleIndex++;
        if (sampleIndex == NUMBER_SAMPLES) {
          amps = 0;
          for (sampleIndex = 0; sampleIndex < NUMBER_SAMPLES; sampleIndex++) {
            amps += currentLimitSampled[sampleIndex];
          }
          sampleIndex = 0;
          amps /= FUDGEFACTOR;
        }
      }
      if (amps==0){
        matrix.print(0.00);
      }
      else {
        matrix.print(amps, 2);
      }
      matrix.writeDisplay();
      lastSampleTime = millis();
    }
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *