Keypad on Rpi using Pi4J


11 posts
by bdjantl » Thu Mar 28, 2013 1:45 pm
I am trying to connect a keypad to the GPIO ports of my Rpi using the Java Pi4J library. It works as follows: two pins on my keypad feed the keypad with power (3.3V). Six other pins are used to find out which key was pressed on the keypad. The 'power' pins are configured as output on my Rpi, the other pins are configured as input.
However: this can only be determined knowing which of the input pins on the keypad was in the high state = providing the power.
Using the two input pins and the six output pins (of the keypad) I am able to know which of the 12 keys was pressed. For instance power on pin 1 and output on pin 5 means key 7 is pressed, whereas power on pin 2 and output on pin means for instance key 4 is pressed.
My problem is that I can not 'see' which of the input pins provided the power. Is there a way to detect on a GPIO output port if there flows a current?
Or is there any other solution to accomplish this?
-- Jan
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm
by savageautomate » Sun Mar 31, 2013 8:40 pm
(I have not programmed or wired a keypad before, so I may be speaking from a bit of a disadvantage here...)

Since the Pi's GPIO pins are only digital pins, I don't think you can know which (of the two) power (output) pin is sourcing which input pins. That is ... unless you implement some sort of timed switching technique where your code knows which output pin is ON and which is OFF at a given moment in time and then alternating the states of the two output pins in rapid succession. This may be a bit tricky to work out but may work for your needs.

-Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com
User avatar
Posts: 187
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
by bdjantl » Mon Apr 01, 2013 5:00 pm
Thanks Robert for your reply.

I found a python example here: http://www.raspberrypi.org/phpBB3/viewtopic.php?f=42&t=36723&p=308604&hilit=keypad#p308604 which gives me - with some modifications for my used GPIO pins (2 out and 6 in) - the correct results.
I have rewritten this in Java using the Pi4J library. However I can't get this to work using the Pi4J library. Any help is highly appreciated!

