Translate

Monday, 11 January 2016

Measuring angular displacement using rotary potentiometer

                         Alright, in the previous post we discussed about interfacing a character LCD. Now lets pair it with the built in analog to digital converter (ADC) of an atmega controller. We will a rotary potentiometer to measure the angular displacement.... Its similar to how a servo measures its angle. The process is simple as shown below




Before we proceed please ensure that you know how to built a power supply and a basic LCD interface.... Also a little bit knowledge on ADC operation is required.

Things you need

ADC

The atmega 8,16 and 32 use a 10bit successive approximation ADC. The values range from 0 - 1023 (10bit -> 1024). The atmega has three reference sources but it can use only one at a time Here the reference voltage is set to 5V to keep things simple. I have not discussed the topics on frequency and prescalar,the data sheet contains more details, you can look it up

CIRCUIT DIAGRAM

Alright heres the circuit diagram. As you can see it is similar to that of the LCD post but with the addition of the potentiometer



CODE



         Here is a simple code... this code has a drawback which I will address next


////////////////////////////////////////////////////Code for ADC readout//////////////////////////////////////////////////////

/*
* Angular_displacement_using_atmega.cpp
*
* Created: 8/1/2016 8:35:28 PM
* Author: Hemanth
*/

#ifndef F_CPU
#define F_CPU 1000000UL // CPU frequency
#endif

#define LCD_DATA PORTC
#define control PORTB
#define rs PB2
#define rw PB1
#define en PB0

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

void LCD_cmd(unsigned char cmd);
void init_LCD(void);
void LCD_write(unsigned char data);
void stringwrite(const char *q);
void moveto(int line,int pos);
void clearLCD();
void InitialiseADC(char Aref,int prescalar);
int ADC_readout(uint8_t ch);

void InitialiseADC(char Aref,int prescalar)
{
if (Aref=='I')
{ADMUX=(1<<REFS0)|(1<<REFS1);}
else if(Aref=='V')
{ADMUX=(1<<REFS0)|(0<<REFS1);}
else if(Aref=='R')
{ADMUX=(0<<REFS0)|(0<<REFS1);}
if (prescalar==2)
{ADCSRA=(1<<ADEN)|(0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);}
else if (prescalar==4)
{ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);}
else if (prescalar==8)
{ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);}
else if (prescalar==16)
{ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0);}
else if (prescalar==32)
{ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);}
else if (prescalar==64)
{ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);}
else if (prescalar==128)
{ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);}
}

int ADC_readout(int channel)
{
channel=channel&0b00000111;//selecting single ended channel refer data sheet for details
ADMUX|=channel;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA|=(1<<ADIF);
return(ADC);
}

void clearLCD()

{ LCD_cmd(0x01);}

void init_LCD(void)
{
LCD_cmd(0x38);// initialization of 16X2 LCD in 8bit mode
_delay_ms(10);
LCD_cmd(0x01); // clear LCD
_delay_ms(10);
LCD_cmd(0x0C); // cursor ON
_delay_ms(10);
LCD_cmd(0x80);//8 go to first line and0 is for 0th position
}

void LCD_cmd(unsigned char cmd)
{LCD_DATA=cmd;
control |=(1<<en); // RS and RW as LOW and EN as HIGH
control &=~(1<<rs);
control &=~(1<<rw);
_delay_ms(10);
control &=~(1<<rs);
control &=~(1<<rw);
control &=~(1<<en); // RS, RW , LOW and EN as LOW
_delay_ms(10);
}

void LCD_write(unsigned char data)
{
LCD_DATA= data;
control |= (1<<rs)|(1<<en); // RW as LOW and RS, EN as HIGH
control &=~(1<<rw);
_delay_ms(10);
control |= (1<<rs); // EN and RW as LOW and RS HIGH
control &=~(1<<rw);
control &=~(1<<en);
_delay_ms(10); // delay to get things executed
return ;
}

void stringwrite(const char *S)
{
while (*S) {
LCD_write(*S++);
}
}

void moveto(int line,int pos)
{
if(line==1)
LCD_cmd(0x80+pos);
if(line==2)
LCD_cmd(0xC0+pos);
if(line==3)
LCD_cmd(0x90+4+pos);
if(line==4)
LCD_cmd(0xD0+4+pos);
}

