Adafruit 5x6 ortho neokeypad and talkie

My students and I am having a strange problem with this code. We are using the 5x6 ortho neokey keypad with the Talkie library. This keyboard is being used as a Braille Teaching device. My students added Braille keycaps and they want to have 2 modes. The teach Mode is where the speaker will say the name of the letter out loud after a button is pressed. The game Mode is where a letter is randomly pressed and it says "Good Work" if the correct button is pressed and "Try Again" if not pressed within 10 seconds.

The problem is that in teach mode, when you press any button in the 4th row, it says all the letters in that row, one after the other. When I try the sample code in the Adafruit Keypad library, it behaves perfectly. Can you see something wrong in this code? I am at a loss as to what is going on.

Could this be the Talkie library not playing nice with the keypad code? It seems to behave erratically and unpredictably.

Thanks.

#include "Adafruit_Keypad.h"
#include "Talkie.h"
#include "Vocab_US_Large.h"
#include "Vocab_Special.h"
#include "Vocab_US_TI99.h"
#include "Vocab_US_Clock.h"
#include "Vocab_Soundbites.h"
#include "Vocab_US_Acorn.h"

#define ROWS 5  // rows
#define COLS 6  // columns

long startTime = 0;
boolean nameIt = true;


//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
  { 'A', 'B', 'C', 'D', 'E', 'F' },
  { 'G', 'H', 'I', 'J', 'K', 'L' },
  { 'M', 'N', 'O', 'P', 'Q', 'R' },
  { 'S', 'T', 'U', 'V', 'W', 'X' },
  { 'Y', 'Z', ' ', ' ', ' ', ' ' }
};

uint8_t rowPins[ROWS] = { 8, 9, 10, 11, 12 };   //connect to the row pinouts of the keypad
uint8_t colPins[COLS] = { 7, 6, 5, 4, 13, 2 };  //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

Talkie voice;
char letterKey;
int switchPin = A0;
int letterpicked;

void setup() {
  Serial.begin(9600);
  //while (!Serial);
  Serial.println("Ortho 5x6 keypad demo");

  customKeypad.begin();
  randomSeed(analogRead(5));
  letterpicked = random(0, 27);
}

void loop() {

  if (analogRead(switchPin) > 500) {
    Serial.println("teach mode");
    teachMode();
  } else {
    Serial.println("game mode");
    gameMode();
  }
}

void teachMode() {
  customKeypad.tick();

  while (customKeypad.available()) {
    keypadEvent e = customKeypad.read();
    Serial.print((char)e.bit.KEY);
    if (e.bit.EVENT == KEY_JUST_PRESSED) {
      Serial.println(" pressed");
      uint8_t row = e.bit.ROW;
      uint8_t col = e.bit.COL;
      Serial.print("Row: ");
      Serial.print(row);
      Serial.print(" col: ");
      Serial.print(col);
      Serial.print(" -> ");
      uint16_t keynum;
      Serial.println(keynum);
      sayLetter((char)e.bit.KEY);
    }
    //else if (e.bit.EVENT == KEY_JUST_RELEASED) {
    //  Serial.println(" released");
    // }
  }
  delay(100);
}
void sayLetter(char letter) {
  switch (letter) {
    case 'A':
      voice.say(sp2_A);
      break;

    case 'B':
      voice.say(sp2_B);
      break;

    case 'C':
      voice.say(sp2_C);
      break;

    case 'D':
      voice.say(sp2_D);
      break;

    case 'E':
      voice.say(sp2_E);
      break;

    case 'F':
      voice.say(sp2_F);
      break;

    case 'G':
      voice.say(sp2_G);
      break;

    case 'H':
      voice.say(sp2_H);
      break;

    case 'I':
      voice.say(sp2_I);
      break;

    case 'J':
      voice.say(sp2_J);
      break;

    case 'K':
      voice.say(sp2_K);
      break;

    case 'L':
      voice.say(sp2_L);
      break;

    case 'M':
      voice.say(sp2_M);
      break;

    case 'N':
      voice.say(sp2_N);
      break;

    case 'O':
      voice.say(sp2_O);
      break;

    case 'P':
      voice.say(sp2_P);
      break;

    case 'Q':
      voice.say(sp2_Q);
      break;

    case 'R':
      voice.say(sp2_R);
      break;

    case 'S':
      voice.say(sp2_S);
      break;

    case 'T':
      voice.say(sp2_T);
      break;

    case 'U':
      voice.say(sp2_U);
      break;

    case 'V':
      voice.say(sp2_V);
      break;

    case 'W':
      voice.say(sp2_W);
      break;

    case 'X':
      voice.say(sp2_X);
      break;

    case 'Y':
      voice.say(sp2_Y);
      break;

    case 'Z':
      voice.say(sp2_Z);
      break;
  }

  delay(1000);
}

