calculator

Status
Not open for further replies.

vtr

New member
hi, first real Teensy project.

Im building a simple calculator (just adds up numbers really) for my darts scoreboard using teensy 3.1

But having difficulty with correctly adding in the third line eg. 40+20=60 works, but 40+20+20 doesn't yet.

it displays on an lcd display (40x4) like this:

IMG_0656.jpg

Can anybody show me where I am going wrong?

Code:
#include<Keypad.h>
#include<LiquidCrystal_I2C.h>
#include<Wire.h>
//#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_7segment matrix = Adafruit_7segment();
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '='},
  {'7', '8', '9', 'C'},
  {'+', '0', '=', }
};

byte rowPins[ROWS] = {1, 2, 3, 4};
byte colPins[COLS] = {5, 6, 7, 8};

// this section not completed yet : using momentary buttons w/10k pullup resistors
//const byte switchPin = 15; // player one 'ENTER' button -deducts score from LED display 0x71.
//const byte switchPin = 17; // player two 'ENTER' button -deducts score from LED display 0x72.

// 
Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 20, 4);

boolean firstNumState = true;
boolean secondNumState = true;
boolean thirdNumState = true;
String firstNum = "";
String secondNum = "";
String thirdNum = "";
int result = 0;
char operatr = ' ';


void setup() {
  lcd.begin();
  lcd.setCursor(0, 0);
  lcd.print("Darts Scoreboard");
  lcd.setCursor(0, 1);
  lcd.print("v1.0");
  delay(1000);
 // scrollDisplay();
  clr();
{
#ifndef __AVR_ATtiny85__
  Serial.begin(9600);
  //Serial.println("0");
  delay(600);
#endif

  matrix.begin(0x70);
  matrix.setBrightness(3);
  matrix.print(0x0, HEX);
  matrix.writeDisplay();
  delay(600);
  
  matrix.begin(0x71);
  matrix.setBrightness(3);
  matrix.print(0x501, HEX);
  matrix.writeDisplay();
  delay(800);

matrix.begin(0x72);
  matrix.setBrightness(3);
  matrix.print(0x501, HEX);
  matrix.writeDisplay();
  delay(800);

}

}




void loop() {
  char newKey = myKeypad.getKey();
  if (newKey != NO_KEY && (newKey == '1' || newKey == '2' || newKey == '3' || newKey == '4' || newKey == '5' || newKey == '6' || newKey == '7' || newKey == '8' || newKey == '9' || newKey == '0')) {

    if (firstNumState == true) {
      firstNum = firstNum + newKey;

      lcd.print(newKey);
    
  }
    else {
      secondNum = secondNum + newKey;

      

      lcd.print(newKey);
    }
}
  
  if (newKey != NO_KEY && (newKey == '+' )) {
    if (secondNumState == true) {
      operatr = newKey;
      firstNumState = true; secondNumState = false;
      lcd.setCursor(8, 0);
      lcd.print(operatr);
      lcd.setCursor(5, 1);
      
    }
  }
    
/*if (newKey != NO_KEY && (newKey == '+' )) {
    if (thirdNumState == true) {
      operatr = newKey;
      firstNumState = false; secondNumState = true; thirdNumState = false;
      //lcd.setCursor(5, 1);
      lcd.print(secondNum);
      lcd.setCursor(7, 1);
      lcd.print(operatr);
      lcd.setCursor(5, 1);
    }

}*/

 if (newKey != NO_KEY && (newKey == '+' )) {
    if (thirdNumState == true) {
      operatr = newKey;
      firstNumState = false; secondNumState = false; thirdNumState = true;
      lcd.setCursor(5, 1);
      lcd.print(thirdNum);
      lcd.setCursor(8, 1);
      lcd.print(operatr);
      lcd.setCursor(5, 1);
    }


  
  }

  if (newKey != NO_KEY && newKey == '=') {
    if (operatr == '+') {
      result = firstNum.toInt() + secondNum.toInt() + thirdNum.toInt();
    }
    // 
  
    //lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print(firstNum);
    lcd.setCursor(8, 0);
    lcd.print(operatr);
    lcd.setCursor(5, 1);
    lcd.print(secondNum);
    lcd.setCursor(8, 1);
    lcd.print(operatr);
    lcd.setCursor(5, 2);
    lcd.setCursor(8, 2);
    lcd.print(thirdNum);
    lcd.setCursor(8, 2);
    //lcd.print("=");
    lcd.setCursor(5, 3);
    lcd.print(result);

    //matrix.print(result);
    matrix.begin(0x70);     
    matrix.setBrightness(3);
    matrix.print(result,10);   //prints total score displayed on calculator to LED display 0x70
  matrix.writeDisplay();
  delay(500);
   
    firstNumState = true; secondNumState = true; thirdNumState = true;
  }

  if (newKey != NO_KEY && newKey == 'C') {
    clr();
  }
} 