char buffer[5];

int main(void)
{
int DATA =0;
MCUCSR|=(1<<JTD);//Disable JTAG
MCUCSR|=(1<<JTD);//Have to send it twice
DDRA=0x00;
DDRB=0xFF;
DDRC=0xFF;
DDRD=0xFF;
PORTA=0x00;
PORTB=0X00;
PORTC=0X00;
PORTD=0x00;
PORTD|=(1<<PD7);
init_LCD();
InitialiseADC('V',4);
while(1)
{
moveto(1,0);
stringwrite("ADC Value :");
DATA=ADC_readout(4);
itoa(DATA,buffer,10);
moveto(1,12);
stringwrite(buffer);
}
}
now when you run this code the voltage entering to the adc pin woul be converted to an accurate digital number. heres a little math

referance voltage = 5000mv
ADC resolution = 2^10 bit (1024)

step value = (5000/1024) = 4.88

which means for every 4.88mv increase the ADC would increment by one

example

if the input to the pin is 2.35V the ADC would read out

(2350/4.88) ~  481

the output will always be in the integer format

The drawback

     so did u guys notice the display when moving from a higher to lower value say from 998 to 25....... your display would read as 258..... the 8 being the 8 from the 998 which was not erased from the LCD memory.... the next code has this covered.....you can write it out with a blank space like so

moveto (1,12);
stringwrite ("    ")//four blank spaces
moveto(1,12)// back to the 1000th place
stringwrite (buffer);

Alright so we got the ADC value how do we convert it to degrees?..... well simple math.... and this is the same procedure for distance or temperature sensors which provides an analog output

here we have a potentiometer with the capability of 0 degrees to 270 degrees

and as you learnt from the previous code (try it on an MCU before proceeding) 0 to 270 corresponds to 0 to 1023... so we just have to derive a simple relation...as such

270 * X = 1023

so X = (1023/270) i.e 3.78

so the angle would be the (ADC reading/3.78)... simple.....any doubts comment below

Heres the final board


here's the code

please note for greater accuracy floating variables must be used.. this code is for referance and simple projects only... no error correction methods have been implemented....In theory the rotary potentiometer is assumed as linear... however that is not always practical.

And here's another note if u plan on using more than 1 potentiometer the ADC must be initailsed again and the next channel selected... The first conversion must be discarded

Example

initialiseADC('V',32);// set ADC referance voltage to vcc i.e 5V with a prescalar of 32
DATA1=ADC_readout(2);//discard first conversion
DATA1=ADC_readout(2);
initialiseADC('I',8); // set ADC referance voltage to internal i.e 2.56V with a prescalar of 8
DATA2=ADC_readout(5);//discard first conversion
DATA2=ADC_readout(5);

////////////////////////////////////////////////////Code for angular readout//////////////////////////////////////////////////////
  
/*
* Angular_displacement_using_atmega.cpp
*
* Created: 8/1/2016 8:35:28 PM
* Author: Hemanth
*/

#ifndef F_CPU
#define F_CPU 1000000UL // CPU frequency
#endif

#define LCD_DATA PORTC
#define control PORTB
#define rs PB2
#define rw PB1
#define en PB0

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

void LCD_cmd(unsigned char cmd);
void init_LCD(void);
void LCD_write(unsigned char data);
void stringwrite(const char *q);
void moveto(int line,int pos);
void clearLCD();
void InitialiseADC(char Aref,int prescalar);
int ADC_readout(uint8_t ch);

void InitialiseADC(char Aref,int prescalar)
{
    if (Aref=='I')
    {ADMUX=(1<<REFS0)|(1<<REFS1);}
    else if(Aref=='V')
    {ADMUX=(1<<REFS0)|(0<<REFS1);}
    else if(Aref=='R')
    {ADMUX=(0<<REFS0)|(0<<REFS1);}
    if (prescalar==2)
    {ADCSRA=(1<<ADEN)|(0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);}
    else if (prescalar==4)
    {ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);}
    else if (prescalar==8)
    {ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);}
    else if (prescalar==16)
    {ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0);}
    else if (prescalar==32)
    {ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);}
    else if (prescalar==64)
    {ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);}
    else if (prescalar==128)
    {ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);}
}

