## Tinkering With A Basic Calculator CloudX

##### Project Details

Let's learn how to design a simple calculator using a keypad and an LCD (Liquid Crystal Display). The circuit connection is very much a simple one; and we’ll be making use of the breadboard and a simple CloudX code to actualize the project.

Just punching away on my calculator the other day, it somewhat occurred to me it would definitely be a nice idea for us to learn the simple basics of a calculator design! With the skill, we can advance farther to design a more complicated one like the commercial ones out there in the market.

In this lesson, we'll be implementing the calculator using a 4x4 Keypad and a 16x2 LCD. And to further simplify things, we'll be utilizing CloudX libraries specifically meant for ease of handling both the keypad and the LCD modules respectively.

List Of Materials Needed

CloudX Microcontroller and Softcard

16x2  LCD Display

•  Resistor:
1. (i)    1 kΩ
2. (ii)   10 kΩ x 4 units

### Section 1:  Hints and Brief Overview

#### KeyPadThe keypad is a small keyboard that is used to input numeric, alphabetic or alphanumeric data into microcontroller systems. It is sometimes referred to as a Matrix Keypad due to how the push button switches, making up the architecture, are arranged in rows and columns. It is available in different shades and sizes ranging from a 2x2, a 4x3, a 4x4, and so on. Here, we’re making use of a 4x4 matrix keypad as shown below.

It has the internal architecture as thus depicted below.

#### Liquid Crystal Display (LCD)  The LCD is used to display  alphanumeric  or  graphical  data. Here, we’re using a variant called 16x2 LCD module. That simply implies 16 columns and 2 rows of display capability.

It has the pin-out as follows:

### Section 2: The Circuit and the Code

#### The Circuit

The whole project runs on the simple block diagram as follows:

Just as demonstrated in the schematic diagram below:

The LCD module, being basically used in a 4-bit communication mode, interfaces with the MCU (microcontroller) such that its pins RS, EN, D4, D5, D6 and D7 connect up to the MCU’s pins P1, P2, P3, P4, P5 and P6 respectively.

1kΩ resistor is connected to the LCD Vo pin through to ground to set the display contrast. (However, one is at liberty to experiment with say a 10kΩ variable resistor to adjust the contrast to one’s more desired point).

Then, the matrix keypad does the interfacing with the Rows 1, 2, 3 and 4 connecting up to the MCU’s pins P7, P8, P9 and P10 respectively; whereas its Columns 1, 2, 3 and 4 connect up to MCU’s pins P11, P12, P13 and P14 respectively.

The matrix keypad internal structure and microcontroller interfacing is illustrated as thus:

The microcontroller module, being at the heart of the working here, can be powered on:
(i)  either via the VIN and the GND points (ie. connecting them up to your external power-supply-unit’s  +ve and –ve terminals respectively) on the board. (The PSU can  range from  7 – 12 VDC);
(ii)  or through your CloudX USB softcard module.

Refer to the table below to check out the details of the rest of other necessary connections.

### The Source Code

The code is written in simple and plain C language as follows:

`#include <CloudX\LCD.h> #include <CloudX\Keypad.h> #include <CloudX\conversion.h> #include <string.h> #include <math.h> #define noIndicator 0 #define error       10 //------------------------------------------- //The below declare and define parameters for  //the keypad module configuration. //------------------------------------------- #define NumberOfRows     4    //sets keypad to four rows #define NumberOfColumns  4    //sets keypad to three columns char  KeypadCharacters[NumberOfRows][NumberOfColumns] =  {     '1', '2', '3', '-',     '4', '5', '6', 'x',     '7', '8', '9', '/',     'C', '0', '=', '+' };  char RowPins[NumberOfRows]         =  {7, 8, 9, 10}; char ColumnsPins[NumberOfColumns]  =  {11, 12, 13, 14}; char keys;           //keys char for keeping record of pressed key char _operator;      //Function to be performed among two operands (numbers) char number; char _text[9]; char *text0; byte operand1 = 0;       //first number byte operand2 = 0;       //second number //------------------------------------------------------- //The below declare and define the custom-char arrays for  //both a division-symbol and an infinity-symbol. //NB: //Refer to CloudX Custom-Char Generator App to create any  //desired custom character for the LCD. //------------------------------------------------------- const char divisionSign[] = {0, 4, 0, 31, 0, 4, 0, 0}; const char infinitySign[] = {0, 10, 21, 21, 10, 0, 0, 0}; /***     RELEVANT FUNCTIONS USED FOR PROJECT      ***/ void displayResult(int value);     //displays the evaluation result void displayFloatRes(float value); //displays evaluation result that is                                    //of float data-type                                    void mathOperation(unsigned char pointer); //handles the maths/arithmetic operation void errorMessage(byte caseValue);         //displays different error messages byte getOperand(char charValue);           //fetches the operands char getOperator(char checkOperator);      //detects the operator errors  void Get_keyPressed();                     //scans and fetches any possible key-press                          setup(){           //setup here                      //The keypad-module configured utilizing the already declared parameters above//           Keypad_setting (PULLDOWNCOL, RowPins, ColumnsPins, NumberOfRows, NumberOfColumns, KeypadCharacters, noIndicator);                      LCD_setting(1, 2, 3, 4, 5, 6); //RS, EN, D4, D5, D6, D7           LCD_cmd(cursorOff);           LCD_cmd(clear);           LCD_writeText(1, 4, "Calculator");           LCD_writeText(2, 3, "With CloudX");           delayMs(1500);           LCD_cmd(clear);                LCD_write(1, 1, '0');               loop(){           //Program here                    //---------------------------------------------        //This routine fetches the first operand (num1)        //---------------------------------------------        Get_keyPressed();        LCD_cmd(clear);                 //clears LCD screen         LCD_write(1, 1, keys);          //echoes the key pressed to LCD        operand1 = getOperand(keys);    //gets int number from char value, it checks for wrong input as well        if(operand1 isNot error)        //if correct input then proceed, num1==Error means wrong input        {                    //----------------------------------------          //This routine gets the operator function          //----------------------------------------          Get_keyPressed();          if((keys is '+') or (keys is '-') or (keys is 'x') or (keys is '/'))          {              if(keys is '/')                 LCD_writeCustomChar(0, 1, 3, divisionSign); //CGRAMAddress, row, col, customCharacter              else                 LCD_write(1, 3, keys);              _operator = getOperator(keys);          }          else            {              LCD_writeCP(keys);              number = getOperand(keys);              if(number isNot error)              {                   operand1 = (operand1*10) + number;                   Get_keyPressed();                   if(keys is '/')                       LCD_writeCustomChar(0, 1, 4, divisionSign); //CGRAMAddress, row, col, customCharacter                   else                       LCD_write(1, 4, keys);                   _operator = getOperator(keys);               }              else                  _operator = getOperator(keys);            //checks for wrong operator              }              if(_operator isNot error)                                {                   //-----------------------------------------------                   //This routine fetches the second operand (num2)                   //-----------------------------------------------                   Get_keyPressed();                   LCD_writeCP(' ');                   LCD_writeCP(keys);                   //echoes the key pressed on LCD                   operand2 = getOperand(keys);         //Get int number from char value, it checks for wrong input as well                   if(operand2 isNot error)                               {                        //----------------------------------------                        //This routine fetches the equal-sign (=)                        //----------------------------------------                        Get_keyPressed();                        if(keys is '=')                           mathOperation(_operator);                        else                         {                            LCD_writeCP(keys);     //echoes the key pressed on LCD                           number = getOperand(keys);                           if(number isNot error)                           {                              operand2 = (operand2 * 10) + number;                              Get_keyPressed();                              if(keys is '=')                                mathOperation(_operator);                           }                           else if(keys is '=')           //if = is pressed, then proceed                               mathOperation(_operator);                           else if(keys is 'C')       //if clear screen is pressed, then clear screen and reset                           {                               LCD_cmd(clear);                                LCD_write(1, 1, '0');                           }                           else                               errorMessage(0);     //displays wrong input error                        }                   }              }        }    } } ////////////////////////////////////////////////////////////////// /////////      The Relevant Function-Definitions        ////////// //////////////////////////////////////////////////////////////////   void displayResult(int value)      {            intTostr(_text, value, DEC);     LCD_writeText(2, 1, "ANS: ");     LCD_writeTextCP(_text); } void displayFloatRes(float value)  {           text0 = floatTostr(value);    text0[8] = 0;    LCD_writeText(2, 1, "ANS: ");    LCD_writeTextCP(text0); } void mathOperation(unsigned char pointer)  {       switch(pointer) {        case '+' : displayResult(operand1 + operand2); break;        case '-' : displayResult(operand1 - operand2); break;        case 'x' : displayResult(operand1 * operand2); break;        case '/' : if(operand2 is 0) {        LCD_writeText(2, 1, "ANS: ");                        LCD_writeCustomChar(1, 2, 6, infinitySign); //CGRAMAddress, row, col, customCharacter                        LCD_writeText(2, 7, "infinity");                        break;                    }                   else                    {                        displayFloatRes((float)operand1 / operand2);                        break;                   }       } } byte getOperand(char charValue)          {    byte operand;    switch(charValue)    {        case '0' : operand = 0; break;        case '1' : operand = 1; break;        case '2' : operand = 2; break;        case '3' : operand = 3; break;        case '4' : operand = 4; break;        case '5' : operand = 5; break;        case '6' : operand = 6; break;        case '7' : operand = 7; break;        case '8' : operand = 8; break;        case '9' : operand = 9; break;                //---------------------------------------        //This clears the screen and sets error;        //and resets the system.        //---------------------------------------        case 'C' : LCD_cmd(clear);                    LCD_write(1, 1, '0');                   operand = error;                   break;                  //-------------------------        //This signals wrong input.        //-------------------------                   default  : errorMessage(0);                    operand = error;                    break;           }    return operand; } char getOperator(char checkOperator)            //detects the operator errors  {    if(checkOperator is 'C')                    //if clear-screen, then clear display and reset    {      LCD_cmd(clear);                           //clears display      LCD_write(1, 1, '0');      return error;    }  if((checkOperator isNot '+') and (checkOperator isNot '-') and (checkOperator isNot 'x') and (checkOperator isNot '/'))  //if input is out of the allowable range, display error    {      errorMessage(1);      return error;    }    return checkOperator;                  }   void errorMessage(byte caseValue)          //displays different error messages {     LCD_cmd(clear);                  switch(caseValue)    {        case 0  : LCD_writeText(1, 1, "Wrong Input");                  delayMs(500);                  LCD_cmd(clear);                  LCD_write(1, 1, '0');                  break;                          case 1  : LCD_writeText(1, 1, "Wrong Operator");                  delayMs(500);                  LCD_cmd(clear);                  LCD_write(1, 1, '0');                  break;                          default : LCD_writeText(1, 1, "Wrong Input");                  delayMs(500);                  LCD_cmd(clear);                  LCD_write(1, 1, '0');                  break;    } } void Get_keyPressed()  {   do   keys = Keypad_getKey();   while(keys is 0); }     `

That comes to an end the project.