void clr() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("1st: ");
  lcd.setCursor(0, 1);
  lcd.print("2nd: ");
  lcd.setCursor(0, 2);
  lcd.print("3rd: ");
  lcd.setCursor(5, 0);
  firstNum = "";
  lcd.setCursor(5, 1);
  secondNum = "";
   lcd.setCursor(5, 2);
  thirdNum = "";
   lcd.setCursor(5, 0);
  //result = 0;
  //operatr = ' ';



  lcd.setCursor(10, 0);
  lcd.print("Leg: ");
  lcd.setCursor(10, 1);
  lcd.print("Ave:      ");
  lcd.setCursor(10, 2);
  lcd.print("Leg: ");
  lcd.setCursor(10, 3);
  lcd.print("Ave:      ");
  lcd.setCursor(5, 0);
  firstNum = "";
  lcd.setCursor(5, 1);
  secondNum = "";
   lcd.setCursor(5, 2);
  thirdNum = "";
  lcd.setCursor(0,3 );
  lcd.print("Scr:    "); 
  lcd.setCursor(5, 3);
  result = 0;
  lcd.setCursor(5,0 );
}

IMG_0655.jpg

Original base code sourced from here https://maker.pro/arduino/projects/how-to-create-an-arduino-controlled-calculator
 
Last edited:
vtr said:
...if you want to throw some light in my direction, I would be most grateful, its prob so easy, nobody wants to comment on it...
It's actually very difficult to troubleshoot a complex bit of code without the hardware.