Code: Select all
import java.util.HashMap;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class KeypadTest2
{

   /** The Constant PINMAPPING. */
   private static final HashMap<String, Integer> PINMAPPING = new HashMap<String, Integer>();

   /** The gpio. */
   private final GpioController theGpio = GpioFactory.getInstance();
   
   /** The Constant PIN_1_OUT. */
   private static final Pin PIN_1_OUT = RaspiPin.GPIO_15;
   
   /** The Constant PIN_3_OUT. */
   private static final Pin PIN_3_OUT = RaspiPin.GPIO_16;
   
   /** The Constant PIN_4_IN. */
   private static final Pin PIN_4_IN = RaspiPin.GPIO_01;
   
   /** The Constant PIN_5_IN. */
   private static final Pin PIN_5_IN = RaspiPin.GPIO_04;
   
   /** The Constant PIN_6_IN. */
   private static final Pin PIN_6_IN = RaspiPin.GPIO_05;
   
   /** The Constant PIN_7_IN. */
   private static final Pin PIN_7_IN = RaspiPin.GPIO_06;
   
   /** The Constant PIN_8_IN. */
   private static final Pin PIN_8_IN = RaspiPin.GPIO_10;
   
   /** The Constant PIN_9_IN. */
   private static final Pin PIN_9_IN = RaspiPin.GPIO_11;

   /** The pin1. */
   private GpioPinDigitalOutput thePin1 = theGpio.provisionDigitalOutputPin(PIN_1_OUT, PinState.LOW);
   
   /** The pin3. */
   private GpioPinDigitalOutput thePin3 = theGpio.provisionDigitalOutputPin(PIN_3_OUT, PinState.LOW);
   
   /** The pin4. */
   private GpioPinDigitalInput thePin4 = theGpio.provisionDigitalInputPin(PIN_4_IN, PinPullResistance.PULL_UP);
   
   /** The pin5. */
   private GpioPinDigitalInput thePin5 = theGpio.provisionDigitalInputPin(PIN_5_IN, PinPullResistance.PULL_UP);
   
   /** The pin6. */
   private GpioPinDigitalInput thePin6 = theGpio.provisionDigitalInputPin(PIN_6_IN, PinPullResistance.PULL_UP);
   
   /** The pin7. */
   private GpioPinDigitalInput thePin7 = theGpio.provisionDigitalInputPin(PIN_7_IN, PinPullResistance.PULL_UP);
   
   /** The pin8. */
   private GpioPinDigitalInput thePin8 = theGpio.provisionDigitalInputPin(PIN_8_IN, PinPullResistance.PULL_UP);
   
   /** The pin9. */
   private GpioPinDigitalInput thePin9 = theGpio.provisionDigitalInputPin(PIN_9_IN, PinPullResistance.PULL_UP);
   
   private GpioPinDigitalOutput theOutputs[] = { thePin1, thePin3 };
   private GpioPinDigitalInput theInputs[] = { thePin4, thePin5, thePin6, thePin7, thePin8, thePin9 };
   
   /** The first pin. */
   private int theFirstPin = 0;
   
   /** The second pin. */
   private int theSecondPin = 0;

   /**
    * @param args
    */
   public static void main(String[] args)
   {
      KeypadTest2 myKT = new KeypadTest2();
      
      myKT.initMapping();
      
      myKT.eventLoop();
   }

   /**
    * Event loop.
    */
   private void eventLoop()
   {
      while (true)
      {
         // Just stay inside the loop, but do not consume all CPU
         try
         {
            boolean myKeyPress = false;
            GpioPinDigitalInput myInput = null;
            int myInId = -1;
            
            // all outputs low
            for (int myO = 0; myO < theOutputs.length; myO++)
            {
               theOutputs[myO].low();
            }
                        
            while (!myKeyPress)
            {
               // waiting for input
               for (int myI = 0; myI < theInputs.length; myI++)
               {
                  if (theInputs[myI].isLow())
                  {
                     myInId = myI + 4;
                     myInput = theInputs[myI];
                     myKeyPress = true;
                     System.out.print("In = " + myInId);
                     break;
                  }
               }
               
               Thread.sleep(100);
            }
            
            // now test the inputs by setting the outputs from high to low one by one
            for (int myO = 0; myO < theOutputs.length; myO++)
            {
               for (int myO2 = 0; myO2 < theOutputs.length; myO2++)
               {
                  theOutputs[myO2].high();
               }

               theOutputs[myO].low();
               
               // input found?
               if (myInput.isLow())
               {
                  System.out.println("Out = " + myO);
                  
                  theSecondPin = myInId;
                  
                  if (myO == 0)
                  {
                     theFirstPin = 1;
                  }
                  else
                  {
                     theFirstPin = 3;
                  }
                  
                  checkPins();
                  break;
               }
            }
         }
         catch (InterruptedException myIE)
         {
            myIE.printStackTrace(System.err);
         }
      }
   }
   
   /**
    * Maps a pin combination on a keypad entry.
    */
   private void initMapping()
   {
      PINMAPPING.put("35", (int) '1');
      PINMAPPING.put("36", (int) '2');
      PINMAPPING.put("37", (int) '3');
      PINMAPPING.put("38", (int) '4');
      PINMAPPING.put("39", (int) '5');
      PINMAPPING.put("14", (int) '6');
      PINMAPPING.put("15", (int) '7');
      PINMAPPING.put("16", (int) '8');
      PINMAPPING.put("17", (int) '9');
      PINMAPPING.put("18", (int) '*');
      PINMAPPING.put("34", (int) '0');
      PINMAPPING.put("19", (int) '#');
   }
   
   private void checkPins()
   {
      System.out.println("Pin states = " + theFirstPin + " - " + theSecondPin);
      
      if (theFirstPin != 0 && theSecondPin != 0)
      {
         int myInput = PINMAPPING.get("" + theFirstPin + theSecondPin);
         
         System.out.println("Input read = " + (char) myInput);
         
         theFirstPin = 0;
         theSecondPin = 0;
      }
   }
}


