Keypad on Rpi using Pi4J


7 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: 4
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: 184
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: 4
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: 184
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: 4
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: 184
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: 4
Joined: Thu Jan 31, 2013 8:47 pm