Keypad sending wrong integers

Arduino Uno. Wiring diagram attached. I am working through a tutorial on using a keypad to make musical notes with a buzzer. The first step ties keys to a specific character (1, 2, 3, ... A, B, C, etc) and then prints the character to the serial terminal. This works just fine, so I know it isn't a wiring or hardware issue.

In the next step, instead of sending characters to the serial terminal it is supposed to send an integer frequency to a buzzer to play. When I implement that code, the serial terminal shows completely wrong values being generated.

#include <Key.h>
#include <Keypad.h>

int buzzer = 10;

const byte ROWS = 4;
const byte COLS = 4;

//Original Code, from the first step, edited out
//char buttons[ROWS][COLS] = {
// {'1', '2', '3', 'A'},
//{'4', '5', '6', 'B'},
//{'7', '8', '9', 'C'},
//{'*', '0', '#', 'D'}
//};

int tones[ROWS][COLS] = {
{31, 93, 147, 208},
{247, 311, 370, 440},
{523, 587, 698, 880},
{1397, 2637, 3729, 4978}
};

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

Keypad customKeypad = Keypad(makeKeymap(tones),rowPins, colPins, ROWS, COLS);

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
int customKey = customKeypad.getKey();

if(customKey) {
Serial.println(customKey);
tone(buzzer, customKey, 1000);
delay(1000);
noTone(buzzer);
}
}

The output I should be getting in the serial terminal (organized by button layout):

31, 93, 147, 208
247, 311, 370, 440
523, 587, 698, 880
1397, 2637, 3729, 4978

The actual output I am getting is:

31, (Nothing), 93, (Nothing)
-109, (Nothing), -48, (Nothing)
-9, (Nothing), 55, 1
114, 1, -72, 1

The getKey() function return a value in char type, which ranges from - 126 to 125. Any value that out of this range will be casted.

IoT_hobbyist:
The getKey() function return a value in char type, which ranges from - 126 to 125. Any value that out of this range will be casted.

Thank you! That solved it.

I’m sure there are better ways to do this, but this was my workaround that worked:

#include <Key.h>
#include <Keypad.h>

int buzzer = 10;
int freq = 31;

const byte ROWS = 4;
const byte COLS = 4;

char tones[ROWS][COLS] = {
{‘1’, ‘2’, ‘3’, ‘4’},
{‘5’, ‘6’, ‘7’, ‘8’},
{‘9’, ‘A’, ‘B’, ‘C’},
{‘D’, ‘E’, ‘F’, ‘G’}
};

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

Keypad customKeypad = Keypad(makeKeymap(tones), rowPins, colPins, ROWS, COLS);

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
char customKey = customKeypad.getKey();

if(customKey) {
Serial.println(customKey);
switch (customKey) {
case ‘1’:
freq = 31;
break;
case ‘2’:
freq = 93;
break;
case ‘3’:
freq = 147;
break;
case ‘4’:
freq = 208;
break;
case ‘5’:
freq = 247;
break;
case ‘6’:
freq = 311;
break;
case ‘7’:
freq = 370;
break;
case ‘8’:
freq = 440;
break;
case ‘9’:
freq = 523;
break;
case ‘A’:
freq = 587;
break;
case ‘B’:
freq = 698;
break;
case ‘C’:
freq = 880;
break;
case ‘D’:
freq = 1397;
break;
case ‘E’:
freq = 2637;
break;
case ‘F’:
freq = 3729;
break;
case ‘G’:
freq = 4978;
break;
default:
freq = 31;
break;
}
tone(buzzer, freq, 1000);
delay(1000);
noTone(buzzer);

}

}

You can use a better way by using array.

The mapping table

int tones_table[] = {
  31, 93, 147, 208, 247, 311, 370, 440,523, 587, 698, 880, 1397, 2637, 3729, 4978
};

Custom keys

int customKeys[ROWS][COLS] = {
  {0, 1, 2, 3},
  {4, 5, 6, 7},
  {8, 9, 10, 11},
  {12, 13, 14, 15}
};

get tone:

char readKey = customKeypad.getKey();
int tone = tones_table[readKey];

@thallios, Please learn to use code tags. You can edit reply #2 and replace quote and /quote by code and /code so it looks like reply #3

IoT_hobbyist:
Custom keys

int customKeys[ROWS][COLS] = {

{0, 1, 2, 3},
 {4, 5, 6, 7},
 {8, 9, 10, 11},
 {12, 13, 14, 15}
};

This is a good idea, but getKey() returns 0 when no key is pressed, causing the first tone to be played.
An easy fix to this, at a cost of 2 bytes, is to index the keys from 1 to 16, and add a dummy integer at the beginning of 'tones_table'.

int tones_table[] = {
  0, 31, 93, 147, 208, 247, 311, 370, 440,523, 587, 698, 880, 1397, 2637, 3729, 4978
};


int customKeys[ROWS][COLS] = {
  {1, 2, 3, 4},
  {5, 6, 7, 8},
  {9, 10, 11, 12},
  {13, 14, 15, 16}
};

Another alternative is to index the keys from 1 to 16, and reference the 'tone_table' with 'readKey - 1'

int tones_table[] = {
 31, 93, 147, 208, 247, 311, 370, 440,523, 587, 698, 880, 1397, 2637, 3729, 4978
};

int customKeys[ROWS][COLS] = {
  {1, 2, 3, 4},
  {5, 6, 7, 8},
  {9, 10, 11, 12},
  {13, 14, 15, 16}
};

:
:

char readKey = customKeypad.getKey();
int tone = tones_table[readKey - 1];

IoT_hobbyist:
The getKey() function return a value in char type, which ranges from - 126 to 125. Any value that out of this range will be casted.

sp. “-128 to 127”

TheMemberFormerlyKnownAsAWOL:
sp. "-128 to 127"

Oh, I made the mistake. I am getting older :confused: