Eduardo Nahmad-Achar
Published © GPL3+

Advanced Calculator

Unary scientific calculator using a TFT_LCD touchscreen, for Exp, Ln, Sin, Tan, and 1/x.

IntermediateFull instructions provided747
Advanced Calculator

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
TFT_LCD Touchscreen Shield 2.4"
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

Advanced Calculator

for unary operations Exp, Ln, Sin, Tan, and 1/x

Schematics

sketch

just place TFT_LCD shield over Arduino UNO board

Code

Advanced calculator

Arduino
Unary calculator for exponential, natural logarithm, sine, tangent, and inverse functions.
/*
 * Unary calculator for Exp, Ln, Sin, Tan, and 1/x
 */

#include <Adafruit_GFX.h> 
#include <MCUFRIEND_kbv.h> 
#include <TouchScreen.h>

MCUFRIEND_kbv tft;          // define tft_lcd object (thin film transistor lcd)

#define MINPRESSURE 200
#define MAXPRESSURE 1000

// Touch panels vary; calibrate to get proper pins:
/* 
 These are the pins for the shield coordinates,
 obtained from TouchScreen_Calibr_native example
 (in MCUFRIEND.kvb examples):
*/
#define YP A2  // coordinate y plus
#define XM A1  // coordinate x minus
#define YM 6   // coordinate y minus
#define XP 7   // coordinate x plus

const int TS_LEFT=177,TS_RT=952,TS_TOP=213,TS_BOT=956;    // 240x320 ID=0x9340

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);    // define touchscreen object

#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define CYAN 0x07FF
#define LIGHTGREY 0xC618
#define GREY 0x8410
#define WHITE 0xFFFF
#define BUTTON_X 30
#define BUTTON_Y 123
#define BUTTON_W 51
#define BUTTON_H 50
#define BUTTON_SPACING_X 07
#define BUTTON_SPACING_Y 07
#define BUTTON_TEXTSIZE 2

char buttonlabels[16][5] = { "1", "2", "3","exp", "4", "5", "6","ln", "7", "8", "9","sin","DEL","0","1/x","tan"};
uint16_t buttoncolors[16] = { CYAN,CYAN,CYAN,GREY,CYAN,CYAN,CYAN,GREY,CYAN,CYAN,CYAN,GREY,RED,CYAN,GREY,GREY };
Adafruit_GFX_Button buttons[16];
int col=0,row=0,z=0, i, j;
#define TEXT_X 5
#define TEXT_Y 25
#define TEXT_W (tft.width()-10)
#define TEXT_H 70
#define TEXT_TSIZE 3
#define TEXT_TCOLOR BLUE
char q;               // button variable
int presskey;
static float num1;    // variable for input number

int operator_type=0;
#define TEXT_LEN 10
char textfield[TEXT_LEN+1] = "";
uint8_t textfield_i=0;
float result=0;

TSPoint tp;
boolean n=false;      // screen will be cleared when n=true
int nc;               // cases for button pressed
float fn;             // inputted number digit by digit
#define TS_MINX 138
#define TS_MINY 236
#define TS_MAXX 772
#define TS_MAXY 869

void setup()
{
Serial.begin(9600);             // only use for debugging
tft.reset();
uint16_t ID = tft.readID();

if (ID == 0xD3D3) ID = 0x9486;  // write-only shield
tft.begin(ID);
tft.setRotation(0);             //PORTRAIT
tft.fillScreen(LIGHTGREY);

//welcome screen
uint16_t width = tft.width() - 1;
uint16_t height = tft.height() - 1;
uint8_t border = 10;
tft.fillScreen(GREY);
tft.fillRect(border, border, (width - border * 2), (height - border * 2), WHITE); 
tft.setTextSize (3);
tft.setTextColor(RED);
tft.setCursor ((tft.width()/2)-70, 40);
tft.println("ADVANCED");
tft.setCursor ((tft.width()/2)-85, 85);
tft.println("CALCULATOR");
tft.setCursor ((tft.width()/2)-17, 160);
tft.setTextSize (2);
tft.setTextColor(BLACK);
tft.println("ENA");
tft.setTextColor(BLUE);
tft.setCursor ((tft.width()/2)-95, 250);
tft.println("Touch to Proceed");

//wait for touch
do{
  tp= ts.getPoint(); 
  pinMode(XM, OUTPUT);  // Pins for TFT control
  pinMode(YP, OUTPUT);
  } while((tp.z < MINPRESSURE ) || (tp.z > MAXPRESSURE));

tp.x = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
tp.y = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());

// calculator output screen
tft.fillScreen(LIGHTGREY);
tft.setCursor ((tft.width()/2)-65, 5);
tft.setTextSize (2);
tft.setTextColor(BLACK);
tft.println("Unary Mode");
tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, BLACK);

// Button initialize
for(int i=0;i<4;i++)
{
  for(int j=0;j<4;j++)
  {
    row=i;col=j;

    buttons[z].initButton(&tft, BUTTON_X+col*(BUTTON_W+BUTTON_SPACING_X), 
    BUTTON_Y+row*(BUTTON_H+BUTTON_SPACING_Y), // x, y, w, h, outline, fill, text
    BUTTON_W, BUTTON_H, BLACK, buttoncolors[z],BLACK,
    buttonlabels[z], BUTTON_TEXTSIZE); 
    buttons[z].drawButton();
    z++;
  }
}

}


