0

I have written a simple calculator program for an LCD keypad shield. It works fine except for the multiplication case. It gives me zero. However, I have noticed that when I enclose the expression num1 * num2 in parenthesis it does work. Why is that so?

#include <LiquidCrystal.h>

LiquidCrystal lcd (8, 9, 4, 5, 6, 7);


void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {

  float ans = 0;

  lcd.print("Starting Calc");
  delay(500);

  lcd.clear();
  lcd.print("Enter 1st Num");
  while (Serial.available() == 0) {}
  float num1 = Serial.parseFloat();

  lcd.clear();
  lcd.print("Enter 2nd Num");
  while (Serial.available () == 0) {}
  float num2 = Serial.parseFloat();

  lcd.clear();
  lcd.print("Enter Operator");
  lcd.setCursor(0, 1);
  lcd.print(" R+, U*, D/, L- ");
  int val = analogRead(A0);

  while (val > 1000) {
    val = analogRead(A0);
  }

  if (val == 0) { // addition
    ans = num1 + num2;
  }

  if (val >= 97 && val <= 98) { // multiplication
    ans = num1 * num2;
  }

  if (val >= 253 && val <= 254) { // division
    ans = num1 / num2;
  }

  if (val >= 407 && val <= 408) { // subtraction
    ans = num1 - num2;
  }

    lcd.clear();
    lcd.print("Answer is = ");
    lcd.print(ans);
    delay(2000);
}

Modified Code

#include <LiquidCrystal.h>

LiquidCrystal lcd (8, 9, 4, 5, 6, 7);

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {

  float ans = 0.0;

  lcd.print("Starting Calc");
  delay(500);

  lcd.clear();
  lcd.print("Enter 1st Num");
  while (Serial.available() == 0) {}
  float num1 = Serial.parseFloat();

  lcd.clear();
  lcd.print("Enter 2nd Num");
  while (Serial.available () == 0) {}
  float num2 = Serial.parseFloat();

  lcd.clear();
  lcd.print("Enter Operator");
  lcd.setCursor(0, 1);
  lcd.print(" R+, U*, D/, L- ");

  // here we split our logic.. first repeatedly read input value until valid operator read
  // secondly we perform the arithmetic operation accordingly

  char input = ' '; // space = no operator read so far
  int val;

  do {
    val = analogRead(A0);
    // see how if statements are written concisely for readability
    // if only one statement after condition you can skip curly brackets
    if (val == 0) input = '+';
    if (val >= 97 && val <= 98) input = '*';
    if (val >= 253 && val <= 254) input = '/';
    if (val >= 407 && val <= 408) input = '-';
  } while (input == ' ');

  Serial.println(input);
  Serial.println(num1);
  Serial.println(num2);
  delay(1000);


  // perform arithmetic operation
    switch (val) { // not written in a standard way but very readable
      case '+': ans = num1 + num2; break;
      case '-': ans = num1 - num2; break;
      case '*': ans = num1 * num2; break;
      case '/': ans = num1 / num2; break;
    }

  lcd.clear();
  lcd.print("Answer = ");
  lcd.print(ans);
  delay(2000);
}
2
  • I think you're looking in the wrong place. The brackets make no difference. Instead you should be looking at your usage of parseFloat.
    – Majenko
    Commented Apr 27, 2020 at 15:56
  • I also don't think that brackets don't make a difference. However, I don't see any problem with my usage of parseFloat. It seems to work for other operations. Do you see an issue here?
    – Zaffresky
    Commented Apr 27, 2020 at 16:10

1 Answer 1

0

The parentheses should definitely make no difference. My guess is that what you saw was just a coincidence. The analog ranges you have defined are extremely narrow. Any instability in the circuit can throw your readings out of the expected ranges. If you get a reading that does not fit in any of those ranges, none of the if conditions will evaluate to true, and you end up with the result being zero, as this is how you initialized the variable ans.

I suggest two changes to your program:

  1. Make the ranges wider
  2. Repeatedly read the analog input until you get a valid reading.

To illustrate the second item, here is a code snippet that splits the logic of you if chain in two parts: first read the operator (repeatedly until we get a valid reading), then perform the operation:

// Read the operator.
char op = ' ';  // space = no operator read so far
do {
    int val = analogRead(A0);
    if (val == 0) op = '+';
    if (val >= 97 && val <= 98) op = '*';
    if (val >= 253 && val <= 254) op = '/';
    if (val >= 407 && val <= 408) op = '-';
} while (op == ' ');

// Perform the operation.
switch (op) {
    case '+': ans = num1 + num2; break;
    case '*': ans = num1 * num2; break;
    case '/': ans = num1 / num2; break;
    case '-': ans = num1 - num2; break;
}
3
  • Thanks a lot for your clear explanation. I fully agree that I was getting 0 occasionally due to circuit instability. I didn't know about do... while loops but now I do :) The program should have worked now but mysteriously the "ans" variable is not being updated by switch case. I tried it with if statements but it also doesn't work. I wonder what's causing this? P.s. I have uploaded the modified code in the original post.
    – Zaffresky
    Commented Apr 28, 2020 at 13:51
  • @Zaffresky: Oops, my bad! The switch should be done on the selected operator, not on the analog value. I just edited the answer. Commented Apr 28, 2020 at 14:15
  • 1
    Bingo. It works nicely :) Thanks
    – Zaffresky
    Commented Apr 28, 2020 at 16:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.