Algunas columnas del keypad dejan de funcionar.

Hola a todos

Estoy trabajando en un proyecto en un Arduino Mega que es, básicamente, tomar un número del teclado, mostrarlo en un LCD, y convertirlo a una palabra de 14 bits para enviarlos a 14 pines digitales.

En el inicio todo funciona ok, pero cuando ejecuta la función de conversión a 14 bit y envío a puerto digital, las columnas 2 y, algunas veces, 1 dejan de funcionar.

He medido los valores del teclado: C1 y C2->5v; C3 y C4->0.5v; F1 a F4->5v. El código es:

// include the libraries code:
#include <LiquidCrystal.h>
#include <Keypad.h>

//constants defining:
const float LSB = 0.0219726562;  //Este es el valor decimal equivalente a un grado binario para un una
                                                  //palabra de 14 bits: LSB = (2^-(n-1)) * 180deg ;en nuestro caso n=14bit.

int BAM_bit[] = {49, 47,  45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23};

//Inicialización del keypad
const byte ROWS = 4;          //four rows
const byte COLS = 4;          //four columns
char keys[ROWS][COLS] = {    //valores tomados por cada una de las teclas
  {'1', '2', '3', 'F'},
  {'4', '5', '6', 'E'},
  {'7', '8', '9', 'D'},
  {'A', '0', 'B', 'C'}
};
byte rowPins[ROWS] = {17, 16, 15, 14}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {21, 20, 19, 18}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

//Inicialización del display
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); //Inicializa pins para LCD(rs, enable, D4, D5, D6, D7)


void setup()
{
  for (int count = 14; count > 0; count--)
  {
    pinMode(BAM_bit[count], OUTPUT);
  }
  Serial.begin(9600);
  lcd.begin(20, 4);            // set up the LCD's number of columns and rows (cols, rows)
  menu();
}

int i = 0;

void loop()
{
  char key = keypad.getKey();     //Espera entrada de teclado para entrar en un modo de trabajo
  if (key != NO_KEY)
  {
    switch (key)
    {
      case 'F':   
        while (keypad.getKey() != 'C')
        {
          lcd.clear();
          lcd.setCursor(4, 0); lcd.write("MODO MANUAL");
          lcd.setCursor(1, 1); lcd.write("Introduzca angulo:");
          int manualDegree = takeNum(8, 2);
          if (manualDegree == 9854)break;
          conversion(manualDegree);
        }
        menu();
        break;

      case 'E':     
        {
          lcd.clear();
          lcd.setCursor(2, 0);
          lcd.write("MODO AUTOMATICO");
          lcd.setCursor(5, 1);
          lcd.write("Introduzca");
          lcd.setCursor(0, 2);
          lcd.write("velocidad(grad/seg):");
          int vel = takeNum(8, 3);              //Velocidad angular en grados/segundo
          if (vel == 9854)break;                //Sale del caso si se ha presionado Menu('C')
          float delayDeg = 1.0 / vel;          //Calcula segundos por cada grado:
          float deg = 0;                            // 1 / (x grad/seg) = x seg/grado
          lcd.clear();
          while (true)
          {
            if (keypad.getKey() == 'C')     //Si se pulsa Menu ('C') se sale a menu
            {
              menu();
              break;
            }
            conversion(deg);
            lcd.setCursor(2, 0);
            lcd.write("MODO AUTOMATICO");
            lcd.setCursor(0, 2);
            lcd.write("Velocidad(deg/s):"); lcd.print(vel);
            lcd.setCursor(0, 3); lcd.write("Posicion: "); lcd.print(int(deg)); lcd.write(" deg.");
            if (deg > 359)
            {
              deg = 0;
              lcd.clear();
            }
            deg ++;
            delay(1000 * delayDeg);       //Espera el tiempo (en ms) dado por la velocidad
          }
          break;
        }

      case 'C':
        menu();
        break;
      default:
        lcd.clear();
        lcd.setCursor(2, 0);
        lcd.write("Introduzca modo");
        lcd.setCursor(2, 2);
        lcd.write("valido:D, E o F");
        delay(1500);
        menu();
    }
  }
}