int ADC_readout(int channel)
{
    channel=channel&0b00000111;//selecting single ended channel refer data sheet for details
    ADMUX|=channel;
    ADCSRA|=(1<<ADSC);
    while(!(ADCSRA & (1<<ADIF)));
    ADCSRA|=(1<<ADIF);
    return(ADC);
}

void clearLCD()

{ LCD_cmd(0x01);}


void init_LCD(void)
{
    LCD_cmd(0x38);// initialization of 16X2 LCD in 8bit mode
    _delay_ms(1);
    LCD_cmd(0x01); // clear LCD
    _delay_ms(10);
    LCD_cmd(0x0C); // cursor ON
    _delay_ms(1);
    LCD_cmd(0x80);//8 go to first line and0 is for 0th position
}

void LCD_cmd(unsigned char cmd)
{LCD_DATA=cmd;
    control |=(1<<en); // RS and RW as LOW and EN as HIGH
    control &=~(1<<rs);
    control &=~(1<<rw);
    _delay_ms(1);
    control &=~(1<<rs);
    control &=~(1<<rw);
    control &=~(1<<en); // RS, RW , LOW and EN as LOW
    _delay_ms(1);
}

void LCD_write(unsigned char data)
{
    LCD_DATA= data;
    control |= (1<<rs)|(1<<en); // RW as LOW and RS, EN as HIGH
    control &=~(1<<rw);
    _delay_ms(1);
    control |= (1<<rs); // EN and RW as LOW and RS HIGH
    control &=~(1<<rw);
    control &=~(1<<en);
    _delay_ms(1); // delay to get things executed
    return ;
}

void stringwrite(const char *S)
{
    while (*S) {
        LCD_write(*S++);
    }
}

void moveto(int line,int pos)
{
    if(line==1)
    LCD_cmd(0x80+pos);
    if(line==2)
    LCD_cmd(0xC0+pos);
    if(line==3)
    LCD_cmd(0x90+4+pos);
    if(line==4)
    LCD_cmd(0xD0+4+pos);
}

char buffer[5];

int main(void)
{
    int DATA =0;
    int ANGLE =0;
   
    MCUCSR|=(1<<JTD);//Disable JTAG
    MCUCSR|=(1<<JTD);//Have to send it twice
    DDRA=0x00;
    DDRB=0xFF;
    DDRC=0xFF;
    DDRD=0xFF;
    PORTA=0x00;
    PORTB=0X00;
    PORTC=0X00;
    PORTD=0x00;
    PORTD|=(1<<PD7);
    init_LCD();
    InitialiseADC('V',4);
    moveto(1,0);
    stringwrite("-----Angular----");
    moveto(2,0);
    stringwrite("measuring device");
    _delay_ms(2000);
    clearLCD();
    moveto(1,0);
    stringwrite("ADC Value :");
    moveto(2,0);
    stringwrite("Angle :   degree");
    InitialiseADC('V',4);
    while(1)
    { DATA=ADC_readout(4);
       
        moveto(2,7);
        stringwrite("   ");// to clear previous value
        moveto(1,12);
        stringwrite("     ");// to clear previous value
        itoa(DATA,buffer,10);
        moveto(1,12);
        stringwrite(buffer);
        ANGLE=DATA/3.78;
        itoa(ANGLE,buffer,10);
        moveto(2,7);
        stringwrite(buffer);
        _delay_ms(200);//delay to reduce flickering
    }
}

--------------------------------------------------------------------------------------------------------------------------

So thats it , hope this helps ...... comment if any doubts



Wednesday, 6 January 2016

Driving Character LCD using Atmega in 8-bit mode

                 So, ever wanted to make a simple message display. well here it is. this article will walk you through the simple steps of getting the LCD working. Before proceeding you must know how to use the ports on the MCU. A lot of tutorials are available online so I decided to jump to the fun stuff.

The image below is a simple message display


It consists of a

  • Charecter LCD
  • MCU (atmega 16)
  • 10k pullup resistor for reset
  • 10k variable resistor for contrast adjustment

here is the circuit diagram

NOTE: I have not used a reset button or an external crystal (x1) on the prototype board. you may use it if you wish as the next tutorials will require it


16X4