-Jan
Last edited by bdjantl on Mon Apr 01, 2013 5:08 pm, edited 1 time in total.
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm
by savageautomate » Mon Apr 01, 2013 5:06 pm
You could paste your code at http://pastebin.com/ and then just include a link here.
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com
User avatar
Posts: 187
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
by bdjantl » Mon Apr 01, 2013 5:09 pm
savageautomate wrote:You could paste your code at http://pastebin.com/ and then just include a link here.


I attached the code in a code-block in my previous comment...
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm
by savageautomate » Mon Apr 01, 2013 6:39 pm
Got it. Having difficulty understanding code logic without a better understanding on how the keypad works. Any links for documentation on the keypad?

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com
User avatar
Posts: 187
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
by bdjantl » Mon Apr 01, 2013 6:51 pm
In fact there is. You can find it here: http://www.schurter.com/var/schurter/storage/ilcatalogue/files/document/datasheet/en/pdf/typ_12_key_piezo_keypad.pdf

I am using the 12 key keypad. On page 8 you see a circuit diagram of the keypad. When someone presses a key, one of the vertical lines, pin 1 and 3 on the keypad (connected on GPIO 15 and 16) and one of the horizontal lines (pins 4-6, connected on GPIO 1, 4, 5, 6, 10 and 11) are connected. So... line 1 and 4 'tells' me the user pressed 6 on the keypad.
The python code works with originally works with the number of columns and rows on the keypad, which isn't the case here. But with slight modifications to my situation it shows me that it should be possible to read out the keypad.

Thanks in advance for your time.
-Jan
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm
by reinaldo.rda » Fri Oct 17, 2014 6:58 pm
bdjantl, you could implement reading the keypad using the Pi4J library? I'm having trouble to read a 4x4 keypad, any help will be appreciated.
Posts: 3
Joined: Thu Aug 14, 2014 1:30 pm
by bdjantl » Fri Oct 24, 2014 9:26 pm
reinaldo.rda wrote:bdjantl, you could implement reading the keypad using the Pi4J library? I'm having trouble to read a 4x4 keypad, any help will be appreciated.


Hi Reinaldo.rda,

What I did first was find out which are the input and output lines on the keyboard. You should setup these lines using the GPIO ports in your code. My keypad had two input lines and six output lines. I also had a schema from this keyboard which identifies the keys on the keypad by combining the input and output lines. For the input lines you create listeners and react on a state change by finding the corresponding output line. From the state change you know which input port was activated. By setting all output lines to high to low, one by one, you can check if the found inputline gets low to. If so, you found the two lines 'crossing' each other, which will give you key pressed on your keypad.
It's a bit cryptic maybe, but this is how I got it working.
Below the example code. It's documented and should give you some more pointers on how to implement this.

Regards,

Jan

Code: Select all
import java.util.HashMap;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;

/**
 * The Class PiezoKeypad.
 */
public class PiezoKeypad
{

   /**
    * <pre>
    * Keypad pin schema key = pina + pinb     
    *     o oiiiiii (output/input) 
    * 1 =   3 5 
    * 2 =   3  6 
    * 3 =   3   7 
    * 4 =   3    8 
    * 5 =   3     9 
    * 6 = 1  4 
    * 7 = 1   5 
    * 8 = 1    6 
    * 9 = 1     7 
    * * = 1      8 
    * 0 =   34 
    * # = 1       9
    * </pre>
    *
    * .
    */

   /** The Constant PINMAPPING. */
   private static final HashMap<String, Integer> PINMAPPING = new HashMap<String, Integer>();

   /** The gpio. */
   private final GpioController theGpio = GpioFactory.getInstance();

   /** The Constant PIN_1_IN. */
   private static final Pin PIN_1_OUT = RaspiPin.GPIO_15;

