Bench Power Supply 2.0
0-25v @ 0-5Amp
I need someone to correct my grammatical error, thanks
History
This project is like the one that all of you must have done in electronics. I took the idea from Circuit Cellar. The original power supply provides an output of 2.5-15V at 500mA. This circuit will provide 0-25V at 0 to 5A. You will see there is a lot of modification to achieve this.
This is my second version of this power supply, the first one was made with mosfet who need a higher voltage on the gate I had to use a higher input voltage and because of this there was a lot of heat generated for nothing. This version work with transistor and it's much more better.
I will explain you some part of this power supply. First you must find a transformer which can handle 24VAC at 5A and one with 6.3VAC at 100ma. I use 2 transformator to have 2 DC level 30V and 40V. The 30V Power the high current for the output and the 40V power all the rest of the circuit. The LT7013 opamp is split in 2 function, the part A is the voltage control and the part B is the current control both opamp output is connected together via diode so the one who output a lower voltage win on the second, so if you set your voltage to 10V and your current to 1A and you short your ouput the current part will pull down his output and the voltage will drop. The current part use a very nice component the ZXCT1009 that work like a current mirror. it will generate a current proportionally the the one who pass in the sense resistor, this current is pass in the pot R8 who convert it in voltage. The output have many transistor because the opamp can't give a lot of current, and note that the resistor R23 is very important, this one will protect your output transistor from a output short circuit "transistor explosion is faster than the current sense". If you build this supply you will be impress how fine it's work.
I also connect to this power supply a LCD to inform you of the set point for voltage and current, plus the current voltage and current. It's done with a small ATMega32 with 4 A/D input to received the value from the power supply and with some simple calculation it display those value.
Features
|
|
Output Voltage adjustable from 0 to 25v |
|
|
Output Current adjustable from 0 to 5amp |
|
|
Digital reading of set points for current & voltage and output current & voltage. |
|
|
No need of multi tap transformer or center tap transformer |
|
|
Short circuit protected |
|
|
Very low cost |
Pictures (from the version 1.0)
Click to enlarge
|
Power supply side view |
LCD Display |
|
Power supply back view |
Power supply front view |
|
LCD Display |
Power supply top view |
Sources codes & Schematics
-Schematic of the powersupply in PDF format
-Schematic of the digital volt & amp reading in PDF format
-Printed Circuit Board of this power supply!!!!
-Circuit cellar inspiration article in PDF format
//*****************************************************************************
//
Powersupply
// Version 1.0 Jan 2007
//
// 1.0 -> -Everything is new
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//
R E T U R N S T A C K 6 4
//
Internal RC oscillator of 8Mhz
//
//*****************************************************************************
//
//
F U S E B I T
//
//( )7 ( )6
( )BL12 ( )BL11 ( )BL02 ( )BL01
( )Lock2 ( )Lock1
//( )7 ( )6
( ) ( ) ( )
( )M103C ( )WDTON ( )
//( )OCDEN ( )JTAGE (X)SPIEN(X)CKOPT
(X)EESAVE ( )BOOTSZ1 (X)BOOTSZ0 (X)BOOTRST
//(X)BODLEV (X)BODEN ( )SUT1 (X)SUT0
( )CKSEL3 (X)CKSEL2 ( )CKSEL1 ( )CKSEL0
//
//*****************************************************************************
//
P I N U S A G E
//
// PA0 -> GND
// PA1 -> ADC Input #1
// PA2 -> ADC Input #2
// PA3 -> ADC Input #3
// PA4 -> ADC Input #4
// PA5 -> GND
// PA6 -> GND
// PA7 -> GND
//
// PB0 -> N/C
// PB1 -> N/C
// PB2 -> N/C
// PB3 -> N/C
// PB4 -> N/C
// PB5 -> N/C
// PB6 -> N/C
// PB7 -> N/C
//
// PC0 -> LCD DB7
// PC1 -> LCD DB6
// PC2 -> LCD DB5
// PC3 -> LCD DB4
// PC4 -> LCD E
// PC5 -> LCD R/W
// PC6 -> LCD RS
// PC7 -> LCD BackLight
//
// PD0 -> N/C
// PD1 -> N/C
// PD2 -> +5
// PD3 -> LED
// PD4 -> N/C
// PD5 -> N/C
// PD6 -> N/C
// PD7 -> LCD Contrast
//
//*****************************************************************************
//
T I M E R U S A G E
//
// Timer 0 not use
// Timer 1 not use
// Timer 2 is use for LCD Contrast
// Timer 3 not use
//
//*****************************************************************************
//*****************************************************************************
//
I N C L U D E
//*****************************************************************************
#include <iom32v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <eeprom.h>
//*****************************************************************************
//
D E F I N E
//*****************************************************************************
#define VERSION
10
#define TRUE
1
#define FALSE
0
#define XTAL
16000000
#define LED
(1<<PD3);
// ADC
#define ADC2
(1<<REFS0) + 2
#define ADC3
(1<<REFS0) + 3
#define ADC4
(1<<REFS0) + 4
#define ADC5
(1<<REFS0) + 5
// LCD
#define LCD_D7
0x01
#define LCD_D6
0x02
#define LCD_D5
0x04
#define LCD_D4
0x08
#define LCD_E
0x10
#define LCD_RW
0x20
#define LCD_RS
0x40
#define LCD_BACKLIGHT
0x80
#define LCD_PIN
PINC
#define LCD_DDR
DDRC
#define LCD_PORT
PORTC
#define LCD_DATA
0x01
#define LCD_CTRL
0x00
#define LCD_C_BLINK_ON
0x09
#define LCD_C_BLINK_OFF
0xfe
#define LCD_C_ON
0x0a
#define LCD_C_OFF
0xfd
#define LCD_DISPLAY_ON
0x0c
#define LCD_DISPLAY_OFF
0xfb
#define LCD_BRIGHT_25
0x23
#define LCD_BRIGHT_50
0x22
#define LCD_BRIGHT_75
0x21
#define LCD_BRIGHT_100
0x20
#define LCD_BACKLIGHT_ON
0x24
#define LCD_BACKLIGHT_OFF
0x25
//*****************************************************************************
//
P R O T O T Y P E
//*****************************************************************************
void main(void);
void Info(void);
void Delay(ushort
Del);
// A/D
void ADInit(void);
void AD_interrupt(void);
// LCD
void LCDInit(ushort
x,ushort y);
void LCDOff(void);
void LCDClrSCR(void);
void LCDGotoXY(ushort,ushort);
ushort LCDWhereX(void);
ushort LCDWhereY(void);
void LCDWriteString(char
*);
void LCDWriteConstString(const
char *);
void LCDWriteChar(char);
void LCDWriteData(ushort,ushort);
ushort LCDReadData(ushort rs);
void LCDCreateCHR(ushort
chnumber, char *ptr);
void LCDWait(void);
void LCDDelay50us(int
Delay);
void LCDTextAttr(ushort
attribute);
void LCDContrast(ushort
Cont);
//*****************************************************************************
//
G L O B A L V A R I A B L E
//*****************************************************************************
// LCD
ushort MaxX, MaxY,
LCDStat;
char Text[20];
// ADC
int AD1;
int AD2;
int AD3;
int AD4;
//*****************************************************************************
//
M A I N
//*****************************************************************************
void main()
{
float VoltSet,Volt,CurrentSet,Current;
WDR();
WDTCR = 0x0f;
// Watch Dog enable
LCDInit(20,2);
ADInit();
DDRD |= LED;
SEI(); //re-enable
interrupts
Info();
Delay(75);
LCDClrSCR();
LCDGotoXY(1,1);
LCDWriteConstString("Vset:
Vout:\0");
LCDGotoXY(1,2);
LCDWriteConstString("Aset:
Aout:\0");
while(1)
{
WDR();
_StackCheck();
PORTD ^= LED;
VoltSet = (((float)(AD2))
* 25) /
1024;
Volt =
(((float)(AD1)) *
25) /
1024;
CurrentSet = (((float)(AD4))
* 4) /
1024;
Current = (((float)(AD3))
* 4) /
1024;
LCDGotoXY(6,1);
csprintf(&Text[0],"%#4.1f\0",VoltSet);
LCDWriteString(&Text[0]);
LCDGotoXY(17,1);
csprintf(&Text[0],"%#4.1f\0",Volt);
LCDWriteString(&Text[0]);
LCDGotoXY(6,2);
csprintf(&Text[0],"%#4.1f\0",CurrentSet);
LCDWriteString(&Text[0]);
LCDGotoXY(17,2);
csprintf(&Text[0],"%#4.1f\0",Current);
LCDWriteString(&Text[0]);
Delay(5);
}
}
/******************************************************************************
Name:
void _StackOverflowed(char c)
Description: This function is
automaticaly called if
the stack crash/
Input:
none
Output:
none
Misc:
******************************************************************************/
void _StackOverflowed(char
c)
{
while(TRUE);
}
/*****************************************************************************
Name:
void Info(void)
Description: Display power on message
Input:
void
Output:
void
Misc:
******************************************************************************/
void Info(void)
{
LCDClrSCR();
LCDGotoXY(1,1);
LCDWriteConstString("PowerSupply
Ver:1.0\0");
LCDGotoXY(1,2);
LCDWriteConstString("Sylvain
Bissonnette\0");
}
/******************************************************************************
Name:
void Delay(ushort Del)
Description: This function make a
delay
Input:
none
Output:
none
Misc:
******************************************************************************/
void Delay(ushort
Del)
{
int i,j;
for (i=0;i<Del;i++)
for (j=0;j<32000;j++)
WDR();
}
/******************************************************************************
Name:
ADCInit(void)
Description: This function initialize
the ADC
Input:
none
Output:
none
Misc:
******************************************************************************/
void ADInit(void)
{
ADCSRA = (1<<ADEN)
+ (1<<ADIE)
+ (1<<ADPS2)
+ (1<<ADPS1)
+ (1<<ADPS0);
ADMUX = ADC2;
ADCSRA |= (1<<ADSC);
// Start AD convertion
}
/******************************************************************************
Name:
AD_interrupt(void)
Description: This function is
automaticaly called when the AD had finish
is convertion
Input:
none
Output:
none
Misc:
******************************************************************************/
#pragma interrupt_handler AD_interrupt:17
void AD_interrupt(void)
{
if (ADMUX
== ADC2)
{
AD1 = (int)((int)ADCH
<< 8)
+ ADCL;
ADMUX = ADC3;
}
else if (ADMUX
== ADC3)
{
AD2 = (int)((int)ADCH
<< 8)
+ ADCL;
ADMUX = ADC4;
}
else if (ADMUX
== ADC4)
{
AD3 = (int)((int)ADCH
<< 8)
+ ADCL;
ADMUX = ADC5;
}
else if (ADMUX
== ADC5)
{
AD4 = (int)((int)ADCH
<< 8)
+ ADCL;
ADMUX = ADC2;
}
ADCSRA |= (1<<ADSC);
// Start AD convertion
}
//*****************************************************************************
// LCD Code
//*****************************************************************************
/******************************************************************************
Name:
LCDCreateCHR
Description: Create a new char in
CGRAM
Input:
ushort : Character number (0-7)
*ushort : 7 ushort containing the data
Output:
none
Misc:
******************************************************************************/
void LCDCreateCHR(ushort
chnumber, char *ptr)
{
ushort i,j;
i = 8
* chnumber;
for (j=0;j<8;j++)
{
LCDWriteData(LCD_CTRL,(0x40
| (i + j)));
LCDWriteData(LCD_DATA,ptr[j]);
}
}
/******************************************************************************
Name:
void LCDClrSCR(void)
Description: Clear the LCD
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDClrSCR(void)
{
LCDWait();
LCDWriteData(LCD_CTRL,0x01);
// Clear display
}
/******************************************************************************
Name:
LCDGotoXY(ushort x, ushort y)
Description: Position cursor on the
LCD at X & Y location
Input:
X -> X position on the LCD
Y -> Y position on the LCD
Output:
none
Misc:
******************************************************************************/
void LCDGotoXY(ushort
x,ushort y)
{
ushort address;
x--;
if (MaxY <
3)
{
switch(y)
{
case
'\x01' :
address =
0 + x;
break;
case
'\x02' :
address =
64 + x;
break;
}
}
else
{
switch(y)
{
case
'\x01' :
address =
0 + x;
break;
case
'\x02' :
address =
64 + x;
break;
case
'\x03' :
address =
20 + x;
break;
case
'\x04' :
address =
84 + x;
break;
}
}
LCDWriteData(LCD_CTRL,address
| 0x80);
}
/******************************************************************************
Name:
LCDWhereX
Description: Get the x position of
the cursor on the LCD
Input:
None
Output:
ushort : Cursor position "x"
Misc:
******************************************************************************/
ushort LCDWhereX(void)
{
ushort i,x,y;
i = LCDReadData(LCD_CTRL)
& 0x7f;
y = LCDWhereY();
if (MaxY
== 2)
{
if (y
== 1)
x = i;
if (y
== 2)
x = i -
0x40;
}
else if (MaxY
== 4)
{
if (y
== 1)
x = i;
if (y
== 2)
x = i -
0x40;
if (y
== 3)
x = i -
0x14;
if (y
== 4)
x = i -
0x54;
}
x = x +
1;
return x;
}
/******************************************************************************
Name:
LCDWhereY
Description: Get the y position of
the cursor on the LCD
Input:
None
Output:
ushort : Cursor position "y"
Misc:
******************************************************************************/
ushort LCDWhereY(void)
{
ushort i,j;
i = LCDReadData(LCD_CTRL)
& 0x7f;
if (MaxY ==
2)
{
if (i
< 0x28)
j = 1;
else j
= 2;
}
else if (MaxY
== 4)
{
if ((i
>0x00)
&& (i <
0x15)) j =
1;
if ((i
>0x14)
&& (i <
0x28)) j =
3;
if ((i
>0x40)
&& (i <
0x55)) j =
2;
if ((i
>0x54)
&& (i <
0x68)) j =
4;
}
return j;
}
/******************************************************************************
Name:
WtireByteLCD(char byte)
Description: Write a byte on the LCD
at cursor position
Input:
byte
Output:
none
Misc:
******************************************************************************/
void LCDWriteChar(char
byte)
{
char tmp;
tmp = byte &
0xf0;
tmp = tmp >>
4;
tmp += 0x30;
if (tmp >
0x39) tmp
+= 0x07;
LCDWriteData(LCD_DATA,tmp);
tmp = byte &
0x0f;
tmp += 0x30;
if (tmp >
0x39) tmp
+= 0x07;
LCDWriteData(LCD_DATA,tmp);
}
/******************************************************************************
Name:
void LCDWriteString(char *ptr)
Description: Write a string from RAM
on the LCD
Input:
string pointer
Output:
none
Misc:
******************************************************************************/
void LCDWriteString(char
*ptr)
{
ushort i;
for (i=1;i<41;i++)
{
if (*ptr
== 0x00)
break;
LCDWriteData(LCD_DATA,*ptr++);
}
}
/******************************************************************************
Name:
void LCDWriteConstString(const char *ptr)
Description: Write a constant string
on the LCD
Input:
string pointer
Output:
none
Misc:
******************************************************************************/
void LCDWriteConstString(const
char *ptr)
{
ushort i;
for (i=1;i<41;i++)
{
if (*ptr
== 0x00)
break;
else if (i
== 21)
LCDGotoXY(1,2);
LCDWriteData(LCD_DATA,*ptr++);
}
}
/******************************************************************************
Name:
void LCDWriteData(ushort rs, ushort ch)
Description: Write a byte in rs of
the LCD
Input:
rs -> Register select
ch -> byte to write
Output:
none
Misc:
******************************************************************************/
void LCDWriteData(ushort
rs,ushort ch)
{
ushort Stat;
Stat = LCD_PIN &
LCD_BACKLIGHT;
LCD_PORT = Stat;
LCDWait();
if ((ch &
0x80) ==
0x80)
LCD_PORT |= LCD_D7;
if ((ch &
0x40) ==
0x40)
LCD_PORT |= LCD_D6;
if ((ch &
0x20) ==
0x20)
LCD_PORT |= LCD_D5;
if ((ch &
0x10) ==
0x10)
LCD_PORT |= LCD_D4;
if (rs ==
1)
LCD_PORT |= LCD_RS;
LCDDelay50us(1);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
LCD_PORT = Stat;
if ((ch &
0x08) ==
0x08)
LCD_PORT |= LCD_D7;
if ((ch &
0x04) ==
0x04)
LCD_PORT |= LCD_D6;
if ((ch &
0x02) ==
0x02)
LCD_PORT |= LCD_D5;
if ((ch &
0x01) ==
0x01)
LCD_PORT |= LCD_D4;
if (rs ==
1)
LCD_PORT |= LCD_RS;
LCDDelay50us(1);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
}
/******************************************************************************
Name:
ushort LCDRead(ushort rs)
Description: read a byte in rs of the
LCD
Input:
rs -> Register select
Output:
ushort
Misc:
******************************************************************************/
ushort LCDReadData(ushort rs)
{
ushort Byte=0;
LCD_DDR &= ~(LCD_D7 +
LCD_D6 + LCD_D5 +
LCD_D4);
LCD_PORT = LCD_PIN &
LCD_BACKLIGHT;
LCD_PORT |= LCD_RW;
if (rs ==
1)
LCD_PORT |= LCD_RS;
LCDDelay50us(1);
LCD_PORT |= LCD_E;
LCD_PORT |= LCD_E;
if (LCD_PIN &
LCD_D7) Byte |=
0x80;
if (LCD_PIN &
LCD_D6) Byte |=
0x40;
if (LCD_PIN &
LCD_D5) Byte |=
0x20;
if (LCD_PIN &
LCD_D4) Byte |=
0x10;
LCD_PORT &= ~LCD_E;
LCD_PORT |= LCD_E;
LCD_PORT |= LCD_E;
if (LCD_PIN &
LCD_D7) Byte |=
0x08;
if (LCD_PIN &
LCD_D6) Byte |=
0x04;
if (LCD_PIN &
LCD_D5) Byte |=
0x02;
if (LCD_PIN &
LCD_D4) Byte |=
0x01;
LCD_PORT &= ~LCD_E;
LCD_PORT &= ~LCD_RW;
LCD_DDR |= LCD_D7 +
LCD_D6 + LCD_D5 +
LCD_D4;
return (Byte);
}
/******************************************************************************
Name:
void LCDWait(void)
Description: wait for the LCD to be
ready
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDWait(void)
{
while((LCDReadData(0)
& 0x80) ==
0x80) WDR();
}
/******************************************************************************
Name:
void LCDDelay50us(int Delay)
Description: Delay of 50 us with a
1Mhz resonator
Input:
Delay X x 50us
Output:
none
Misc:
******************************************************************************/
void LCDDelay50us(int
Delay)
{
int i,j;
for (i=0;i<Delay;i++)
{
for (j=1;j<120;j++);
asm("WDR");
}
}
/******************************************************************************
Name:
void LCDTextAttr(ushort Attribute)
Description: Set the LCD attribute
Input:
LCD_C_BLINK_ON : Cursor blink on
LCD_C_BLINK_OFF : Cursor blink off
LCD_C_ON
: Cursor on
LCD_C_OFF :
Cursor off
LCD_DISPLAY_ON : Display ON
LCD_DISPLAY_OFF : Display OFF
LCD_BRIGHT_25 : VFD 25% Bright
LCD_BRIGHT_50 : VFD 50% Bright
LCD_BRIGHT_75 : VFD 75% Bright
LCD_BRIGHT_100 : VFD 100% Bright
LCD_BACK_LIGHT_ON : Back Light ON
LCD_BACK_LIGHT_OFF : Back Light OFF
Output:
none
Misc:
******************************************************************************/
void LCDTextAttr(ushort
attribute)
{
switch (attribute)
{
case LCD_C_BLINK_ON:
LCDStat
|= LCD_C_BLINK_ON;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_C_BLINK_OFF:
LCDStat
&= LCD_C_BLINK_OFF;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_C_ON:
LCDStat
|= LCD_C_ON;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_C_OFF:
LCDStat
&= LCD_C_OFF;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_DISPLAY_ON:
LCDStat
|= LCD_DISPLAY_ON;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_DISPLAY_OFF:
LCDStat
&= LCD_DISPLAY_OFF;
LCDWriteData(LCD_CTRL,LCDStat);
break;
case LCD_BRIGHT_25:
LCDWriteData(LCD_CTRL,0x20);
LCDWriteData(LCD_DATA,0x03);
break;
case LCD_BRIGHT_50:
LCDWriteData(LCD_CTRL,0x20);
LCDWriteData(LCD_DATA,0x02);
break;
case LCD_BRIGHT_75:
LCDWriteData(LCD_CTRL,0x20);
LCDWriteData(LCD_DATA,0x01);
break;
case LCD_BRIGHT_100:
LCDWriteData(LCD_CTRL,0x20);
LCDWriteData(LCD_DATA,0x00);
break;
case LCD_BACKLIGHT_ON:
LCD_PORT
|= LCD_BACKLIGHT;
break;
case LCD_BACKLIGHT_OFF:
LCD_PORT
&= ~(LCD_BACKLIGHT);
break;
}
}
/******************************************************************************
Name:
void LCDOn(ushort X, ushort Y)
Description: Initialize LCD in 4bit
mode
Input:
ushort X -> X size
ushort Y -> Y size
Output:
none
Misc:
******************************************************************************/
void LCDInit(ushort
X, ushort Y)
{
MaxX = X;
MaxY = Y;
LCDStat = 0x0c;
LCD_PORT = 0x00;
LCD_DDR = LCD_D7+LCD_D6+LCD_D5+LCD_D4+LCD_E+LCD_RS+LCD_RW+LCD_BACKLIGHT;
LCD_PORT = ~(LCD_D7+LCD_D6+LCD_D5+LCD_D4+LCD_E+LCD_RS+LCD_RW);
LCD_PORT |= LCD_BACKLIGHT;
LCDDelay50us(340);
LCD_PORT = (LCD_D5 +
LCD_D4 + LCD_BACKLIGHT);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
LCDDelay50us(100);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
LCDDelay50us(100);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
LCDDelay50us(100);
LCD_PORT = (LCD_D5 +
LCD_BACKLIGHT);
LCD_PORT |= LCD_E;
LCD_PORT &= ~LCD_E;
LCDDelay50us(100);
if (Y ==
1)
LCDWriteData(LCD_CTRL,0x20);
// 1 line
else LCDWriteData(LCD_CTRL,0x28);
// 2 line
LCDWriteData(LCD_CTRL,0x0c);
// Disp ON-Cur OFF-Blink OFF
LCDWriteData(LCD_CTRL,0x01);
// Clear display
LCDDelay50us(50);
LCDWriteData(LCD_CTRL,0x06);
// Cursor INC Shift OFF
DDRD |= 0x80;
TCCR2 = 0x79;
OCR2 = 0xf0;
}
/******************************************************************************
Name:
void LCDContrast(ushort Cont)
Description: Set the LCD Contrast
Input:
from 0 to 255
Output:
none
Misc:
******************************************************************************/
void LCDContrast(ushort
Cont)
{
OCR2 = Cont;
}
/******************************************************************************
Name:
void LCDOff(void)
Description: Shut down LCD
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDOff(void)
{
LCD_DDR = 0xff;
LCD_PORT = 0x00;
DDRD &= ~0x80;
}