The 16 X 4 LCD has 16 columns and 4 rows. The LCD displays two screens with a delay of 2000 milli seconds or two seconds


16X2


The 16 X 2 LCD has 16 columns and 2 rows. The LCD displays two screens with a delay of 2000 milli seconds or two seconds. Note that the same code is used for both LCDs the 16 X 2 ignores line 3 and 4. well technically it is in the memory and can be forced to display but that's beyond the scope of this article.

The LCD has 16 pins the table below tabulates them


Pin number
Pin name
Discription
1
Gnd
Common ground
2
Vcc
5.5V max (check datasheet)
3
VE
Voltage for contrast adjustment use 10k pot
4
RS
Register select; Low for control; High for data
5
RW
Read or write; High for read; Low for write
6
EN
Enable pulse triggers on falling edge (high to low)
7 - 14
D0 - D7
8 bit data bus; 
15
+ LED
LED positive 5V max
16
- LED
Connect to common ground

 So to get the LCD started follow these steps
  • Ensure that  the vcc is powered to +5v and all ground pins are connected together for both the controller and the LCD. 

  •  before programming the chip. power on the circuite and adjust the contrast till you see black squares on the first line of the LCD

  • Now program the chip

  • The LCD will display as shown in the figures above

Possible problems you may encounter

If the LCD is not displaying anything even the black squares before flashing the chip.

  • Check the contrast.
  • Check the voltage and ground connections  

If the LCD is not initialising (i.e black squares not disappering)

  • Check data lines and control lines for shorts.
  • Ensure that the DDR (data direction register) for the data lines and control lines are set as output
  • Ensure that the F_CPU matches the clock speed of the chip. new chips have a frequency of 1 MHZ so F_CPU must be '1000000UL'. this is the value in hertz. for different frequencies change accordingly.
  • Atmega 16 and 32 have the JTAG unit enabled hence portc cannot function as a normal IO port ensure that the line MCUCSR|=(1<<JTD); is typed twice.