void loop()
{
// wait for button press
do {
    tp= ts.getPoint(); 
    pinMode(XM, OUTPUT);  // Pins for TFT control
    pinMode(YP, OUTPUT);
   } while((tp.z < MINPRESSURE ) || (tp.z > MAXPRESSURE));

tp.x = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
tp.y = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());

// clear results
if (n == true)
{
  tft.setCursor(TEXT_X + 2, TEXT_Y+40);
  tft.setTextColor(TEXT_TCOLOR, LIGHTGREY);
  tft.setTextSize(TEXT_TSIZE);
  tft.print("            ");
  tft.setCursor(TEXT_X + 2, TEXT_Y+10);
  tft.print("            ");
  n = false;
}

//get button
for (uint8_t b=0; b<16; b++) 
{ 
  if (buttons[b].contains(tp.x, tp.y)) 
  {
    buttons[b].press(true); // button pressed
    q=b;
  } 
  else 
  {
    buttons[b].press(false); // button not pressed
  }
}

// when number button is pressed:
if(q == 0 || q==1 || q==2 || q== 4 || q==5 ||
    q==6 || q==8 || q==9 || q==10 || q==13)
{ 
  switch (q)
  {   
    case 0: nc = 1; pressed_button();animate();display_text(); break;
    case 1: nc = 2; pressed_button();animate();display_text(); break;
    case 2: nc = 3; pressed_button();animate();display_text(); break;
    case 4: nc = 4; pressed_button();animate();display_text(); break;
    case 5: nc = 5; pressed_button();animate();display_text(); break;
    case 6: nc = 6; pressed_button();animate();display_text(); break;
    case 8: nc = 7; pressed_button();animate();display_text(); break;
    case 9: nc = 8; pressed_button();animate();display_text(); break;
    case 10: nc = 9; pressed_button();animate();display_text(); break;
    case 13: nc = 0; pressed_button();animate();display_text(); break;
  }
}

// form input number digit by digit:
if (nc > 0 || q==13)
{
  switch (presskey)
  { // can input up to 5 digits:
    case 0: fn = nc; break;
    case 1: fn = fn*10 + nc; break;
    case 2: fn = fn*10 + nc; break;
    case 3: fn = fn*10 + nc; break;
    case 4: fn = fn*10 + nc; break;
  }

nc=0;
presskey++;   // 1st press = units; 2nd press = tens; 3rd press = hundreds; etc.
delay(200);
}


// when operator button is pressed:
if(q == 3 || q==7 || q==11 || q== 12 || q==14 || q==15 )
{
  presskey=0;
  num1 = fn;

  switch (q)
  {
    case 3: operator_type = 1; pressed_button();animate();display_result(num1); break;
    case 7: operator_type = 2; pressed_button();animate();display_result(num1); break;
    case 11: operator_type = 3; pressed_button();animate();display_result(num1); break;
    case 15: operator_type = 4; pressed_button();animate();display_result(num1); break;
    case 14: operator_type = 5; pressed_button();animate();display_result(num1); break;
    case 12: pressed_button();animate();clr_button(); break;
  }
}

}


// pressed button
void pressed_button()
{
textfield[textfield_i] = buttonlabels[q][0]; 
textfield_i++; 
textfield[textfield_i] = 0; // zero terminate
}


//Animate
void animate()
{
  if (buttons[q].justPressed()) 
  {
    buttons[q].drawButton(true); // draw invert
    delay(300);
    buttons[q].drawButton(); 
  } 
}


//text display
void display_text()
{
  tft.setCursor(TEXT_X + 2, TEXT_Y+10);
  tft.setTextColor(TEXT_TCOLOR, WHITE);
  tft.setTextSize(TEXT_TSIZE);
  tft.print(textfield);
}


//display result
void display_result(float num)
{ 
  switch (operator_type)
    {
    case 1:result=exp(num);break;
    case 2:result=log(num);break;
    case 3:result=sin(num);break;
    case 4:result=tan(num);break;
    case 5:result=1/num;break;
    }
  tft.setCursor(TEXT_X + 2, TEXT_Y+40);
  tft.setTextColor(TEXT_TCOLOR, WHITE);
  tft.setTextSize(TEXT_TSIZE);
  tft.print('=');
  tft.print(result,4);    // result to 4 decimal places
}


//clr button
void clr_button()
{ 
  q=0;
  num1 = 0; 
  nc=0;
  fn=0;
  result=0;
  //char textfield[TEXT_LEN+1] = "";
  tft.setCursor(TEXT_X + 2, TEXT_Y+40);
  tft.setTextColor(TEXT_TCOLOR, LIGHTGREY);
  tft.setTextSize(TEXT_TSIZE);
  tft.print("            ");
  tft.setCursor(TEXT_X + 2, TEXT_Y+10);
  tft.print("            ");
  textfield_i=0;
  operator_type=0; 
  n=true;
}

Credits

Eduardo Nahmad-Achar

Eduardo Nahmad-Achar

1 project • 0 followers

Comments