# Simple Calculator with ATmega32 Microcontroller

A calculator is a simple and essential tool in everyday life, and it can also be a fun and educational project to build one yourself. One way to do this is by using an ATmega32 microcontroller, which is a powerful and versatile chip that can be programmed to perform a wide range of functions. In this blog post, we will show you how to build a simple calculator using the ATmega32 microcontroller.

Here a simple calculator build with ATmega32 microcontroller is illustrated. The calculator uses the Atmega32 as a calculator brain and controller. It takes user input from 4x4 keypad and outputs the result on 16x2 LCD(Liquid Crystal Display). This is a very simple calculator useful to learn how to interface input and output devices with microcontroller, learn how to write C program code for taking input from keypad, perform mathematical calculation and send the result of the calculation to the LCD display output device.

The first step in building a calculator is to gather the necessary components. The main component of the calculator is the ATmega32 microcontroller, which can be purchased from a variety of electronics retailers. Additionally, you will need a 16x2 LCD display, a keypad, and a few other components such as resistors, capacitors, and a power supply.

The following shows the circuit schematic of the ATmega32 calculator.

In the above circuit drawing, the 4x4 keypad is connected to port C of the microcontroller and the 16x2 LCD are connected to the port A.

Once you have all the components, you can begin assembling the calculator. The ATmega32 microcontroller is the brain of the calculator, and it is responsible for performing the calculations and displaying the results on the LCD display. The keypad is used to input the numbers and operations, and it is connected to the ATmega32 microcontroller as shown in the circuit diagram above.

Once you have assembled the hardware, you can begin programming the ATmega32 microcontroller. This is done using a programming language such as C, and you will need a programmer such as AVR MKII to upload the code to the microcontroller. To learn how to upload code see the tutorial How to Program ATmega328p using ATMEL Studio & AVR ISP MKII.

The program code for this calculator consist C program files for performing the actual calculation, read keypad, write to LCD, the main C program and an sbit C file. So the files are:

1. main C program

3. LCD header and C program

4. sbit header program

5. calculation header and C program

These calculator programing files are provided below.

#### 1. main C program

The main C program code is below.

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include "lcd.h"
#include "sbit.h"
#include "calc.h"

int main(void){

lcdinit();

unsigned char key;           	// Key char for keeping record of pressed key
int num1, num2;       				// First number, second number
char func;    				// Function to be performed among two numbers

lcdgoto(5,1);
lcdstr("ATmega32 ");
lcdgoto(4,2);
lcdstr("Calculator");
_delay_ms(2000);
lcdclear();

while(1)
{
key = keypress();		 //get numb1
lcdcmd(0x01);         	// Clear LCD screen
lcdchar(key);       		// Echo the key pressed to LCD
num1 = get_num(key);       // Get int number from char value, it checks for wrong input as well

if(num1 != Error)            // If correct input then proceed, num1==Error means wrong input
{
key = keypress();		//get function
lcdchar(key);             //Echo the key pressed to LCD
func = get_func(key);            //it checks for wrong func
if(func!='e')                    //if correct input then proceed, func=='e' means wrong input
{
key = keypress();		 	//get numb2
lcdchar(key);   				//Echo the key pressed to LCD
num2 = get_num(key);  //Get int number from char value, it checks for wrong input as well
if(num2!=Error)  				//if correct input then proceed, num2==Error means wrong input
{
key = keypress();	//get equal sign
lcdchar(key); //Echo the key pressed to LCD
if(key == '=')    //if = is pressed then proceed
{
switch(func)    //switch on function
{
case '+':
disp_num(num1+num2);
break;
case '-':
disp_num(num1-num2);
break;
case 'x':
disp_num(num1*num2);
break;
case '/':
disp_num(num1/num2);
break;
}
}
else   //key other then = here means error wrong input
{
if(key == 'C')     //if clear screen is pressed then clear screen and reset
lcdcmd(0x01); // Clear LCD screen
else
DispError(0);     //Display wrong input error
}
}
}
}

}
return 0;
}



This main program code uses keypad, lcd ,sbit and calculator program code as follows.

#### 2. keypad header and C program

The keypad program codes consist of a header file keypad.h and c program file keypad.c. These controls the keypad aspect in the main.c program above. They have functions which are called in the main program code. These program code are below.

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

unsigned char keypress();


#include <avr/io.h>
#include "util/delay.h"
#include "sbit.h"

#define R1 SBIT(PORTC, 0)
#define R2 SBIT(PORTC, 1)
#define R3 SBIT(PORTC, 2)
#define R4 SBIT(PORTC, 3)
#define c1 SBIT(PINC, 4)
#define c2 SBIT(PINC, 5)
#define c3 SBIT(PINC, 6)
#define c4 SBIT(PINC, 7)

unsigned char keypress(void)
{

DDRC=0b00001111;
PORTC=0b11110000;

while (1)
{
R1=0;     R2=1;     R3=1;     R4=1;
_delay_us(50);
if (c1==0){while (c1==0);return ('7');}
if(c2==0){while (c2==0); return ('8');}
if (c3==0){while (c3==0); return ('9');}
if(c4==0){while (c4==0);return ('/');}

R1=1;     R2=0;     R3=1;     R4=1;
_delay_us(50);
if (c1==0){while (c1==0); return ('4');}
if(c2==0){while (c2==0); return ('5');}
if(c3==0){while (c3==0); return ('6');}
if(c4==0){while (c4==0); return ('x');}

R1=1;     R2=1;     R3=0;     R4=1;
_delay_us(50);
if (c1==0){while (c1==0); return ('1');}
if (c2==0){while (c2==0); return ('2');}
if (c3==0){while (c3==0); return ('3');}
if (c4==0){while (c4==0); return ('-');}

R1=1;     R2=1;     R3=1;     R4=0;
_delay_us(50);
if (c1==0){while (c1==0); return ('C');}
if (c2==0){while (c2==0); return ('0');}
if (c3==0){while (c3==0); return ('=');}
if (c4==0){while (c4==0); return ('+');}
}

}


#### 3. LCD header and C program

The LCD program code consist also of a header file lcd.h and c program file lcd.c. These program code controls the LCD aspect from the main.c program above. They have functions which are called in the main C program. The programming code for these files are provided below.

a. lcd.h

#include <avr/io.h>

void lcdinit();
void lcdcmd(unsigned char);
void lcdchar(unsigned char);
void lcdstr(char *);
void latch(void);
void lcdgoto(uint8_t , uint8_t );
void lcdclear();


b.lcd.c

#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"

#define E (1<<PA3)
#define RW (1<<PA2)
#define RS (1<<PA1)

void lcdinit(){

//initialize PORTs for LCD
DDRA |= (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7);  //make output for E,RW,RS and 4 bit Data

//Send Pulse to Latch the data

latch();
_delay_ms(2);  //delay for stable power
// Command to set up the LCD
lcdcmd(0x33);
_delay_us(100);
lcdcmd(0x32);
_delay_us(100);
lcdcmd(0x28);	// 2 lines 5x7 matrix dot
_delay_us(100);
//lcdcmd(0x0E);  // display ON, Cursor ON
lcdcmd(0x0C);  // display ON, Cursor ON
_delay_us(100);
lcdcmd(0x01);	//clear LCD
_delay_ms(20);	//wait
lcdcmd(0x06);	//shift cursor to right
_delay_ms(100);

}

void latch(void){
PORTA |= E;		//send high
_delay_us(500);		//wait
PORTA &= ~E;		//send low
_delay_us(500);		//wait
}

void lcdcmd(unsigned char cmd){

PORTA = (PORTA & 0x0F) | (cmd & 0xF0);  // send high nibble
PORTA &= ~RW;	//send 0 for write operation
PORTA &= ~RS;	//send 0 to select command register
latch();			//latch the data

PORTA = (PORTA & 0x0F) | (cmd<<4);	//send low nibble
latch();			//latch the data

}

void lcdchar(unsigned char data){

PORTA = (PORTA & 0x0F) | (data & 0xF0);  // send high nibble
PORTA &= ~RW;	//send 0 for write operation
PORTA |= RS;	//send 1 to select data register
latch();

PORTA = (PORTA & 0x0F) | (data<<4);  // send high nibble
latch();

}

void lcdstr(char *str){
unsigned char k=0;
while(str[k] != 0){
lcdchar(str[k]);
k++;
}
}

void lcdgoto(unsigned char x, unsigned char y){
unsigned char firstcharadr[] = {0x80, 0xC0, 0x94, 0xD4};
_delay_us(1000);
}

void lcdclear(){
lcdcmd(0x01);
_delay_ms(10);
}


#### 4. sbit header program

Another file used in this calculator program is the sbit.h program file. This file just creates a macro which allows to refer to  a single bit from a selected port.

#ifndef _sbit_h_
#define _sbit_h_

struct bits {
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} __attribute__((__packed__));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)

#endif


#### 5. calculation header and C program

Lastly another programming code file used is for the calculator. These are the calc.h and calc.c files. The program codes in these files controls the calculation aspect of the calculator. The functions used in these files are used in the main C program.

a.calc.h

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

#define Error   13

int get_num(unsigned char);
unsigned char get_func(unsigned char);
void DispError(int);
void disp_num(int);


b.calc.c

#include <avr/io.h>
#include <util/delay.h>
#include "calc.h"
#include "lcd.h"

int get_num(unsigned char ch)         //convert unsigned char into int
{
int num = 0;
switch(ch)
{
case '0':
num = 0;
break;
case '1':
num = 1;
break;
case '2':
num = 2;
break;
case '3':
num = 3;
break;
case '4':
num = 4;
break;
case '5':
num = 5;
break;
case '6':
num = 6;
break;
case '7':
num = 7;
break;
case '8':
num = 8;
break;
case '9':
num = 9;
break;
case 'C':
lcdcmd(0x01);
num = Error;
break;  //this is used as a clear screen and then reset by setting error
default:
DispError(0);
num = Error;
break;       //it means wrong input
}
return num;
}

unsigned char get_func(unsigned char chf)            //detects the errors in inputted function
{
if(chf=='C')                   //if clear screen then clear the LCD and reset
{
lcdcmd(0x01);             //clear display
return 'e';
}
if( chf != '+' && chf != '-' && chf != 'x' && chf != '/' )  //if input is not from allowed funtions then show error
{
DispError(1);
return 'e';
}
return chf;                        //function is correct so return the correct function
}

void DispError(int numb)           //displays differet error messages
{
unsigned char msg1[] = {"Wrong Input"};
unsigned char msg2[] = {"Wrong Function"};

lcdcmd(0x01);              //clear display
switch(numb)
{
case 0:
lcdstr(msg1);
break;
case 1:
lcdstr(msg2);
break;
default:
lcdstr(msg1);
break;
}
}

void disp_num(int numb)            //displays number on LCD
{
unsigned char UnitDigit  = 0;  //It will contain unit digit of numb
unsigned char TenthDigit = 0;  //It will contain 10th position digit of numb

if(numb<0)    {
numb = -1*numb;          // Make number positive
lcdchar('-');   // Display a negative sign on LCD
}
TenthDigit = (numb/10);                    // Find out Tenth Digit

if( TenthDigit != 0)                    // If it is zero, then don't display
lcdchar(TenthDigit+0x30);    // Make Char of TenthDigit and then display it on LCD
UnitDigit = numb - TenthDigit*10;
lcdchar(UnitDigit+0x30);    // Make Char of UnitDigit and then display it on LCD
}


Once the code is uploaded, you can test the calculator by using it to perform simple calculations such as addition, subtraction, multiplication, and division. If everything is working correctly, the calculator should display the results of the calculations on the LCD display.

Watch the following video demonstration of how this ATmega32 microcontroller based calculator works.

In conclusion, building a calculator with an ATmega32 microcontroller is a fun and educational project that can teach you about microcontroller programming and electronic circuit design. The ATmega32 microcontroller is a powerful and versatile chip that can be programmed to perform a wide range of functions, making it a great choice for building a calculator. With a little bit of time and effort, you can have a fully functional calculator that you can use to perform simple calculations.

If you are interested in this microcontroller based calculator and want to learn more about LCD and keypad see the following tutorials: