Thứ Sáu, 14 tháng 12, 2018

Variable Power Supply with LCD

Are you an electronic hobbyist? Then an adjustable power supply is a must for your various needs. This project explains how to make a LM317 based adjustable power supply unit with a digital display.

Components Required
1. LM317 IC
 
2. Resistor – 240 Ohms
 
3. Capacitors – 0.1uF, 10uF
 
4. Potentiometer – 5k
 
5. 30V/1A Adapter (or a transformer + Bridge wave rectifier IC)
 
6. ATMega16 Developments Board
 
7. 16 x 2 LCD 
7. 16 x 2 LCD Board

Circuit Design
Well the power supply circuit is very simple and can be found in the datasheet of LM317 itself.
variable power supply
Fig. 1: Circuit Diagram of LM317 IC based Variable Power Supply
The output voltage is given by the equation,
 
Vout = 1.25 (1+ R2/R1) + Iadj x R2
 
What we need to design is the additional voltmeter kind of arrangements using a microcontroller in order to display the output voltage value accurately. For this, we use the ADC feature of the microcontroller.
 
But the problem is that ATmega16 can only take up to 5V. Input voltage more than that can fry up the controller.
 
Solution: A Voltage divider circuit!
 
variable power supply
Fig. 2: Circuit Diagram of Voltage Divider Circuit for power output
Here R1 and R2 are the resistors and Vin is the input voltage. The output voltage Vout is given as:
Vout =  Vin X R2/(R1 + R2) .  .  .  .  .  .  .  .  .  .  .  .  .  .  . (1)
We choose the resistor values based on our requirements. Like, say now our maximum voltage to be measured is 30V but we can only give up to 5V to our controller.
So here maximum Vin = 30V and maximum Vout = 5V
Substituting in equation (1) and on solving, we get
R1:R2 = 5 : 1
So we can take R1= 5kOhm and R2=1k Ohm

Code Explanation

- Initialize the 16 bit ADC mode of the controller.
 
- Initialize the LCD function.
 
- Enter an infinite loop.
 
- Read the voltage level at ADC1, convert it into a 16-bit discreet value (0 to 1023) and store it in a variable “val”.
 
- Divide the value at “val” by 1024 and then multiply it with 30. This gives you the original applied voltage value.
 
- Now display this value in the LCD.

Conversion Process Example
• Let us say that we applied some input voltage Vin= 24V to the system
 
• Now from the design equation, the output voltage of voltage divider circuit can be calculated. Here the output would be 4V, which is the input to the ADC pin of microcontroller.
 
• The controller would covert the analog value (0-5V) into a discreet value of range, 0-1023. In this case the value would be around 819.
 
• Next, this discreet value is again converted into the original input voltage range which is 0-30V through programming. Here the value obtained would be 23.99, which is almost equal to 24V!
variable power supply
Fig. 3: Block Diagram of AVR ATMega16 based Variable Power Supply

How we display decimals:
Let us say we got a value val = 24.93
 
Now “lcd_write_int()” function only accepts whole numbers and no decimal part.
 
So what we do is,
Step 1: Multiply ‘val’ with 100
Val x 100 = 24.93 x 100 = 2493 (say we name it ‘a’)
 
Step 2: Obtain integer part by using ‘/ ’operator
I = a / 100 = 2493 / 100 = 24 (Integer)
 
Step 3: Obtain decimal part as another integer using ‘%’ operator
D = a % 100 = 2493 % 100 = 93
Step 4:
First display the integer part followed by ‘.’ and then the decimal part.
Example: display(I+’.’+D)   à I.D
variable power supply
Fig. 4: Representational image of display panel for AVR ATMega16 based Adjustable Power Supply
Circuit:

Circuit Diagram of AVR ATMega16 based Adjustable Power Supply
Code:
LCD.H



#ifndef LCD_H_
#define LCD_H_
#define rs PA7
#define rw PA6
#define en PA4
void lcd_init();
void dis_cmd(char);
void dis_data(char);
void lcdcmd(char);
void lcddata(char);
void clrscr();
void gotoxy(char,char);
void LCD_write_string(const char *);
void lcd_write_int(int,unsigned int);
#endif


Variable.C


/*
 * VARIABLE.c
 *
 * Created: 5/29/2014 3:53:39 PM
 *  Author: GANESH SELVARAJ
 */ 
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
void SetADC()
{
ADMUX|=(1<<REFS0);
ADCSRA=(1<<ADEN)|(7<<ADPS0);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX&=0b11100000;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return(ADC);
}
void Waiting(int j) // simple delay function
{
uint8_t i;
for(i=0;i<j;i++)
_delay_ms(200);
}
int main(void)
{
int v;
_delay_ms(50); // delay of 50 milliseconds
SetADC();
lcd_init();
LCD_write_string("Adj Power Supply");
while(1)
    {
gotoxy(1,1);
LCD_write_string("Voltage:");
v=((ReadADC(0)/1024.00)*3000.00);
lcd_write_int((v/100),2);
dis_data('.');
lcd_write_int((v%100),2);
dis_data('V');
dis_data(' ');
Waiting(2);
    }
}



LCD.H


/*
 * EG_LCD.c
 *
 * Created: 2/9/2014 10:49:54 PM
 *  Author: stranger
 */ 
#include<avr/io.h>
#include<util/delay.h>
#include<inttypes.h>
#include "lcd.h"
void LCD_write_string(const char *str) //store address value of the string in pointer *str
{
int i=0;
while(str[i]!='\0') // loop will go on till the NULL character in the string
{
if (str[i]=='*')
{
i++;
int8_t cc=str[i]-'0';
if(cc>=0 && cc<=7)
{
dis_data(cc);
}
else
{
dis_data('%');
dis_data(str[i]);
}
}
else dis_data(str[i]); // sending data on LCD byte by byte
i++;
}
return;
}
void lcd_init() // function for initialize
{
DDRB=0xFF;
dis_cmd(0x02); // to initialize LCD in 4-bit mode.
dis_cmd(0x28); //to initialize LCD in 2 lines, 5X7 dots and 4bit mode.
dis_cmd(0x0C);
dis_cmd(0x06);
dis_cmd(0x0E);
gotoxy(0,0);
}
void dis_cmd(char cmd_value)
{
char cmd_value1;
cmd_value1 = ((cmd_value>>4) & 0x0F); //shift 4-bit and mask
lcdcmd(cmd_value1); // send to LCD
cmd_value1 = cmd_value & 0x0F; //mask lower nibble because PA4-PA7 pins are used.
lcdcmd(cmd_value1); // send to LCD
}
void dis_data(char data_value)
{
char data_value1;
data_value1=((data_value>>4)&0x0F);
lcddata(data_value1);
data_value1=data_value&0x0F;
lcddata(data_value1);
}
void lcdcmd(char cmdout)
{
PORTB=cmdout;
PORTB&=~(1<<rs);
PORTB&=~(1<<rw);
PORTB|=(1<<en);
_delay_ms(1);
PORTB&=~(1<<en);
}
void lcddata(char dataout)
{
PORTB=dataout;
PORTB|=(1<<rs);
PORTB&=~(1<<rw);
PORTB|=(1<<en);
_delay_ms(1);
PORTB&=~(1<<en);
}
void clrscr()
{
_delay_ms(10);
dis_cmd(0x01);
_delay_ms(100);
}
void gotoxy(char a,char b)
{
if(a==0)  a=0b10000000;
else if(a==1) a=0b11000000;
else if(a==2) a=0b10010100;
else if(a==3) a=0b11010100;
dis_cmd(a+b); 
}
void lcd_write_int(int val,unsigned int field_length)
{
char str[5]={0,0,0,0,0};
uint8_t i=4,j=0;
while(val)
{
str[i]=val%10;
val=val/10;
i--;
}
if(field_length==-1)
while(str[j]==0) j++;
else
j=5-field_length;
if(val<0) dis_data('-');
for(i=j;i<5;i++)
{
dis_data(48+str[i]);
}
}

Không có nhận xét nào:

Đăng nhận xét

Bài đăng mới nhất

Hướng dẫn sử dụng Cân điện tử Fujihatsu FTC-01

Hướng dẫn sử dụng Cân điện tử Fujihatsu FTC-01 # candientu ,  # fujihatsu ,  # candientufujihatsu  #candientu,  # candientufujhatsu , #fuji...

Bài đăng phổ biến