   /** The Constant PIN_3_IN. */
   private static final Pin PIN_3_OUT = RaspiPin.GPIO_16;

   /** The Constant PIN_4_IN. */
   private static final Pin PIN_4_IN = RaspiPin.GPIO_01;

   /** The Constant PIN_5_IN. */
   private static final Pin PIN_5_IN = RaspiPin.GPIO_04;

   /** The Constant PIN_6_IN. */
   private static final Pin PIN_6_IN = RaspiPin.GPIO_05;

   /** The Constant PIN_7_IN. */
   private static final Pin PIN_7_IN = RaspiPin.GPIO_06;

   /** The Constant PIN_8_IN. */
   @SuppressWarnings("unused")
   private static final Pin PIN_8_IN = RaspiPin.GPIO_10;

   /** The Constant PIN_9_IN. */
   @SuppressWarnings("unused")
   private static final Pin PIN_9_IN = RaspiPin.GPIO_11;

   /** The pin1. */
   private final GpioPinDigitalOutput thePin1 = theGpio
         .provisionDigitalOutputPin(PIN_1_OUT);

   /** The pin3. */
   private final GpioPinDigitalOutput thePin3 = theGpio
         .provisionDigitalOutputPin(PIN_3_OUT);

   /** The pin4. */
   private final GpioPinDigitalInput thePin4 = theGpio
         .provisionDigitalInputPin(PIN_4_IN, PinPullResistance.PULL_UP);

   /** The pin5. */
   private final GpioPinDigitalInput thePin5 = theGpio
         .provisionDigitalInputPin(PIN_5_IN, PinPullResistance.PULL_UP);

   /** The pin6. */
   private final GpioPinDigitalInput thePin6 = theGpio
         .provisionDigitalInputPin(PIN_6_IN, PinPullResistance.PULL_UP);

   /** The pin7. */
   private final GpioPinDigitalInput thePin7 = theGpio
         .provisionDigitalInputPin(PIN_7_IN, PinPullResistance.PULL_UP);

   /** The pin8. */
   private final GpioPinDigitalInput thePin8 = theGpio
         .provisionDigitalInputPin(PIN_8_IN, PinPullResistance.PULL_UP);

   /** The pin9. */
   private final GpioPinDigitalInput thePin9 = theGpio
         .provisionDigitalInputPin(PIN_9_IN, PinPullResistance.PULL_UP);

   /** The outputs. */
   private final GpioPinDigitalOutput theOutputs[] = { thePin1, thePin3 };

   /** The input. */
   private GpioPinDigitalInput theInput;

   /** The in id. */
   private int theInId;

   /** The first pin. */
   private int theFirstPin = 0;

   /** The second pin. */
   private int theSecondPin = 0;

   /**
    * Instantiates a new piezo keypad.
    */
   public PiezoKeypad()
   {
      initMapping();

      initListeners();
   }

   /**
    * Check pins.
    *
    * Determins the pressed key based on the activated GPIO pins.
    */
   private synchronized void checkPins()
   {
      if (theFirstPin != 0 && theSecondPin != 0)
      {
         final int myInput = PINMAPPING
               .get(theFirstPin + theSecondPin);

         // inform the externa listeners on the pressed key
         PiezoKeypad.this.fireEvent(myInput);

         theFirstPin = 0;
         theSecondPin = 0;
      }
   }

   /**
    * Find output.
    *
    * Sets output lines  to high and then to low one by one.
    * Then the input line is tested. If its state is low, we have the right output line and therefore
    * a mapping to a key on the keypad.
    */
   private void findOutput()
   {
      // now test the inputs by setting the outputs from high to low
      // one by one
      for (int myO = 0; myO < theOutputs.length; myO++)
      {
         for (final GpioPinDigitalOutput myTheOutput : theOutputs)
         {
            myTheOutput.high();
         }

         theOutputs[myO].low();

         // input found?
         if (theInput.isLow())
         {
            theSecondPin = theInId;

            if (myO == 0)
            {
               theFirstPin = 1;
            }
            else
            {
               theFirstPin = 3;
            }

            checkPins();
            break;
         }
      }

      for (final GpioPinDigitalOutput myTheOutput : theOutputs)
      {
         myTheOutput.low();
      }
   }