void gameMode() {

  Serial.print(letterpicked);
  Serial.println("    ");

  if (millis() - startTime < 10000) {
    while (nameIt) {
      switch (letterpicked) {
        case 0:
          voice.say(sp2_A);
          letterKey = 'A';
          Serial.println("letter chosen = A");
          break;
        case 1:
          voice.say(sp2_B);
          letterKey = 'B';
          Serial.println("letter chosen = B");
          break;
        case 2:
          voice.say(sp2_C);
          letterKey = 'C';
          Serial.println("letter chosen = C");
          break;
        case 3:
          voice.say(sp2_D);
          letterKey = 'D';
          Serial.println("letter chosen = D");
          break;
        case 4:
          voice.say(sp2_E);
          letterKey = 'E';
          Serial.println("letter chosen = E");
          break;
        case 5:
          voice.say(sp2_F);
          letterKey = 'F';
          Serial.println("letter chosen = F");
          break;
        case 6:
          voice.say(sp2_G);
          letterKey = 'G';
          Serial.println("letter chosen = G");
          break;
        case 7:
          voice.say(sp2_H);
          letterKey = 'H';
          Serial.println("letter chosen = H");
          break;
        case 8:
          voice.say(sp2_I);
          letterKey = 'I';
          Serial.println("letter chosen = I");
          break;
        case 9:
          voice.say(sp2_J);
          letterKey = 'J';
          Serial.println("letter chosen = J");
          break;
        case 10:
          voice.say(sp2_K);
          letterKey = 'K';
          Serial.println("letter chosen = K");
          break;
        case 11:
          voice.say(sp2_L);
          letterKey = 'L';
          Serial.println("letter chosen = L");
          break;
        case 12:
          voice.say(sp2_M);
          letterKey = 'M';
          Serial.println("letter chosen = M");
          break;
        case 13:
          voice.say(sp2_N);
          letterKey = 'N';
          Serial.println("letter chosen = N");
          break;
        case 14:
          voice.say(sp2_O);
          letterKey = 'O';
          Serial.println("letter chosen = O");
          break;
        case 15:
          voice.say(sp2_P);
          letterKey = 'P';
          Serial.println("letter chosen = P");
          break;
        case 16:
          voice.say(sp2_Q);
          letterKey = 'Q';
          Serial.println("letter chosen = Q");
          break;
        case 17:
          voice.say(sp2_R);
          letterKey = 'R';
          Serial.println("letter chosen = R");
          break;
        case 18:
          voice.say(sp2_S);
          letterKey = 'S';
          Serial.println("letter chosen = S");
          break;
        case 19:
          voice.say(sp2_T);
          letterKey = 'T';
          Serial.println("letter chosen = T");
          break;
        case 20:
          voice.say(sp2_U);
          letterKey = 'U';
          Serial.println("letter chosen = U");
          break;
        case 21:
          voice.say(sp2_V);
          letterKey = 'V';
          Serial.println("letter chosen = V");
          break;
        case 22:
          voice.say(sp2_W);
          letterKey = 'W';
          Serial.println("letter chosen = W");
          break;
        case 23:
          voice.say(sp2_X);
          letterKey = 'X';
          Serial.println("letter chosen = X");
          break;
        case 24:
          voice.say(sp2_Y);
          letterKey = 'Y';
          Serial.println("letter chosen = Y");
          break;
        case 25:
          voice.say(sp2_Z);
          letterKey = 'Z';
          Serial.println("letter chosen = Z");
          break;
      }
      nameIt = false;
    } 
  } else {
    voice.say(spt_TRY_AGAIN);
    letterpicked = random(0, 27);
    startTime = millis();
    nameIt = true;
  }
  getKeyStroke();
  delay(1000);
}


void getKeyStroke() {

  customKeypad.tick();

  while ((customKeypad.available()) && (digitalRead(switchPin <= 500))) {
    Serial.print("letter typed= ");
    keypadEvent e = customKeypad.read();
    Serial.println((char)e.bit.KEY);

    if ((letterKey) == (char)e.bit.KEY) {
      voice.say(spt_GOOD_WORK);
      Serial.println("good work");
      letterpicked = random(0, 27);
      nameIt = true;
    }
  }
  delay(1000);
}

A link to the datasheet of the keypad and schematics showing how it's wired would surely make more helpers interested.

It certainly does seem like a wiring issue. The code looks plausible, and nothing jumps out to account for one bad row or column or button.

I did see a 13 in the pin list which awfully looks like it wants to be 3, but it doesn't look to be involved with the faulty buttons. Check both that you are telling us about the right row or column and that you are def using pin 13.

Pin 13 on at least the UNO has some circuitry already attach, so it can be a bad (or unfortunate) choice for certain other uses.

Since matrix scanning exploits all the features of an i/o pin, you might in any case want to move off that pin.

I leave pin 13 for almost the last pins to use. Pins 0 and 1 are for when you've really run out of pins and have no other options that you like.

13, no not superstitious at all.

a7

I used pin 13 because we needed to use pin 3 for the Talkie library to work. I did a little research and found that the Talkie library uses both timers 1 and 2 and I know that pins 3 and 11 are used for timer 2 on the Arduino Uno which we are using. All other pins are being used. I can send a picture of the wiring and the schematic of the keypad. When I switched to the regular keypad.h library and not the Adafruit keypad library, This sounds suspiciously like it is a timer issue and I don't know if it can be resolved. I need the keypad to register a key stroke and then afterwards, I need the Talkie library to speak the key stroke out loud.

Is there a way that both can be using the same timers, but at different times? Like shut it off for Talkie while Keypad uses the timer? I really don't understand timers very well....



So, I decide to try something - I moved the wire from pin 13 to A5 and it works beautifully now. Something squirrelly about pin 13 I guess.....

Someone mentioned that.

And I was just about to ask, or point out, that you are not using all the pins.

The so-called analog pins A0..A5 also function when used as digital pins. In fact this

analogRead(switchPin) > 500

use of analogRead() made me think you might not know. Use

    digitalRead(switchPin) == HIGH

the pin mode is INPUT at reset, depending on what you have wired to A0, that seems to work now.

What is the circuit on A0?

Just now checking for A0 switchPin, I see

digitalRead(switchPin <= 500)

Which is nonsense. The PIN number expression evaluates to false, or zero, so you are reading pin 0, used for the serial monitor and uploading you sketch.

Probably not what you want. I'm not sure why your code is working.

a7

A switch is connected to A0 to switch between game mode and teach mode. It will either have a voltage of 5v or 0v. So that’s why I write the code I did ti see if it reads above or below 500. Is there a better way?

I found this information. Is this what I should do with the switch pin?

I see a problem with pin A0. I need to check the wiring. It looks like it might be connected to the keypad which is for the neopixels that are not being used but the code says it’s for the switch. I will check on it tomorrow. Thanks for pointing it out.

A switch has two terminals.

In you case, one of them is connected to A0. What is the other terminal connected to?

Do you have any components other than that switch wired in any way to pin A0?

Pin A0 can be used as a digital input or output pin, in exactly the same way as pins 2, 3 and so forth. Just use them the same way.

Set a pin mode, use digital read or write.

I'm on the tiny window, so IDK what your picture says. Don't worry about it, just treat A0..A5 like they are digital,pins, because they are. Also. In addition to being analog capable.

It was stupid for someone at some point to call then]m analog pins.

Did you understand my point about the odd digitalRead() in you code? And address whatever the implications of that might be?

a7

Yes, I found the digitalRead(switchPin) and corrected it to analogRead(switchPin) - my mistake.
I have been teaching Arduino for 10 years and always thought that analog pins were analog input pins only. This is the first time I ever heard that they can be used as digital pins....Learn something new every day, I guess.

The switch has one end connected to ground and the other to a resistor connected to 5V and also to A5 - creating a pull-down resistor.

Words. What I make of that is that you have a pull up resistor, wired between the pin and Vcc (5V). Or you have an unusual switch circuit.

If one of these is what you have, say which. It it isn't, draw it, even like I did with my finger:

Words. It's hard to tell if you mean your mistake was using analogRead() and you fixed it so you are using digitalRead() as you should, or fixed it so you use analogRead() in both places.

I like to learn something every day, too. Don't take my word for this idea that analog pins (most analog pins, but def A0..A5) on an UNO, can be used for all digital purposes.

And you should do if your input or output is digital (on / off, pressed / not pressed) nature.

There are circumstances where using analog input to derive a digital condition in the code is necessary, if this is the case for you pleas say why.

a7

I meant that I moved it to be analogRead in both places because I had a greater than 500 but then I tried it your way using digitalRead instead, and it only works when I have digitalRead == LOW rather than HIGH for some reason. No big deal but the code is working and I’m happy and I thank you for your help.

The wiring is like the picture you drew on the right with the pulldown resistor. I may have described it incorrectly in my reply .

You didn't comment on this expression, and I remain confused about the switch:

digitalRead(switchPin <= 500)

It kinda is a big deal, these are questions that can should be answered, not left to a shrug of the shoulders.

Also confirm that your pushbuttons are normally open, that is to say the contacts conduct electricity only when you press the button.

There are normally closed switches, but this is not common.

Post your final version of the code, it might help explain all this. And if you do, I'll share something about which you might be able to say "I learned something today".

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.