If the LCD displays random/junk characters

  • One or more data lines may not be soldered properly
  • Ensure that the F_CPU matches the clock speed of the chip. new chips have a frequency of 1 MHZ so F_CPU must be '1000000UL'. this is the value in hertz. for different frequencies change accordingly.

        So here it is the code to drive the LCD. this code was written in atmel studio.

  • just create a new executable project (c/c++). 
  • Select you device
  • past the code (starting from /*).
  • build the code by pressing F7
  • wait for the build to complete then use a flashing tool (burner as it is regularly called). to flash the program to the chip. 

        That's it, your done. Alter the lines to match your display needs. experiment with the code and find out how to make it work your way. I really recommend learning the theory behind the LCD's operation as it will help you a lot..... especially writing a code from scratch and debugging.

--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------

/*
* LCD DEMO.cpp
* Created: 29-12-2015 13:16:17
* Author: Hemanth
*/
//////////////////////////////////////////Define CPU Frequency///////////////////////////////////////////////////

#ifndef F_CPU
#define F_CPU 1000000UL // CPU frequency
#endif

////////////////////////////////////////////Value definitions/////////////////////////////////////////////////

#define LCD_DATA PORTC // data port for LCD
#define control PORTB // port for command
#define rs PB2 // Register select pin
#define rw PB1 // Read or write pin
#define en PB0 // Enable pin

////////////////////////////////////////Header files/////////////////////////////////////////////////////

#include <avr/io.h> //header file for DDR and PORT function
#include <util/delay.h> //header file for _dela_ms() function

/////////////////////////////////////////Function prototypes////////////////////////////////////////////////////

void LCD_cmd(unsigned char cmd);
void init_LCD(void);
void LCD_write(unsigned char data);
void stringwrite(const char *q);
void moveto(int line,int pos);
void clearLCD();

/////////////////////////////////////Functions////////////////////////////////////////////////////////

void clearLCD()
{
LCD_cmd(0x01);
}

void init_LCD(void)
{
LCD_cmd(0x38);// initialization of 16X2 LCD in 8bit mode
_delay_ms(10);
LCD_cmd(0x01); // clear LCD
_delay_ms(10);
LCD_cmd(0x0C); // cursor ON
_delay_ms(10);
LCD_cmd(0x80);//8 go to first line and 0 is for 0th position
}

void LCD_cmd(unsigned char cmd)
{
LCD_DATA=cmd;
control |=(1<<en); // RS and RW as LOW and EN as HIGH
control &=~(1<<rs);
control &=~(1<<rw);
_delay_ms(10);
control &=~(1<<rs);
control &=~(1<<rw);
control &=~(1<<en); // RS, RW , LOW and EN as LOW

}

void LCD_write(unsigned char data)
{
LCD_DATA= data;
control |= (1<<rs)|(1<<en); // RW as LOW and RS, EN as HIGH
control &=~(1<<rw);
_delay_ms(10);
control |= (1<<rs); // EN and RW as LOW and RS HIGH
control &=~(1<<rw);
control &=~(1<<en);
// delay to get things executed
}

void stringwrite(const char *S)
{
while (*S) {
LCD_write(*S++);
}}

void moveto(int line,int pos)
{
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//The following block is for 16X4 LCD for 16X2 line 1 is 1st line and line 2 is second line
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(line==1)
LCD_cmd(0x80+pos);//1st line 0th position
if(line==2)
LCD_cmd(0xC0+pos);//2nd line 0th position
if(line==3)
LCD_cmd(0x90+pos);//3rd line 0th position
if(line==4)
LCD_cmd(0xD0+pos);//4th line 0th position
}

/////////////////////////////////////////Main function//////////////////////////////////////////////////

int main(void)
{
MCUCSR|=(1<<JTD);//Disable JTAG
MCUCSR|=(1<<JTD);//Have to send it twice
DDRB=0xFF;// Set all pin of portB to act as output pins
DDRC=0xFF;// Set all pin of portC to act as output pins
DDRD=0xFF;// Set all pin of portD to act as output pins
PORTD|=(1<<PD7);//// Set pin PD7 to logic high.... this is used to turn on the LCD light

init_LCD(); // initializing LCD...... must be called else it will not accept any commands

while(1)
{
moveto(1,0);// 1st line 0th position
stringwrite("Simple 16X4 LCD");
moveto(2,0);
stringwrite("Interfacing in 8");
moveto(3,0);
stringwrite("bitmode~Atmega16");
moveto(4,0);
stringwrite("Hemanth Praveen");
_delay_ms(2000);// wait 2 seconds
clearLCD();// clears the LCD memory
moveto(1,0);
stringwrite("8bit DATA ~PORTC");
moveto(2,0);
stringwrite("Command ~PORTB");
moveto(3,0);
stringwrite("RS~PB2 R/W~PB1");
moveto(4,0);
stringwrite("En~PB0 CLK~1MHz");
_delay_ms(2000);
clearLCD();
}}

--------------------------------------------------------------------------------------------------

ok guys that's it for now do comment if you experience any problems with the code.

Hardware for powering on and programming ATmega

                    Alright, After the power supply  (refer here for power supply ) the next step is to build a board with the chip and the connectors for programming.
here is a simple board ready for programming.
.

                       As you can see the ISP (in system programming) pins are soldered on the board which means that reprogramming the board will be easy as we do not have to remove the chip. 

However you can also use something like this





Here the chips can be programmed separately (as shown above) and later be placed or soldered directly to a board.

The image of the board shown above has the following
  • 28 pin ZIF socket
  • 40 pin ZIF socket
  • 10 pin male socket
  • 16Mhz crystal
  • 2 X 0.33pf ceramic disc capacitors
Even though two ZIF (zero insertion force) sockets are present only one chip can be recognised at a time. If we put both the chips. None of them will be detected.

Here’s the back wiring of the board



Here is the circuit diagram of the board



                  

ok, now that the basic programming and power connections (refer here for power supply ) have been set out, a simple but important topic. 'Reset function in ATmega's. A reset basically means 'returning to defaults' , which in this case returns the controller register values to their defaults. The MCU also execute its code from the beginning.

The ATmega8 has four sources of Reset:
  • Power-on Reset. The MCU is reset when the supply voltage is below the Power-on
    Reset threshold
  • External Reset. The MCU is reset when a low level is present on the RESET pin for
    Longer than the minimum pulse length 
  • Watchdog Reset. The MCU is reset when the Watchdog Timer period expires and the
    Watchdog is enabled
  • Brown-out Reset. The MCU is reset when the supply voltage VCC is below the Brown-out Reset threshold (VBOT) and the Brown-out Detector is enabled
Ill briefly explain the first two as they are commonly used

Power on reset

Well this is the simplest form of resetting the chip. The name says it all ' The chip resets when it is powered on'. Every ATmega chip (at least the ones most commonly used) have a on-chip Power-on Reset (POR) circuit to generate a POR pulse. whenever the supply voltage (VCC) is below the detection level, the POR gets activated. The POR circuit can also be used to trigger a Start-up Reset, and also to detect a failure in supply voltage. A Power-on Reset (POR) circuit ensures that the device is reset from Power-on.

External reset

This function lets you use a pulse to reset the chip. The pulse can be a signal from a button or another microcontroller project. The only thing is that the reset pin (pin 9 in ATmega 16/32) should be grounded to trigger it.



Notice the resistor? (R). This is a pull up resistor. Which means the line in this case pin 9 of the MCU has a defined state. That is when the button SW1 is not pressed the line is pulled high (+5V) to prevent any accidental resets. This is very important. I have not used it on the board containing the ZIF sockets because the programmer has one on board. However to make a stand alone circuit the resistor is required.

If a rest button is not used. The reset pin must be pulled up by the resistor. So what about the value?

Well the best and safest method to use the values mentioned in the data sheet. However here are a few values which worked for me

8K2 to 15K @ 5V
4.7K to 8K2 @ 3.3V(only for ATmega 8L, 16L, 32L)
3K3 @ 1.8V(only for ATmega 8L, 16L, 32L)


   For that you will need an USB to ISP programmer.There are two pin configurations 10pin and 6 pin, both work the same way but the pinout is different.Even though 10 pin only 6 lines are generally used.
A 10 pin USB to ISP AVR programmer
A 6 pin USB to ISP AVR Programmer
 The default directory of the hex file is in my documents but you can change it any time. Any burning software available can be used. Just google it.


Here is a screen shot of what I use

Well guys the in the next post we will discuss on connecting the IO pins to an LED and a button......Ill provide a sample code too.

By the way This article was written with reference from the datasheet

Friday, 23 October 2015

MCU Power supply


             Hey guys, here we are at the most basic subsystem of any system. The power source! In this post I will go through the procedure for building a simple power supply. When it comes to projects be it robotics or control systems you will need to provide a stable voltage to ensure that the system will operate without any issues. An unstable power supply can cause MCUs to reset unexpectedly. If you are working with audio amplifiers or any general purpose amplifiers a background noise will be generated if you do not filter the supply. In this post I will go through the procedure for building a simple power supply which should be satisfactory for most projects. So take a look

Before you go ahead there are a few basic terminologies which you must be familiar with 

Voltage

  Voltage is the potential difference between two points of a circuit like the  + and - of a battery every component will have a maximum voltage beyond which it will fail to operate and may be permanently damaged. Cross check datasheet of the respective component.

Current 

     This is the flow of electric charge every device will have a current rating now unlike voltage current dose not enter the circuit just like that. Every device draws its rated current so an MCU that requires a 5V @ 30ma(milli amps = 1/1000A) can be connected to a 5v @ 1A supply. The voltage must be within the operating range. HOWEVER certain devices such as motors(not all), solenoids, high watt bulbs will require current limiters. this is because these devices will draw more current (more than what it can handle ) when started at full power. so a STARTER is required (initially) which limits the power going into the coils refer motor starter for more details. In robotics Brushless motors can draw huge amounts of power if directly started at full speed. However most speed controllers can monitor these conditions and provide a gradual acceleration so that the current flowing through the windings are under control. Another way to reduce the risk of burning the motors is to provide a smooth voltage control using PWM (pulse width modulation). so the motors can be started and stopped slowly(in milli seconds that is). 

Polarity

       This is denoted by  a  ‘ + ‘ and  ‘ – ‘ sign. ‘ + ‘ is referred as the positive terminal and ‘ – ‘ is referred to as the negative terminal check the figures below

now moving on ->

Battery connections



Figure 1
Figure 2
The Figure 1 on the left has a single 9v power source when a multimeter is connected between the terminals ie ‘common to -’ and the other to ‘+’  u will get a reading of 9v. This is the simplest form of a battery arrangement. So 9v is great to operate LCD based projects (with a voltage regulator) But just not good enough for a heavy robot. Most relays and motors are designed to run from 12v and up (exception are there -> such  as RC servo motors etc). In such a case we would go for a series connection (Figure 2) where one battery’s + connects to another battery’s ‘ - ‘ in this case the voltage would add up so if you connect two batteries of 9v @ 4.5A in series the available power would be 18V @ 4.5A notice only the voltage has doubled and not the current.
Figure 3
Now  lets say you are operating a heavy load say an inverter or a UPS more than voltage you would need current in this case you would choose a parallel connection (Figure 3).

         Here the  ‘ + ‘ terminals of all the battires are connected together and the ‘ – ‘ terminals are connected together. So lets assume you have four 12V @ 7A battires (a typical UPS battery) connecting them in parallel would give you 12v @ 28Ah which mean your backup time would improve 4 times… however charging time will also increase by 4 times. Moreover this may over load the charging section of the UPS so you would need to provide a separate source for charging thereby reducing the load on the UPS . Anyway that was just an example back to our topic..

       In case you need a dual polarity supply which means your power supply will have 3 output points ‘+, 0, -‘ You would need a circuit like Figure 4. Here two 9v battires are connected in series HOWEVER ground/ common/ 0v is not tapped from ‘ – ‘ but from the interconnection of both the battires. (Figure 4)
In this case

Figure 4

out1 = +9v
out2 = -9v
out3 = +18v

when you are working with these kind of power supplies (Figure 4&5) ensure that the common line is connected properly else it could result in component damage. These type of power supplies are used in amplifiers, computers (old ones) and so on. Most of the projects I post would use a single polarity supply 

Figure 5

A dual polarity voltage regulator based power supply can provide regulated voltages  (+12 (not regulated), +5, -5, -12 (not regulated)) simply add more regulators to increase the voltage choices. (Figure 6)
Figure 6

Voltage regulators and filters

              Now that you are familiar with the basic connections let’s move on to more fun stuff like using this power to our advantage. Now most MCUs will work on 5V, motors on 12V or 24V, LEDs on 3V and so on. So how would you get different voltages from the same supply? One way is to use resistors. For example to operate an LED from a 12v battery we would give a 1K 1/4W resistor in series to the LED. This is fine since it requires only a small amount of current. SO how on earth will you drive a servo motor which requires a power supply of 5V @ 2A? You would need a big rheostat (remember the ones in the physics lab?). Here we would use a voltage regulator. A voltage regulator basically regulates the voltage by internal circuity and ensures that only the prescribed voltage flows out. It is also more efficient than a rheostat since the rheostat dissipates energy as heat.

So how do you choose a voltage regulator?  Simple! Look at the data sheet right?
Well first of you must ensure your requirements (like voltage, current, cycle)
Take a look at the classification below

Voltage regulators
Positive cycle
Negative cycle
Fixed
78xx series
LM 337
Variable
LM 317
79xx series

Note the ‘series’ check out the table below

Sl. No.
Voltage regulator
Output voltage
1
7805
5
2
7806
6
3
7809
9
4
7815
15
5
7818
18
6
7824
24
Sl. No.
Voltage regulator
Output voltage
1
7905
-5
2
7906
-6
3
7909
-9
4
7915
-15
5
7918
-18
6
7924
-24

Get the idea? The last two digits indicates the output voltage.

OK now lets move on to the final part of this post ill provide different diagrams for different types of supplies

simple bridge rectifier .... no regulator present the out put voltage is dependent on the transformer (good for a NON AUTOMATED lead acid battery charger)

Center tap transformer with a half wave rectifier good to operate motors and relays

Center tap transformer with bridge rectifier gets only half the rated current use this only if u have no other options
Regulator based power supply suitable for MCU, LCD etc 7805 -> +5v, 7812 -> +12v, L317 -> variable (check datasheet)

SO that’s it. We can wrap this topic up. Do comment if u have any questions. For the next post we would need this power supply
Simple regulated 5v power supply


So give it a try..... oh and here is a small demo







We will be moving into MCU based circuits next.. :)
Stay tune :)