   /**
    * Inits the listeners.
    */
   private void initListeners()
   {
      thePin4.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin4;
               theInId = 4;
               findOutput();
            }
         }
      });
      thePin5.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin5;
               theInId = 5;
               findOutput();
            }
         }
      });
      thePin6.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin6;
               theInId = 6;
               findOutput();
            }
         }
      });
      thePin7.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin7;
               theInId = 7;
               findOutput();
            }
         }
      });
      thePin8.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin8;
               theInId = 8;
               findOutput();
            }
         }
      });
      thePin9.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin9;
               theInId = 9;
               findOutput();
            }
         }
      });
   }

   /**
    * Inits the mapping.
    *
    * Maps input/output line to key on keypad.
    */
   private void initMapping()
   {
      PINMAPPING.put("35", (int) '1');
      PINMAPPING.put("36", (int) '2');
      PINMAPPING.put("37"), (int) '3');
      PINMAPPING.put("38"), (int) '4');
      PINMAPPING.put("39"), (int) '5');
      PINMAPPING.put("14"), (int) '6');
      PINMAPPING.put("15"), (int) '7');
      PINMAPPING.put("16"), (int) '8');
      PINMAPPING.put("17"), (int) '9');
      PINMAPPING.put("18"), (int) '*');
      PINMAPPING.put("34"), (int) '0');
      PINMAPPING.put("19"), (int) '#');
   }
}
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm
by reinaldo.rda » Mon Oct 27, 2014 10:46 am
bdjantl wrote:
reinaldo.rda wrote:bdjantl, you could implement reading the keypad using the Pi4J library? I'm having trouble to read a 4x4 keypad, any help will be appreciated.


Hi Reinaldo.rda,

What I did first was find out which are the input and output lines on the keyboard. You should setup these lines using the GPIO ports in your code. My keypad had two input lines and six output lines. I also had a schema from this keyboard which identifies the keys on the keypad by combining the input and output lines. For the input lines you create listeners and react on a state change by finding the corresponding output line. From the state change you know which input port was activated. By setting all output lines to high to low, one by one, you can check if the found inputline gets low to. If so, you found the two lines 'crossing' each other, which will give you key pressed on your keypad.
It's a bit cryptic maybe, but this is how I got it working.
Below the example code. It's documented and should give you some more pointers on how to implement this.

Regards,

Jan

Code: Select all
import java.util.HashMap;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;

/**
 * The Class PiezoKeypad.
 */
public class PiezoKeypad
{

   /**
    * <pre>
    * Keypad pin schema key = pina + pinb     
    *     o oiiiiii (output/input) 
    * 1 =   3 5 
    * 2 =   3  6 
    * 3 =   3   7 
    * 4 =   3    8 
    * 5 =   3     9 
    * 6 = 1  4 
    * 7 = 1   5 
    * 8 = 1    6 
    * 9 = 1     7 
    * * = 1      8 
    * 0 =   34 
    * # = 1       9
    * </pre>
    *
    * .
    */

   /** The Constant PINMAPPING. */
   private static final HashMap<String, Integer> PINMAPPING = new HashMap<String, Integer>();

   /** The gpio. */
   private final GpioController theGpio = GpioFactory.getInstance();

   /** The Constant PIN_1_IN. */
   private static final Pin PIN_1_OUT = RaspiPin.GPIO_15;

   /** The Constant PIN_3_IN. */
   private static final Pin PIN_3_OUT = RaspiPin.GPIO_16;

   /** The Constant PIN_4_IN. */
   private static final Pin PIN_4_IN = RaspiPin.GPIO_01;

   /** The Constant PIN_5_IN. */
   private static final Pin PIN_5_IN = RaspiPin.GPIO_04;

   /** The Constant PIN_6_IN. */
   private static final Pin PIN_6_IN = RaspiPin.GPIO_05;

   /** The Constant PIN_7_IN. */
   private static final Pin PIN_7_IN = RaspiPin.GPIO_06;

   /** The Constant PIN_8_IN. */
   @SuppressWarnings("unused")
   private static final Pin PIN_8_IN = RaspiPin.GPIO_10;

   /** The Constant PIN_9_IN. */
   @SuppressWarnings("unused")
   private static final Pin PIN_9_IN = RaspiPin.GPIO_11;

   /** The pin1. */
   private final GpioPinDigitalOutput thePin1 = theGpio
         .provisionDigitalOutputPin(PIN_1_OUT);

   /** The pin3. */
   private final GpioPinDigitalOutput thePin3 = theGpio
         .provisionDigitalOutputPin(PIN_3_OUT);

   /** The pin4. */
   private final GpioPinDigitalInput thePin4 = theGpio
         .provisionDigitalInputPin(PIN_4_IN, PinPullResistance.PULL_UP);

   /** The pin5. */
   private final GpioPinDigitalInput thePin5 = theGpio
         .provisionDigitalInputPin(PIN_5_IN, PinPullResistance.PULL_UP);

   /** The pin6. */
   private final GpioPinDigitalInput thePin6 = theGpio
         .provisionDigitalInputPin(PIN_6_IN, PinPullResistance.PULL_UP);

   /** The pin7. */
   private final GpioPinDigitalInput thePin7 = theGpio
         .provisionDigitalInputPin(PIN_7_IN, PinPullResistance.PULL_UP);

   /** The pin8. */
   private final GpioPinDigitalInput thePin8 = theGpio
         .provisionDigitalInputPin(PIN_8_IN, PinPullResistance.PULL_UP);

   /** The pin9. */
   private final GpioPinDigitalInput thePin9 = theGpio
         .provisionDigitalInputPin(PIN_9_IN, PinPullResistance.PULL_UP);

   /** The outputs. */
   private final GpioPinDigitalOutput theOutputs[] = { thePin1, thePin3 };

   /** The input. */
   private GpioPinDigitalInput theInput;

   /** The in id. */
   private int theInId;

   /** The first pin. */
   private int theFirstPin = 0;

   /** The second pin. */
   private int theSecondPin = 0;

   /**
    * Instantiates a new piezo keypad.
    */
   public PiezoKeypad()
   {
      initMapping();

      initListeners();
   }

   /**
    * Check pins.
    *
    * Determins the pressed key based on the activated GPIO pins.
    */
   private synchronized void checkPins()
   {
      if (theFirstPin != 0 && theSecondPin != 0)
      {
         final int myInput = PINMAPPING
               .get(theFirstPin + theSecondPin);

         // inform the externa listeners on the pressed key
         PiezoKeypad.this.fireEvent(myInput);

         theFirstPin = 0;
         theSecondPin = 0;
      }
   }

   /**
    * Find output.
    *
    * Sets output lines  to high and then to low one by one.
    * Then the input line is tested. If its state is low, we have the right output line and therefore
    * a mapping to a key on the keypad.
    */
   private void findOutput()
   {
      // now test the inputs by setting the outputs from high to low
      // one by one
      for (int myO = 0; myO < theOutputs.length; myO++)
      {
         for (final GpioPinDigitalOutput myTheOutput : theOutputs)
         {
            myTheOutput.high();
         }

         theOutputs[myO].low();

         // input found?
         if (theInput.isLow())
         {
            theSecondPin = theInId;

            if (myO == 0)
            {
               theFirstPin = 1;
            }
            else
            {
               theFirstPin = 3;
            }

            checkPins();
            break;
         }
      }

      for (final GpioPinDigitalOutput myTheOutput : theOutputs)
      {
         myTheOutput.low();
      }
   }