But I'm pretty sure you are not setting the state variable you've added correctly (or the others you've inherited).

You test it for 'true' and set it to 'true' but you never set it to 'false'; so it cannot be doing anything for you.

I started to look for all the places you've omitted setting the state variables or set them incorrectly but it's basically everywhere.

You need to go through the original author's code explanation line by line to see how he meant it to work before you have any hope of extending it.

I think it works by shifting the state variables so that first is made FALSE when an operator is pressed and the second becomes TRUE. When the equals is detected the second becomes FALSE and then (after printing the result) the first become TRUE (one you've removed!).

This seems redundant to me even though they are set separately I can't see the need for separate variables.

Instead an integer (or unsigned integer) could count through and retain the index of the active value you're typing with the plus key as an increment and the equal key a reset to the starting value while triggering the calculation and display.

If its on the final index the + could also trigger the calculation and reset.
 
Looks like the handling of the #NumState vars are not kept straight.

Second goes to First not Third

Code:
  if (newKey != NO_KEY && (newKey == '+' )) {
    if (secondNumState == true) {
      operatr = newKey;
      firstNumState = true; secondNumState = false;
 
Code:
  if (newKey != NO_KEY && (newKey == '+' )) {
    if (secondNumState == true) {
      operatr = newKey;
      firstNumState = true; secondNumState = false;
      lcd.setCursor(8, 0);
      lcd.print(operatr);
      lcd.setCursor(5, 1);
      
    }
  }
I think this is the part of your changes that stops the third number from sequencing .... it might have been closer if you made thirdNumState = TRUE here but you were still missing other parts...

With an integer state variable it might look like this:
Code:
  if (newKey != NO_KEY && (newKey == '+' )) {
    operatr = newKey; // you don't need this if + is your only operator (I think!?)
    numState++
    lcd.setCursor(8, 0);
    lcd.print(operatr);
    lcd.setCursor(5, 1);
  }

Then if you increment past your last field you can force the cacluation
 
untested alteration to your code will likely need a few fixes to even compile but hopefully shows the alternate state variable scheme.
Code:
#include<Keypad.h>
#include<LiquidCrystal_I2C.h>
#include<Wire.h>
//#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_7segment matrix = Adafruit_7segment();
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '='},
  {'7', '8', '9', 'C'},
  {'+', '0', '=', }
};

byte rowPins[ROWS] = {1, 2, 3, 4};
byte colPins[COLS] = {5, 6, 7, 8};

// this section not completed yet : using momentary buttons w/10k pullup resistors
//const byte switchPin = 15; // player one 'ENTER' button -deducts score from LED display 0x71.
//const byte switchPin = 17; // player two 'ENTER' button -deducts score from LED display 0x72.

// 
Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 20, 4);

[COLOR="#FF0000"]int numState = 1;[/COLOR]
String firstNum = "";
String secondNum = "";
String thirdNum = "";
int result = 0;
//char operatr = ' ';  it's always +

void setup() {
  lcd.begin();
  lcd.setCursor(0, 0);
  lcd.print("Darts Scoreboard");
  lcd.setCursor(0, 1);
  lcd.print("v1.0");
  delay(1000);
 // scrollDisplay();
  clr();


  // ??
#ifndef __AVR_ATtiny85__
  Serial.begin(9600);
  //Serial.println("0");
  delay(600);
#endif

  matrix.begin(0x70);
  matrix.setBrightness(3);
  matrix.print(0x0, HEX);
  matrix.writeDisplay();
  delay(600);
  
  matrix.begin(0x71);
  matrix.setBrightness(3);
  matrix.print(0x501, HEX);
  matrix.writeDisplay();
  delay(800);

matrix.begin(0x72);
  matrix.setBrightness(3);
  matrix.print(0x501, HEX);
  matrix.writeDisplay();
  delay(800);

}





void loop() {
  char newKey = myKeypad.getKey();
  if (newKey != NO_KEY && (newKey == '1' || newKey == '2' || newKey == '3' || newKey == '4' || newKey == '5' || newKey == '6' || newKey == '7' || newKey == '8' || newKey == '9' || newKey == '0')) {
    
    
[COLOR="#FF0000"]    // numState is incremented through these '}else if{' structures when + is detected until = is detected
    if (numState == 1) { [/COLOR]

      firstNum = firstNum + newKey;

      lcd.print(newKey);
    
[COLOR="#FF0000"]    } else if (numState == 2) {[/COLOR]
      secondNum = secondNum + newKey;

      lcd.print(newKey);
[COLOR="#FF0000"]    } else if (numState == 3) {[/COLOR]
      thirdNum = thirdNum + newKey;

      lcd.print(newKey);
     
    }else{
      // fire calcultation?
    }

  
  if (newKey != NO_KEY && (newKey == '+' )) {
    operatr = newKey;
[COLOR="#FF0000"]    numState++[/COLOR]
    lcd.setCursor(8, 0);
    lcd.print(operatr);
    lcd.setCursor(5, 1);
  }
    



  if (newKey != NO_KEY && newKey == '=') {

    result = firstNum.toInt() + secondNum.toInt() + thirdNum.toInt();
    // 


    //lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print(firstNum);
    lcd.setCursor(8, 0);
    lcd.print("+");
    lcd.setCursor(5, 1);
    lcd.print(secondNum);
    lcd.setCursor(8, 1);
    lcd.print("+");
    lcd.setCursor(5, 2);
    lcd.setCursor(8, 2);
    lcd.print(thirdNum);
    lcd.setCursor(8, 2);
    //lcd.print("=");
    lcd.setCursor(5, 3);
    lcd.print(result);

    //matrix.print(result);
    matrix.begin(0x70);     
    matrix.setBrightness(3);
    matrix.print(result,10);   //prints total score displayed on calculator to LED display 0x70
  matrix.writeDisplay();
  delay(500);
   
[COLOR="#FF0000"]    numState = 1; // reset for next calculation[/COLOR]
  }

  if (newKey != NO_KEY && newKey == 'C') {
    clr();
  }
}



void clr() {
  // This seems a bit of a mess?
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("1st: ");
  lcd.setCursor(0, 1);
  lcd.print("2nd: ");
  lcd.setCursor(0, 2);
  lcd.print("3rd: ");
  lcd.setCursor(5, 0);
  firstNum = "";
  lcd.setCursor(5, 1);
  secondNum = "";
   lcd.setCursor(5, 2);
  thirdNum = "";
   lcd.setCursor(5, 0);
  //result = 0;




  lcd.setCursor(10, 0);
  lcd.print("Leg: ");
  lcd.setCursor(10, 1);
  lcd.print("Ave:      ");
  lcd.setCursor(10, 2);
  lcd.print("Leg: ");
  lcd.setCursor(10, 3);
  lcd.print("Ave:      ");
  lcd.setCursor(5, 0);
  firstNum = "";
  lcd.setCursor(5, 1);
  secondNum = "";
   lcd.setCursor(5, 2);
  thirdNum = "";
  lcd.setCursor(0,3 );
  lcd.print("Scr:    "); 
  lcd.setCursor(5, 3);
  result = 0;
  lcd.setCursor(5,0 );
}

The else-ifs could be replaced by a case statement but I'm not a huge fan.
 
I just wanted to thank you guys for looking into this already... yes, this is exactly the part of the code I was having difficulty processing (in my head).

Sorry Im such a newb @ coding... I was hoping that adding a few numbers together then taking them away from a prescribed total and displaying it, would be within my scope right away. :rolleyes:

but the code seems to get really big and more difficult to compartmentalize very, very quickly;

I will examine and try to integrate all of your suggestions and let you know as soon as possible (Defragster's suggestion & Oddson's post #5 looks very promising at first glance) - thanks again to all who looked into it so far, you guys are awesome :cool:.
 
Last edited:
I think pressing [+] twice on mine would skip a field... the logic should check that ordinalNum has a digit already before incrementing.
 
Status
Not open for further replies.
Back
Top