This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

reading hex keypad input

Other Parts Discussed in Thread: MSP430F2274

Hello,

I am working with a msp430f2274 and I am doing an exercise with a hex keypad. I have the outputs working just fine, but I am having difficulty reading the input signals. The way I figured is that the best way to do this is by scanning the ADC values of each pin. (P3, P4, P5) I believe my main issue is not knowing how to trigger the sampling for each individual input pin, and I don't know if I need a slight delay in order to reset the ADC. I have constructed a sample code to demonstrate what I am trying to do for sampling. 

#include "msp430f2274.h"
int main(void)
{
//Initialize ADC & WDT
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
ADC10AE0 |= 0x07; // P2.2,1,0 ADC10 option select
P1DIR |= 0x01; // Set P1.0 to output direction
//End of Initialization
//Start sampling loop
for (;;)
{
//Sample P3
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start P3
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
if (ADC10MEM < 0x238)
//do something
//Sample P4
//Command for sample for P4?
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
if (ADC10MEM < 0x238)
// Do something
//Sample P5
//Command to sample start for P5?
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
if (ADC10MEM < 0x238)
//do something
}
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}

  • What is kind of hex keypad are you using? Are there analog signals?

    What is P5?

  • Isaac Puckett said:

    I am working with a msp430f2274 and I am doing an exercise with a hex keypad. I have the outputs working just fine, but I am having difficulty reading the input signals. The way I figured is that the best way to do this is by scanning the ADC values of each pin. (P3, P4, P5) I believe my main issue is not knowing how to trigger the sampling for each individual input pin, and I don't know if I need a slight delay in order to reset the ADC. I have constructed a sample code to demonstrate what I am trying to do for sampling. 

    Here is my keyboard for MSP430G2xx...

    When signal on IRK (ADC) pin goes to logic zero, ADC is turned on, and start collecting samples. After 100 samples is collected, they are sorted, and average value of 8 mid samples is calculated. Depending on avg calculated value pressed key is decoded.

  • Interesting. Is it hex or hexa?

    Can R1..R6 all use the same value ? (e.g., all 2.2k) Or, do they need to have different values ? (Smaller for R1 and progressively higher toward R6.)

  • old_cow_yellow said:

    Can R1..R6 all use the same value ? (e.g., all 2.2k) Or, do they need to have different values ? (Smaller for R1 and progressively higher toward R6.)

    Only "logic zero" interval is used, half of ADC resolution. In ADC resistor array is is included TSOP (close to) 30k internal resistor. I suggested resistor values, but it up to end user, because there is learn key function, and target device is able to recalibrate keyboard anytime.

    R1 1322 1023 * 1322 / 31322 = 43
    R2 2483 1023 * 3805 / 33805 = 115
    R3 2911 1023 * 6716 / 36716 = 187
    R4 3459 1023 * 10175 / 40175 = 259
    R5 4179 1023 * 14354 / 44354 = 331
    R6 5148 1023 * 19502 / 49502 = 403

  • zrno soli said:
    ...

    R1 1322 1023 * 1322 / 31322 = 43
    R2 2483 1023 * 3805 / 33805 = 115
    R3 2911 1023 * 6716 / 36716 = 187
    R4 3459 1023 * 10175 / 40175 = 259
    R5 4179 1023 * 14354 / 44354 = 331
    R6 5148 1023 * 19502 / 49502 = 403

    ...

    This is incorrect.

    When PB2 is pressed, R=R1+R2. When PB3 is pressed, R=R1+R2+R3. etc.

    Also,you could use 1.5V Ref.

  • old_cow_yellow said:

    This is incorrect.

    When PB2 is pressed, R=R1+R2. When PB3 is pressed, R=R1+R2+R3. etc.

    Also,you could use 1.5V Ref.

    When PB2 is pressed, R = R1 + R2 = 1322 + 2483 = 3805, ADC value 1023 * 3805 / 33805 = 115

    When PB3 is pressed, R = R1 + R2 + R3 = 1322 + 2483 + 2911 = 6716, ADC value 1023 * 6716 / 36716 = 187

    ...

    As ref is used VCC/VSS because target device voltage is not fixed, it is selected (2.5V - 3.3V) by end user. And want to keep same ADC values, not depending on selected VCC.

  • This is a schematic of my keypad I am using: hex_keypad_schematic.jpg

    Simply, the rows are controlled by and output from my msp and I scan the columns for a high at the same time. I know how to do a output sweep, but my issue is that I am not sure on how to do an adc sweep of the inputs to see which button is pressed. I've provided a bare bones code above in my first post. For the ADC sweep I know how to initiialize ADC on P3-P6, but I am having issues doing the physical sweep. Any hints?

  • I don't think my keypad schematic was linked properly. This should be better:

  • That is better. I think you actually do not need those resistors and the value of 4.7k is too low. You could have enabled the internal pull-up/pull-down resistors. But it will work as is too.

    You do not need to use the ADC at all. What you do is you do an outer loop of 4 columns and an inner loop of 4 rows. (Or the other way around.) You drive one row high at a time and read one column at a time. When the reading is high, the row you are driving high and the column you are reading high singles out the key that is depressed.

  • zrno soli,

    You are right. My mistake.

    -- OCY

  • Sorry for the delay,

    There seems to be some internal resistance that drops the voltage to around 3.3V. Since the Voltage reference is 3.6, will the msp still read the pin as a high input?

    -Thanks

  • I made this sample code to read a 3X3 hex keypad. Unless my code is wrong, my assumptions were right that the 0.3V drop makes it impossible to read the input by seeing if the pin is high or not. Should I use a ADC sweep? or is there an easier way?


  • #include "msp430f2274.h"

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    P1DIR |= 0x01; // Set P1.0 to output direction
    P2DIR |= 0x03; // P1-3 is output

    for (;;)
    {
    //First Column
    P2OUT=BIT0;
    if(P2IN & BIT2) //PIN P2.4 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT0) //Pin P2.5 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT3) //P2.6 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;
    //Second Column
    P2OUT=Bit1;
    if(P2IN & BIT2) //PIN P2.4 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT0) //Pin P2.5 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT3) //P2.6 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;
    //Third Column
    P2OUT=Bit0+Bit1;
    if(P2IN & BIT2) //PIN P2.4 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT0) //Pin P2.5 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;

    if(P2IN & BIT2&BIT3) //P2.6 is high
    P1OUT = 0x01;
    else
    P1OUT = 0x00;
    }
    }

  • According to your schematics of the key pad, the "columns" all have a 4.7k pull-down resistors (while the "rows" do not).

    Are P2.1, 2, and 3 used as "columns" and each has a pull-down resistor?

    And are P2.4, 5, and 6 used as "rows" with no resistor?

    Is P1.0 use as output to indicate that one of the 9 keys is pressed? No matter which one?

  • There is some internal resistance in the hex keypad that was not shown on the schematic. The LED is P1.0 just to show functionality. 


  • Your need not draw much current through the switches, even ~100 ohms of internal resistance is okay.

    My question is, are P2.1, 2, and 3 used as "columns" each with a 4.7k pull-down resister?

    Are P2.4, 5, and 6 used as "rows" without any pull-down?

  • No, I only implemented the pull down resisters to complete the circuit for the columns. I also tried doing without them as you suggested earlier.

  • It appears the problem must be with my code. When I tie the Vdd Pin to my inputs the LED doesn't turn on.

  • You only need pull-down resistors for either all the columns or all the rows. Never both columns and rows.

    My suggestions was to use internal pull-down resistors for either all the columns or all the rows. In that case you do not need the external 4.7k resistors, but you do need tO tell the MSP430 to enable the internal pull-down.

    Since you already have the external 4.7k on the columns, let it stay that way. But you are not handling P2 correctly. You need to change all the lines your code that involves P2.

    In the initial setup. You should have:

    P2SEL = 0;

    P2DIR = BIT4 | BIT5 | BIT6;

    Inside the loop, you should drive First Row, not First Column, with:

    P2OUT = BIT4;

    And later, Second Row:

    P2OUT = BIT5;

    And still later, Third Row:

    P2OUT = BIT6;

    In each of the above case, you read the Column one at a time:

    if (P2IN & BIT1) ....
    if (P2IN & BIT2) ....
    if (P2IN & BIT3) ....

  • Yep this did it even with the slight voltage drop. Thanks for your help!

**Attention** This is a public forum