   /**
    * Inits the listeners.
    */
   private void initListeners()
   {
      thePin4.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin4;
               theInId = 4;
               findOutput();
            }
         }
      });
      thePin5.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin5;
               theInId = 5;
               findOutput();
            }
         }
      });
      thePin6.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin6;
               theInId = 6;
               findOutput();
            }
         }
      });
      thePin7.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin7;
               theInId = 7;
               findOutput();
            }
         }
      });
      thePin8.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin8;
               theInId = 8;
               findOutput();
            }
         }
      });
      thePin9.addListener(new GpioPinListenerDigital()
      {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent)
         {
            if (aEvent.getState() == PinState.LOW)
            {
               theInput = thePin9;
               theInId = 9;
               findOutput();
            }
         }
      });
   }

   /**
    * Inits the mapping.
    *
    * Maps input/output line to key on keypad.
    */
   private void initMapping()
   {
      PINMAPPING.put("35", (int) '1');
      PINMAPPING.put("36", (int) '2');
      PINMAPPING.put("37"), (int) '3');
      PINMAPPING.put("38"), (int) '4');
      PINMAPPING.put("39"), (int) '5');
      PINMAPPING.put("14"), (int) '6');
      PINMAPPING.put("15"), (int) '7');
      PINMAPPING.put("16"), (int) '8');
      PINMAPPING.put("17"), (int) '9');
      PINMAPPING.put("18"), (int) '*');
      PINMAPPING.put("34"), (int) '0');
      PINMAPPING.put("19"), (int) '#');
   }
}


bdjantl, thanks for your help, I made small changes to the code that you sent and it worked perfectly for reading a 4x4 keypad using pi4j, following code.

Code: Select all
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

public class KeypadTest {

   private List<PropertyChangeListener> listener = new ArrayList<PropertyChangeListener>();
   public static final String KEY = "key";
   private char keyPressed;

   /** The Constant KEYPAD. */
   private static final char keypad[][] = { { '1', '2', '3', 'A' },
         { '4', '5', '6', 'B' }, { '7', '8', '9', 'C' },
         { '*', '0', '#', 'D' } };

   /** The gpio. */
   private final GpioController theGpio = GpioFactory.getInstance();

   /** The Constant PIN_1_IN. */
   private static final Pin PIN_1_IN = RaspiPin.GPIO_07;

   /** The Constant PIN_2_IN. */
   private static final Pin PIN_2_IN = RaspiPin.GPIO_00;

   /** The Constant PIN_3_IN. */
   private static final Pin PIN_3_IN = RaspiPin.GPIO_02;

   /** The Constant PIN_4_IN. */
   private static final Pin PIN_4_IN = RaspiPin.GPIO_03;

   /** The Constant PIN_5_OUT. */
   private static final Pin PIN_5_OUT = RaspiPin.GPIO_01;

   /** The Constant PIN_6_OUT. */
   private static final Pin PIN_6_OUT = RaspiPin.GPIO_04;

   /** The Constant PIN_7_OUT. */
   private static final Pin PIN_7_OUT = RaspiPin.GPIO_05;

   /** The Constant PIN_8_OUT. */
   private static final Pin PIN_8_OUT = RaspiPin.GPIO_06;

   /** The pin1. */
   private final GpioPinDigitalInput thePin1 = theGpio
         .provisionDigitalInputPin(PIN_1_IN, PinPullResistance.PULL_UP);

   /** The pin2. */
   private final GpioPinDigitalInput thePin2 = theGpio
         .provisionDigitalInputPin(PIN_2_IN, PinPullResistance.PULL_UP);

   /** The pin3. */
   private final GpioPinDigitalInput thePin3 = theGpio
         .provisionDigitalInputPin(PIN_3_IN, PinPullResistance.PULL_UP);

   /** The pin4. */
   private final GpioPinDigitalInput thePin4 = theGpio
         .provisionDigitalInputPin(PIN_4_IN, PinPullResistance.PULL_UP);

