How to convert ascii to int ?

Hi , i´m new to this community.
I just start with learning the C language of arduino.
I found a schets at your "programming question side" to make a calculation with two figures, a program which I can use. The problem is, the result at the end. It will show the result as an ASCII figure.

I read that I have to use "atoi" in my program, but the question is how and where ?

I´m 72, so it will take a little bit longer to understand everything.

I will insert the program so that you have a better understanding of what I mean.

Can you help me please with this.

Thanks in advance.

Francois

#include <Keypad.h>
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27);  // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <stdio.h> //you must include this library to get the atoi function
#include <stdlib.h>

int Addition(int a, int b)
{
  int z;
  z = a + b; // z is now the integer sum
  lcd.print( z, DEC); // print the decimal value of z (default is ascii)
}

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

const byte rows = 4;
const byte cols = 4;

char keys[rows][cols] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};


byte rowPins[rows] = {9, 8, 7, 6};
byte colPins[cols] = {5, 4, 3, 2};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

void loop() {

  char a;
  char b;

  a = keypad.getKey();
  if (a != NO_KEY) {

    do {
      b = keypad.getKey();
    } while (b == NO_KEY);

    lcd.setBacklight(255);
    lcd.begin(16, 2);
    lcd.clear();

    lcd.setCursor(0, 0);
    lcd.print(a), DEC;

    lcd.setCursor(1, 0);
    lcd.write("+");

    lcd.setCursor(2, 0);
    lcd.print(b), DEC;

    lcd.setCursor(3, 0);
    lcd.print("=");

    Addition(a, b);
    delay(500);
  }
}

It's not clear from your program what "ascii" you would like to convert. The atoi() function does not appear in your program.

If what you are trying to do is convert the value returned by the keypad to a number than I suspect there is no need for atoi().

If the keypad returns a character representation of a number for example the character '3' then you can convert that to a number like this

byte myNumber = myChar - '0'';

The ASCII code for '3' is 51 and the ASCII for '0' is 48 so 51 - 48 = 3

Link to the documentation for atoi()

...R

1 Like

Robin2:
It's not clear from your program what "ascii" you would like to convert. The atoi() function does not appear in your program.

Probably the ASCII in the keypad table.

AWOL:
Probably the ASCII in the keypad table.

I believe I have covered the bulk of that :slight_smile:

...R

I´m sorry. I explained myself wrong. I changed now "z = a*10+b" by "z=a+b" in the existing program I

sent to you in my previous message. This to make it more clear what I want.

If I give in 1+1. That has to be 2 as result. The result I got is 98. Thats what I mention with

the " ASCII "result. The program add two times 49 (the ASCII code).

The question is, how can I fix it so that it would be 2 and not 98 as result.

What do I have to change and where ?

#include <Keypad.h>
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <stdio.h> //you must include this library to get the atoi function
#include <stdlib.h>

int Addition(int a, int b)
{
int z;
z = a + b; // z is now the integer sum
lcd.print( z, DEC); // print the decimal value of z (default is ascii)
}

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

const byte rows = 4;
const byte cols = 4;

char keys[rows][cols] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[rows] = {9, 8, 7, 6};
byte colPins[cols] = {5, 4, 3, 2};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

void loop() {

char a;
char b;

a = keypad.getKey();
if (a != NO_KEY) {

do {
b = keypad.getKey();
} while (b == NO_KEY);

lcd.setBacklight(255);
lcd.begin(16, 2);
lcd.clear();

lcd.setCursor(0, 0);
lcd.print(a), DEC;

lcd.setCursor(1, 0);
lcd.write("+");

lcd.setCursor(2, 0);
lcd.print(b), DEC;

lcd.setCursor(3, 0);
lcd.print("=");

Addition(a, b);
delay(500);
}
}

Subtract '0' from the ASCII value to get the actual value

Hi, ASCII characters are to make things easy for humans, when it comes to computers and microcontrollers it is easier for them to work with numbers.

So when you fill an array with ASCII characters the controller sees the ASCII code value and not the character, for example you have already shown that you recognize the value 49 as being the character code for ASCII character '1', notice the single quotes they appear elsewhere in your code.

char keys[rows][cols] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

the above could just as easily have been written with the character codes but using the characters is easier for us to read, here it is with the character codes.

char keys[rows][cols] = {
  {49, 50, 51, 65},
  {52, 53, 54, 66},
  {55, 56, 57, 67},
  {42, 48, 35, 68}
};

What people have been trying to point out to you is that if you subtract 48 from the character code you will end up with the numeric value that the character represents. For example character '9' = character code 57 if you subtract 48 from 57 you get the numeric value 9.

This will fix it for now

void Addition(int a, int b)
{
  int z=(a+b)-96; // z is now the integer sum
  lcd.print( z, DEC); // print the decimal value of z (default is ascii)
}

@OP

1. For some reasons, your program gives the following result when executed in my NANO+LCD+Keypad system.

Press the button 1 for twice and then the LCD shows: 1Z1 = 98.

2. To show the following message on the LCD, I have corrected/adjusted your posted program
as listed beneath.

Press 1, LCD shows: 1+
Press 1 again, LCD show: 1+ 1 = 98.

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <stdio.h> //you must include this library to get the atoi function
#include <stdlib.h>

const byte rows = 4;
const byte cols = 4;

byte rowPins[rows] = {9, 8, 7, 6};
byte colPins[cols] = {5, 4, 3, 2};


char keys[rows][cols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
char a;
char b;
int charCounter = 0;
bool flag1 = false;

void setup()
{
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

}

void loop()
{
  a = myKeypad.getKey();
  if (a != NO_KEY)
  {
    if (flag1 == false)
    {
      lcd.print(a);
      lcd.print("+"); //LCD shows: 1 +
      charCounter++;
      if (charCounter == 1)
      {
        flag1 = true;
      }
    }
    else
    {
      b = a;
      lcd.print(b);
      charCounter++;
      if (charCounter == 2)
      {
        lcd.print("=");
        int sum = Addition(a, b);
        lcd.print(sum, DEC);
        charCounter = 0;
      }
    }
  }
}

int Addition(int a, int b)
{
  int z;
  z = a + b; // z is now the integer sum
  return (z); 
}

3. Let us investigate your codes (corrected/adjusted program),
why the program does produce: 1 + 1 = 98 and not 1 + 1 = 2.
....will continue after sometimes!

(1) Let us note that when we press 1 from the keypad, this bit pattern 00110001 (0x31 in hex format) is stored in 'character type a'. 00110001 (0x31) is called the ASCII coded value for the digit/numeral 1.

(2) Next time, the same bit pattern 00110001 (0x31) got stored in variable b when we entered 1 from the Keypad.

(3) Now we havee: a = 0x31 and b = 0x31.

(4) To get the result of a + b, we have called the following sub-program:

int sum = Addition (a, b);

int Addition(int a, int b)
{
   int z;
   z = a + b;
   return(z);
}

The sub-program named Addition(int a, int b) has received the values of a (0x31) and b (0x31) and then added them to produce z = a + b = 0x31 + 0x31 = 0x62 which is 98 (6x 16 + 2x1) in decimal, which we have passed to the calling program via variable sum. After that we have executed this instruction: lcd.print(sum, DEC); as a result, 98 has appeared on the LCD. Everything is fine up to now except that we want to see 2 on the LCD.

4. How can we get final result of 2 from the apparent resulat of 0x62 (98 in decimal)?
(1) We must not allow the sub-program (Addition()) to add 0x31 and 0x31; we need to manipulate the received data in such a way so that the addition is done on 0x01 (= a) and 0x01 (=b).

(2) 0x01 for a can be obtained from 0x31 by subtracting 0x30. Thet is to say:

==> newA = 0x31 - 0x30 = 0x01
==> newA = received a - 0x30
==> newA = received a - '0'           //'0' will be coded into 0x01 = 00000001

Similarly,

newB = received b - 0x30
==> newB = 0x31 - 0x30 = 0x01
==> newB = received b - '0'

(3) Finally, the sub-program (Addition()) is to be modified to take the following form:

int Addition(int a, int b)
{
  int z;
  int newA = a - '0'; //0x31 - 0x30 = 0x01
  int newB = b - '0';
  z = newA + newB; //z is now the integer sum
  return (z); 
}

5. The final program (it just works for: 1+ 1 = 2; 2+2=4;, ...) that will yield the expected result is:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <stdio.h> //you must include this library to get the atoi function
#include <stdlib.h>

const byte rows = 4;
const byte cols = 4;

byte rowPins[rows] = {9, 8, 7, 6};
byte colPins[cols] = {5, 4, 3, 2};


char keys[rows][cols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
char a;
char b;
int charCounter = 0;
bool flag1 = false;

void setup()
{
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

}

void loop()
{
  a = myKeypad.getKey();
  if (a != NO_KEY)
  {
    if (flag1 == false)
    {
      lcd.print(a);
      lcd.print("+"); //LCD shows: 1 +
      charCounter++;
      if (charCounter == 1)
      {
        flag1 = true;
      }
    }
    else
    {
      b = a;
      lcd.print(b);
      charCounter++;
      if (charCounter == 2)
      {
        lcd.print("=");
        int sum = Addition(a, b);
        lcd.print(sum, DEC);
        charCounter = 0;
      }
    }
  }
}

int Addition(int a, int b)
{
  int z;
  int newA = a - '0'; //0x31 - 0x30 = 0x01
  int newB = b - '0';
  z = newA + newB; //z is now the integer sum
  return (z); 
}

MGSED46:
I´m sorry. I explained myself wrong. I changed now "z = a*10+b" by "z=a+b" in the existing program I

sent to you in my previous message. This to make it more clear what I want.

If I give in 1+1. That has to be 2 as result. The result I got is 98.

The solution to that is in Reply #1

...R

Thanks Guys.

To sumguy, I filled in what you sent me and it works now.

{
int z=(a+b)-96; // z is now the integer sum
lcd.print( z, DEC); // print the decimal value of z (default is ascii)

}

It is so easy for specialists but for me as a newbie, a nightmare when it want work.
Thanks a lot. I have a lot to learn.

MGSED46:

  int z=(a+b)-96; // z is now the integer sum

That will work but it is not a general solution. It would be better like this

  int z=((a - 48) + (b - 48)); // z is now the integer sum

to signify clearly that each character is being converted to its numerical equivalent.

It could also be written as

  int z=((a - '0') + (b - '0')); // z is now the integer sum

which might make the process of conversion more obvious

...R

Robin2:

  int z=(a+b)-96; // z is now the integer sum

That will work but it is not a general solution. It would be better like this

  int z=((a - 48) + (b - 48)); // z is now the integer sum

to signify clearly that each character is being converted to its numerical equivalent.

It could also be written as

  int z=((a - '0') + (b - '0')); // z is now the integer sum

which might make the process of conversion more obvious

The expressions are equivalent, so all are equal general.
In the third variant the outer braces don't help grouping operands IMHO.

Whandall:
The expressions are equivalent, so all are equal general.

I don't agree. The first style won't work if there are 3 variables.

In the third variant the outer braces don't help grouping operands IMHO.

I can't see a difference between the braces in the 2nd and 3rd examples ? Have I made some mistake?

...R

They are equivalent.

1: (a+b)-96, 2: ((a - 48) + (b - 48))

  ((a - 48) + (b - 48))
= (a - 48) + (b - 48)
= a - 48 + b - 48
= a + b - 48 - 48
= (a + b) - (48 + 48)
= (a + b) - 96

qed.

The second form is a little easier to expand to more digits but who adds values of ASCII digits anyway?

The second and third have that superfluous outer braces, sorry.

Whandall:
They are equivalent.

That's only true if you understand where the magic 96 comes from - you do, and I do, but I would not be so certain that the OP does, or some other newbie reading this Thread.

The second and third have that superfluous outer braces, sorry.

Yes, I was aware of that. I just added them so that the linking of the (a and the 48) would be clear

...R

Robin2:

They are equivalent.

That's only true if you understand where the magic 96 comes from - you do, and I do,
but I would not be so certain that the OP does, or some other newbie reading this Thread.

Equivalence is a mathematical property that does not depend on a special observer, or his knowledge.

Can we settle on - ('0' << 1)?
That's also equivalent.

All the equivalent expressions serve the task equally well.

Some are easier to read, write, understand, maintain and/or whatnot.

Whandall:
Equivalence is a mathematical property that does not depend on a special observer, or his knowledge.

Pedant :slight_smile:

...R

Whandall:
All the equivalent expressions serve the task equally well.

Some develop understanding, or engender good habits.
Others do not.