/**********************************FUNCIONES**********************************/



/*Esta función presenta el menú de inicio en el LCD*/

void menu(void)
{
  lcd.clear();
  lcd.setCursor(8, 0);
  lcd.write("MENU");
  lcd.setCursor(0, 1);
  lcd.write("F: MODO MANUAL");
  lcd.setCursor(0, 2);
  lcd.write("E: MODO AUTOMATICO");
  lcd.setCursor(0, 3);
  lcd.write("D: MODO PROGRAMADO");
}


/*Esta función queda en espera de recibir entrada de teclado para almacenarla, devolviendo el valor
  introducido como un entero. Mostrará en pantalla los dígitos introducidos a partir de la posición
  dadda en PosX y PosY.*/

int takeNum(int PosX, int PosY)
{
  lcd.setCursor(PosX, PosY);
  lcd.cursor(); lcd.blink();
  int i = 0;
  while (true)
  {
    char kpress = keypad.waitForKey();    //Espera que se introduzca el dato y lo almacena en kpress
    if (kpress != 'A' && kpress != 'D' && kpress != 'E' && kpress != 'F')
    {
      if (kpress == 'B')break;
      else if (kpress == 'C')
      {
        i = 9854;
        menu();
        break;
      }
      else
      {
        lcd.write(kpress);
        kpress -= '0';                        //convierte el caracter ASCII 'kpress' en entero ('1'=1)
        int x = (int)kpress;                  //asigna a 'x' el valor de kpress como entero
        i = (10 * i) + x;
      }
    }
  }
  lcd.noCursor(); lcd.noBlink();
  return i;
}


/*  Esta función recoge un número decimal, lo comvierte a BAM y envía el dato a las salidas
     digitales bitBAM01 a bitBAM14 */

void conversion(int degree)
{
  int BAM_degree = degree / LSB;
  int mask = 0x2000;
  for (int count = 14; count > 0; count--)
  {
    BAM_bit[count] = (BAM_degree & mask) >> count - 1;/*
    Serial.print("BAM: "); Serial.print(BAM_degree);
    Serial.print(" - Grados: "); Serial.print(degree);
    Serial.print(" - Bit "); Serial.print(count); Serial.print(": "); Serial.println(BAM_bit[count]);
    Serial.print(BAM_degree, BIN); Serial.print("&"); Serial.print(mask, BIN); Serial.print("="); Serial.println(BAM_bit[count], BIN);*/
    mask = mask >> 1;
  }
  return ;
}

¿Podría alguien ayudarme? Esto me está volviendo loco. Muchas gracias por adelantado.

Pregunto: como tienes cableado el teclado al Arduino Mega?

Está conectado: fila 1 a fila 4=> 17, 16, 15, 14; columna 1 a 4 => 21, 20, 19, 18; sin pull-up o pull-down. También he probado a cambiarlos a los pines 50 al 44, pero me seguía pasando lo mismo.

Este es tu problema!!
mala asignación de un vector, mira este link

int myArray[10]={9,3,2,4,3,2,7,8,9,11};
     // myArray[9]    contains 11
     // myArray[10]   is invalid and contains random information (other memory address)

En tu caso

// defines BAM_bit con 14 elementos
int BAM_bit[] = {49, 47,  45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23};

// y luego en el loop pretenden empezar po la posición 14 que no existe
// debes empezar en 13
for (int count = 14; count > 0; count--)  {

y tampoco llegas al item 0, porque count>0 implica que el último elemento será 1.

Lo correcto sería esto

for (int count = 13; count >= 0; count--)  {

Después de tantos años sin programar veo que vuelvo a ser un novato.... :-[

Exacto surbyte, ese era el problema. Está solucionado. Me estaba volviendo loco dando vueltas al keypad.

Muchas gracias surbyte.