   /** The pin5. */
   private final GpioPinDigitalOutput thePin5 = theGpio
         .provisionDigitalOutputPin(PIN_5_OUT);

   /** The pin6. */
   private final GpioPinDigitalOutput thePin6 = theGpio
         .provisionDigitalOutputPin(PIN_6_OUT);

   /** The pin7. */
   private final GpioPinDigitalOutput thePin7 = theGpio
         .provisionDigitalOutputPin(PIN_7_OUT);

   /** The pin8. */
   private final GpioPinDigitalOutput thePin8 = theGpio
         .provisionDigitalOutputPin(PIN_8_OUT);

   /** The outputs. */
   private final GpioPinDigitalOutput theOutputs[] = { thePin5, thePin6,
         thePin7, thePin8 };

   /** The input. */
   private GpioPinDigitalInput theInput;

   /** The in id. */
   private int theLin;

   /** The in id. */
   private int theCol;

   /**
    * Instantiates a new piezo keypad.
    */
   public KeypadTest() {
      initListeners();
   }

   /**
    * Find output.
    *
    * Sets output lines to high and then to low one by one. Then the input line
    * is tested. If its state is low, we have the right output line and
    * therefore a mapping to a key on the keypad.
    */
   private void findOutput() {
      // now test the inuts by setting the outputs from high to low
      // one by one
      for (int myO = 0; myO < theOutputs.length; myO++) {
         for (final GpioPinDigitalOutput myTheOutput : theOutputs) {
            myTheOutput.high();
         }

         theOutputs[myO].low();

         // input found?
         if (theInput.isLow()) {
            theCol = myO;
            checkPins();
            try {
               Thread.sleep(200);
            } catch (InterruptedException e) {
            }
            break;
         }
      }

      for (final GpioPinDigitalOutput myTheOutput : theOutputs) {
         myTheOutput.low();
      }
   }

   /**
    * Check pins.
    *
    * Determins the pressed key based on the activated GPIO pins.
    */
   private synchronized void checkPins() {

      notifyListeners(this, KEY, this.keyPressed,
            this.keyPressed = keypad[theLin - 1][theCol]);

      // System.out.println(keypad[theLin - 1][theCol]);
   }

   /**
    * Inits the listeners.
    */
   private void initListeners() {
      thePin1.addListener(new GpioPinListenerDigital() {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent) {
            if (aEvent.getState() == PinState.LOW) {
               theInput = thePin1;
               theLin = 1;
               findOutput();
            }
         }
      });
      thePin2.addListener(new GpioPinListenerDigital() {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent) {
            if (aEvent.getState() == PinState.LOW) {
               theInput = thePin2;
               theLin = 2;
               findOutput();
            }
         }
      });
      thePin3.addListener(new GpioPinListenerDigital() {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent) {
            if (aEvent.getState() == PinState.LOW) {
               theInput = thePin3;
               theLin = 3;
               findOutput();
            }
         }
      });
      thePin4.addListener(new GpioPinListenerDigital() {
         @Override
         public void handleGpioPinDigitalStateChangeEvent(
               final GpioPinDigitalStateChangeEvent aEvent) {
            if (aEvent.getState() == PinState.LOW) {
               theInput = thePin4;
               theLin = 4;
               findOutput();
            }
         }
      });
   }

   private void notifyListeners(Object object, String property, char oldValue,
         char newValue) {
      for (PropertyChangeListener name : listener) {
         name.propertyChange(new PropertyChangeEvent(this, property,
               oldValue, newValue));
      }
   }

   public void addChangeListener(PropertyChangeListener newListener) {
      listener.add(newListener);
   }
}
Posts: 3
Joined: Thu Aug 14, 2014 1:30 pm
by bdjantl » Mon Oct 27, 2014 10:53 am
Glad I could help!

Regards, Jan
Posts: 6
Joined: Thu Jan 31, 2013 8:47 pm