Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Is it possible to run more than one pin to an interrupt for sleep/wake purposes?

Is it possible to run more than one pin to an interrupt for sleep/wake purposes?

Scheduled Pinned Locked Moved Troubleshooting
55 Posts 7 Posters 14.2k Views 5 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • AWIA AWI

    @karl261 There is no clue reading through the articles. I suggest you try to force an interrupt by pulling one pin low in idle. If that works, we go from there.

    There are a few 16key & 8key more simple examples ;) with touch keypads

    karl261K Offline
    karl261K Offline
    karl261
    wrote on last edited by
    #28

    @AWI I think the problem is with the keypad. Because it is not really putting a signal to its pins. The only thing it does is short circuiting them when a key is pressed... No change in high or low.

    I tried for example to pull row 1 to high and column 1 to low. Then the interrupt fires ( I think) but there is no key press detected any more. But I am not sure if the interrupt fires correctly.

    I tested some variations last night, but nothing works. It's all still set up on the breadboard, so if you have some suggestions I am happy to try.

    AWIA 1 Reply Last reply
    0
    • karl261K karl261

      @AWI I think the problem is with the keypad. Because it is not really putting a signal to its pins. The only thing it does is short circuiting them when a key is pressed... No change in high or low.

      I tried for example to pull row 1 to high and column 1 to low. Then the interrupt fires ( I think) but there is no key press detected any more. But I am not sure if the interrupt fires correctly.

      I tested some variations last night, but nothing works. It's all still set up on the breadboard, so if you have some suggestions I am happy to try.

      AWIA Offline
      AWIA Offline
      AWI
      Hero Member
      wrote on last edited by
      #29

      @karl261 That's how it is supposed to be. When the library "scans" the keyboard it succesively pulls one of the rows (or colums) and check in the colums (or rows) if there is a connection. To have interrupts detected either the rows of colums should be set to low to detect a change. That would mean adapting the library (if possible) -or- (more fun) build your own routine by using Rob Tillaarts basic library from your previous post.
      I don't have any PCF8574 to play with...

      karl261K 2 Replies Last reply
      0
      • AWIA AWI

        @karl261 That's how it is supposed to be. When the library "scans" the keyboard it succesively pulls one of the rows (or colums) and check in the colums (or rows) if there is a connection. To have interrupts detected either the rows of colums should be set to low to detect a change. That would mean adapting the library (if possible) -or- (more fun) build your own routine by using Rob Tillaarts basic library from your previous post.
        I don't have any PCF8574 to play with...

        karl261K Offline
        karl261K Offline
        karl261
        wrote on last edited by
        #30

        @AWI Yes, basically, 4 inputs should be set to high in the library, and 4 inputs to low. Rows and columns. I had a look at the library examples yesterday, but so far it is beyond my programming skills. As far as I understand from all the docs this is theoretically possible.

        Then, if done so, the pcf should detect a change in the low/high of the input pins and also detect what key was pressed. Or better the library interprets the received data by i2c correctly.

        1 Reply Last reply
        0
        • AWIA AWI

          @karl261 There is no clue reading through the articles. I suggest you try to force an interrupt by pulling one pin low in idle. If that works, we go from there.

          There are a few 16key & 8key more simple examples ;) with touch keypads

          karl261K Offline
          karl261K Offline
          karl261
          wrote on last edited by
          #31

          @AWI Yeah, I guess just getting another keypad would be the easiest solution. Pitty though. I like my keypad and the fact that it is self-adhesive on the outside of the case.

          1 Reply Last reply
          0
          • karl261K Offline
            karl261K Offline
            karl261
            wrote on last edited by
            #32

            Or I go back to my three proposed solutions. For example solution 3) works fine. I tested it.

            1 Reply Last reply
            0
            • AWIA AWI

              @karl261 That's how it is supposed to be. When the library "scans" the keyboard it succesively pulls one of the rows (or colums) and check in the colums (or rows) if there is a connection. To have interrupts detected either the rows of colums should be set to low to detect a change. That would mean adapting the library (if possible) -or- (more fun) build your own routine by using Rob Tillaarts basic library from your previous post.
              I don't have any PCF8574 to play with...

              karl261K Offline
              karl261K Offline
              karl261
              wrote on last edited by
              #33

              @AWI I think this Library sounds very promising. What do you think? At least it talks about high and low.

              http://playground.arduino.cc/Main/I2CPortExpanderAndKeypads

              AWIA 1 Reply Last reply
              0
              • karl261K karl261

                @AWI I think this Library sounds very promising. What do you think? At least it talks about high and low.

                http://playground.arduino.cc/Main/I2CPortExpanderAndKeypads

                AWIA Offline
                AWIA Offline
                AWI
                Hero Member
                wrote on last edited by
                #34

                @karl261 At least it is a more comprehensible library but it does not deal with interrupts (yet).
                Are you able to do the following experiment?

                • Using the library you quoted, execute the following sketch
                #include <Wire.h>
                #include <i2ckeypad.h>
                
                #define ROWS 4
                #define COLS 3
                
                // With A0, A1 and A2 of PCF8574 to ground I2C address is 0x20
                #define PCF8574_ADDR 0x20
                
                
                i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS);
                
                void setup()
                {
                  Serial.begin(9600);
                
                  Wire.begin();
                
                  kpd.init();
                   
                
                  Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
                
                  pcf8574_write(pcf8574_i2c_addr, 0xf0);
                
                }
                
                void loop()
                {
                }
                
                
                • measure the input/output pins of the pcf8574 (should be 4 pins low/ 4 pins high)
                • measure the power consumption of the pcf8574 (hope it is next to nothing)

                IF the above is true we can easily rework te sketch to use the interrupt.

                karl261K 2 Replies Last reply
                0
                • AWIA AWI

                  @karl261 At least it is a more comprehensible library but it does not deal with interrupts (yet).
                  Are you able to do the following experiment?

                  • Using the library you quoted, execute the following sketch
                  #include <Wire.h>
                  #include <i2ckeypad.h>
                  
                  #define ROWS 4
                  #define COLS 3
                  
                  // With A0, A1 and A2 of PCF8574 to ground I2C address is 0x20
                  #define PCF8574_ADDR 0x20
                  
                  
                  i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS);
                  
                  void setup()
                  {
                    Serial.begin(9600);
                  
                    Wire.begin();
                  
                    kpd.init();
                     
                  
                    Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
                  
                    pcf8574_write(pcf8574_i2c_addr, 0xf0);
                  
                  }
                  
                  void loop()
                  {
                  }
                  
                  
                  • measure the input/output pins of the pcf8574 (should be 4 pins low/ 4 pins high)
                  • measure the power consumption of the pcf8574 (hope it is next to nothing)

                  IF the above is true we can easily rework te sketch to use the interrupt.

                  karl261K Offline
                  karl261K Offline
                  karl261
                  wrote on last edited by karl261
                  #35

                  @AWI Thanks. I am in the train now and I am spending my time to try to understand how things work. I also made some progress in my brain. My idea is similar, but you already have a sketch ready. :-) I will try it out, I guess on Saturday. Until then I will try to deepen my knowledge of the libraries.

                  It is also possible with the "original" library, but you are right: the "new" library is much clearer.

                  1 Reply Last reply
                  0
                  • AWIA AWI

                    @karl261 At least it is a more comprehensible library but it does not deal with interrupts (yet).
                    Are you able to do the following experiment?

                    • Using the library you quoted, execute the following sketch
                    #include <Wire.h>
                    #include <i2ckeypad.h>
                    
                    #define ROWS 4
                    #define COLS 3
                    
                    // With A0, A1 and A2 of PCF8574 to ground I2C address is 0x20
                    #define PCF8574_ADDR 0x20
                    
                    
                    i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS);
                    
                    void setup()
                    {
                      Serial.begin(9600);
                    
                      Wire.begin();
                    
                      kpd.init();
                       
                    
                      Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
                    
                      pcf8574_write(pcf8574_i2c_addr, 0xf0);
                    
                    }
                    
                    void loop()
                    {
                    }
                    
                    
                    • measure the input/output pins of the pcf8574 (should be 4 pins low/ 4 pins high)
                    • measure the power consumption of the pcf8574 (hope it is next to nothing)

                    IF the above is true we can easily rework te sketch to use the interrupt.

                    karl261K Offline
                    karl261K Offline
                    karl261
                    wrote on last edited by karl261
                    #36

                    @AWI I found this library:

                    https://github.com/skywodd/pcf8574_arduino_library

                    There is a lot of talk about interrupt functionality and it seems to be somehow implemented. But I don't fully understand how it works. Maybe you can make something out of it?

                    Oh, and maybe in even more detail with some examples, I have not read it yet:

                    https://github.com/RalphBacon/PCF8574-Pin-Extender-I2C

                    ...but it looks like a software interrupt rather than a hardware interrupt??? I am confused.

                    ... at least for the last example: It does not need any library. It's all quite clear in one sketch.

                    AWIA 1 Reply Last reply
                    0
                    • karl261K karl261

                      @AWI I found this library:

                      https://github.com/skywodd/pcf8574_arduino_library

                      There is a lot of talk about interrupt functionality and it seems to be somehow implemented. But I don't fully understand how it works. Maybe you can make something out of it?

                      Oh, and maybe in even more detail with some examples, I have not read it yet:

                      https://github.com/RalphBacon/PCF8574-Pin-Extender-I2C

                      ...but it looks like a software interrupt rather than a hardware interrupt??? I am confused.

                      ... at least for the last example: It does not need any library. It's all quite clear in one sketch.

                      AWIA Offline
                      AWIA Offline
                      AWI
                      Hero Member
                      wrote on last edited by
                      #37

                      @karl261 the last sketch does not work with interrupts. It just mentions them.

                      I would stick with the previous suggestion. Measure the current when you set some outputs to low (low is active 1)

                      karl261K 2 Replies Last reply
                      0
                      • AWIA AWI

                        @karl261 the last sketch does not work with interrupts. It just mentions them.

                        I would stick with the previous suggestion. Measure the current when you set some outputs to low (low is active 1)

                        karl261K Offline
                        karl261K Offline
                        karl261
                        wrote on last edited by
                        #38

                        @AWI Yes, I will work with the test sketch on the weekend. It is clear to me now how to set pins of the PCF8574 to HIGH or LOW, and from there we can see.

                        1 Reply Last reply
                        0
                        • AWIA AWI

                          @karl261 the last sketch does not work with interrupts. It just mentions them.

                          I would stick with the previous suggestion. Measure the current when you set some outputs to low (low is active 1)

                          karl261K Offline
                          karl261K Offline
                          karl261
                          wrote on last edited by karl261
                          #39

                          @AWI Finally:

                          Yes, it works as expected. 4 pins are 0 V and 4 pins are 3.3 V. The chip is using 2.5 uA.

                          I had to change a little bit the library, it did not compile and was slightly outdated, also the function we wanted to use was private, but I just did the changes in the library.

                          I also needed to update to the latest arduino from 1.6.5 to 1.6.12, because i got an error: collect2.exe: error: ld returned 5 exit status. Now it works.

                          Where do we go from here?

                          AWIA 1 Reply Last reply
                          1
                          • karl261K karl261

                            @AWI Finally:

                            Yes, it works as expected. 4 pins are 0 V and 4 pins are 3.3 V. The chip is using 2.5 uA.

                            I had to change a little bit the library, it did not compile and was slightly outdated, also the function we wanted to use was private, but I just did the changes in the library.

                            I also needed to update to the latest arduino from 1.6.5 to 1.6.12, because i got an error: collect2.exe: error: ld returned 5 exit status. Now it works.

                            Where do we go from here?

                            AWIA Offline
                            AWIA Offline
                            AWI
                            Hero Member
                            wrote on last edited by
                            #40

                            @karl261 Thats good news! What you now have is 4 rows high/ 4 colums low (or v.v.). Now short a column with a row and and expect :baby: an interrupt (= keypress). If that is the case, you can create (or copy) a routine to read the key or keys pushed.

                            karl261K 3 Replies Last reply
                            0
                            • AWIA AWI

                              @karl261 Thats good news! What you now have is 4 rows high/ 4 colums low (or v.v.). Now short a column with a row and and expect :baby: an interrupt (= keypress). If that is the case, you can create (or copy) a routine to read the key or keys pushed.

                              karl261K Offline
                              karl261K Offline
                              karl261
                              wrote on last edited by
                              #41

                              @AWI yeah, I kind of thought the same. I'll try to have rows high and colls low and see if the interrupt pin finally triggers. I should have some pull up on the interrupt pin. Then I'll need to see if I need any pull up or down on the other lines..,

                              Hope I'll get something done this weekend.

                              1 Reply Last reply
                              0
                              • AWIA AWI

                                @karl261 Thats good news! What you now have is 4 rows high/ 4 colums low (or v.v.). Now short a column with a row and and expect :baby: an interrupt (= keypress). If that is the case, you can create (or copy) a routine to read the key or keys pushed.

                                karl261K Offline
                                karl261K Offline
                                karl261
                                wrote on last edited by
                                #42

                                @AWI Ok, so far so good. If I connect 4 high wires to rows and 4 low wires to columns (or vice versa, no idea) then the interrupt pin indeed changes to 0. If I connect the interrupt pin of the IC to D3of the Arduino and then both through a pull up of 10 kOhm to Vcc, the interrupt is at 3.3 V. If I press a key it goes down to 0.040 V. That should be enough to read it as low.

                                That sounds good, doesn't it? The question is, whether the key library still works...

                                AWIA 1 Reply Last reply
                                0
                                • karl261K karl261

                                  @AWI Ok, so far so good. If I connect 4 high wires to rows and 4 low wires to columns (or vice versa, no idea) then the interrupt pin indeed changes to 0. If I connect the interrupt pin of the IC to D3of the Arduino and then both through a pull up of 10 kOhm to Vcc, the interrupt is at 3.3 V. If I press a key it goes down to 0.040 V. That should be enough to read it as low.

                                  That sounds good, doesn't it? The question is, whether the key library still works...

                                  AWIA Offline
                                  AWIA Offline
                                  AWI
                                  Hero Member
                                  wrote on last edited by AWI
                                  #43

                                  @karl261 Certainly and it can be pretty straight forward from here. Stick to the library you use (this), it contains all you need. You need to let MySensors catch the interrupt (in the sleep function) and have the callback routine (receive) execute char key = kpd.get_key(); as described in the example.

                                  1 Reply Last reply
                                  0
                                  • AWIA AWI

                                    @karl261 Thats good news! What you now have is 4 rows high/ 4 colums low (or v.v.). Now short a column with a row and and expect :baby: an interrupt (= keypress). If that is the case, you can create (or copy) a routine to read the key or keys pushed.

                                    karl261K Offline
                                    karl261K Offline
                                    karl261
                                    wrote on last edited by
                                    #44

                                    @AWI It does not compile... I get this stupid error again:

                                    collect2.exe: error: ld returned 5 exit status

                                    But I don't know what to do with it.

                                    1 Reply Last reply
                                    0
                                    • karl261K Offline
                                      karl261K Offline
                                      karl261
                                      wrote on last edited by
                                      #45

                                      current code

                                      sketch

                                      #include <Wire.h>
                                      #include <i2ckeypad.h>
                                      
                                      #define ROWS 4
                                      #define COLS 4
                                      
                                      // With A0, A1 and A2 of PCF8574 to ground I2C address is 0x20
                                      #define PCF8574_ADDR 0x38
                                      #define PCF8574_PIN_CONFIG 0xf0
                                      
                                      
                                      i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS, PCF8574_PIN_CONFIG);
                                      
                                      void setup()
                                      {
                                        Serial.begin(9600);
                                      
                                        Wire.begin();
                                      
                                        kpd.init();
                                         
                                      
                                        Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
                                      
                                      //  pcf8574_write(pcf8574_i2c_addr, 0xf0);
                                      
                                      }
                                      
                                      void loop()
                                      {
                                        char key = kpd.get_key();
                                      
                                        if(key != '\0') {
                                              Serial.print(key);
                                        }
                                      }
                                      

                                      .cpp

                                      /*
                                       *  i2ckeypad.cpp v0.1 - keypad/I2C expander interface for Arduino
                                       *
                                       *  Copyright (c) 2009 Angel Sancho <angelitodeb@gmail.com>
                                       *  All rights reserved.
                                       *
                                       *  Original source from keypad v0.3 of Mark Stanley <mstanley@technologist.com>
                                       *  (http://www.arduino.cc/playground/Main/KeypadTutorial)
                                       *
                                       *
                                       *  LICENSE
                                       *  -------
                                       *  This program is free software: you can redistribute it and/or modify
                                       *  it under the terms of the GNU General Public License as published by
                                       *  the Free Software Foundation, either version 3 of the License, or
                                       *  (at your option) any later version.
                                       *  
                                       *  This program is distributed in the hope that it will be useful,
                                       *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                                       *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                       *  GNU General Public License for more details.
                                       *  
                                       *  You should have received a copy of the GNU General Public License
                                       *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
                                       *
                                       *
                                       *  EXPLANATION
                                       *  -----------
                                       *  This library is designed for use with PCF8574, but can possibly be
                                       *  adapted to other I2C port expanders
                                       *
                                       *  Wiring diagrams for PCF8574 and 4x3 keypad can be found under
                                       *  examples directory. Library runs correctly without cols pull-up
                                       *  resistors but it's better to use it
                                       *
                                       *  You can change pin connections between PCF8574 and keypad under
                                       *  PIN MAPPING section below
                                       *
                                       *  IMPORTANT! You have to call Wire.begin() before init() in your code
                                       *
                                       *  ... and sorry for my poor english!
                                       */
                                      
                                      #include "i2ckeypad.h"
                                      #include <Wire.h>
                                      
                                      //extern "C" {
                                      //  #include "WConstants.h"
                                      //}
                                      
                                      
                                      /*
                                       *  PIN MAPPING
                                       *
                                       *  Here you can change your wire mapping between your keypad and PCF8574
                                       *  Default mapping is for sparkfun 4x3 keypad
                                       */
                                      
                                      #define COL0  2  // P2 of PCF8574, col0 is usually pin 3 of 4x3 keypads
                                      #define COL1  0  // P0 of PCF8574, col1 is usually pin 1 of 4x3 keypads
                                      #define COL2  4  // P4 of PCF8574, col2 is usually pin 5 of 4x3 keypads
                                      #define COL3  7  // sorry, don't have a 4x4 keypad to try it
                                      #define ROW0  1  // P1 of PCF8574, row0 is usually pin 2 of 4x3 keypads
                                      #define ROW1  6  // P6 of PCF8574, row1 is usually pin 7 of 4x3 keypads
                                      #define ROW2  5  // P5 of PCF8574, row2 is usually pin 6 of 4x3 keypads
                                      #define ROW3  3  // P3 of PCF8574, row3 is usually pin 4 of 4x3 keypads
                                      
                                      
                                      /*
                                       *  KEYPAD KEY MAPPING
                                       *
                                       *  Default key mapping for 4x4 keypads, you can change it here if you have or
                                       *  like different keys
                                       */
                                      
                                      const char keymap[4][5] =
                                      {
                                        "123A",
                                        "456B",
                                        "789C",
                                        "*0#D"
                                      };
                                      
                                      
                                      /*
                                       *  VAR AND CONSTANTS DEFINITION. Don't change nothing here
                                       *
                                       */
                                      
                                      // Default row and col pin counts
                                      int num_rows = 4;
                                      int num_cols = 3;
                                      
                                      // PCF8574 i2c address
                                      int pcf8574_i2c_addr;
                                      
                                      // PCF8574 i2c pin configuration (high low)
                                      int pcf8574_i2c_pin_cfg;
                                      
                                      // Current search row
                                      static int row_select;
                                      
                                      // Current data set in PCF8574
                                      static int current_data;
                                      
                                      // Hex byte statement for each port of PCF8574
                                      const int hex_data[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
                                      
                                      // Hex data for each row of keypad in PCF8574
                                      const int pcf8574_row_data[4] = 
                                      {
                                        hex_data[ROW1] | hex_data[ROW2] | hex_data[ROW3] |
                                        hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                        hex_data[ROW0] | hex_data[ROW2] | hex_data[ROW3] |
                                        hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                        hex_data[ROW0] | hex_data[ROW1] | hex_data[ROW3] |
                                        hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                        hex_data[ROW0] | hex_data[ROW1] | hex_data[ROW2] |
                                        hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                      };
                                      
                                      // Hex data for each col of keypad in PCF8574
                                      int col[4] = {hex_data[COL0], hex_data[COL1], hex_data[COL2], hex_data[COL3]};
                                      
                                      
                                      /*
                                       *  CONSTRUCTORS
                                       */
                                      
                                      i2ckeypad::i2ckeypad(int addr)
                                      {
                                        pcf8574_i2c_addr = addr;
                                      }
                                      
                                      i2ckeypad::i2ckeypad(int addr, int r, int c, int pinc)
                                      {
                                        pcf8574_i2c_addr = addr;
                                        num_rows = r;
                                        num_cols = c;
                                        pcf8574_i2c_pin_cfg = pinc;
                                      }
                                      
                                      
                                      /*
                                       *  PUBLIC METHODS
                                       */
                                      
                                      void i2ckeypad::init()
                                      {
                                        // All PCF8574 ports high
                                        pcf8574_write(pcf8574_i2c_addr, pcf8574_i2c_pin_cfg);
                                      
                                        // Start with the first row
                                        row_select = 0;
                                      }
                                      
                                      char i2ckeypad::get_key()
                                      {
                                        static int temp_key;
                                      
                                        int tmp_data;
                                        int r;
                                      
                                        int key = '\0';
                                      
                                        // Search row low
                                        pcf8574_write(pcf8574_i2c_addr, pcf8574_row_data[row_select]);
                                      
                                        for(r=0;r<num_cols;r++) {
                                          // Read pcf8574 port data
                                          tmp_data = pcf8574_byte_read(pcf8574_i2c_addr);
                                      
                                          // XOR to compare obtained data and current data and know
                                          // if some column are low
                                          tmp_data ^= current_data;
                                      
                                          // Key pressed!
                                          if(col[r] == tmp_data) {
                                            temp_key = keymap[row_select][r];
                                            return '\0';
                                          }
                                        }
                                      
                                        // Key was pressed and then released
                                        if((key == '\0') && (temp_key != '\0'))    
                                        {
                                          key = temp_key;
                                          temp_key = '\0';
                                          return key;
                                        }
                                      
                                        // All PCF8574 ports high again
                                        pcf8574_write(pcf8574_i2c_addr, pcf8574_i2c_pin_cfg);
                                      
                                        // Next row
                                        row_select++;
                                        if(row_select == num_rows) {
                                          row_select = 0;
                                        }
                                      
                                        return key;
                                      }
                                      
                                      /*
                                       *  PRIVATE METHODS
                                       */
                                      
                                      void i2ckeypad::pcf8574_write(int addr, int data)
                                      {
                                        current_data = data;
                                      
                                        Wire.beginTransmission(addr);
                                        Wire.write(data);
                                        Wire.endTransmission();
                                      }
                                      
                                      int i2ckeypad::pcf8574_byte_read(int addr)
                                      {
                                        Wire.requestFrom(addr, 1);
                                      
                                        return Wire.read();
                                      }
                                      

                                      .h

                                      #ifndef i2ckeypad_h
                                      #define i2ckeypad_h
                                      
                                      #include <inttypes.h>
                                      
                                      #if ARDUINO >= 100
                                      #include "Arduino.h"
                                      #else
                                      #include "WProgram.h"
                                      #endif
                                      
                                      
                                      class i2ckeypad {
                                      public:
                                        i2ckeypad(int);
                                        i2ckeypad(int, int, int, int);
                                        char get_key();
                                        void init();
                                        
                                      private:
                                        void pcf8574_write(int, int);
                                        int pcf8574_byte_read(int);
                                      };
                                      
                                      #endif
                                      
                                      AWIA 1 Reply Last reply
                                      0
                                      • karl261K karl261

                                        current code

                                        sketch

                                        #include <Wire.h>
                                        #include <i2ckeypad.h>
                                        
                                        #define ROWS 4
                                        #define COLS 4
                                        
                                        // With A0, A1 and A2 of PCF8574 to ground I2C address is 0x20
                                        #define PCF8574_ADDR 0x38
                                        #define PCF8574_PIN_CONFIG 0xf0
                                        
                                        
                                        i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS, PCF8574_PIN_CONFIG);
                                        
                                        void setup()
                                        {
                                          Serial.begin(9600);
                                        
                                          Wire.begin();
                                        
                                          kpd.init();
                                           
                                        
                                          Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
                                        
                                        //  pcf8574_write(pcf8574_i2c_addr, 0xf0);
                                        
                                        }
                                        
                                        void loop()
                                        {
                                          char key = kpd.get_key();
                                        
                                          if(key != '\0') {
                                                Serial.print(key);
                                          }
                                        }
                                        

                                        .cpp

                                        /*
                                         *  i2ckeypad.cpp v0.1 - keypad/I2C expander interface for Arduino
                                         *
                                         *  Copyright (c) 2009 Angel Sancho <angelitodeb@gmail.com>
                                         *  All rights reserved.
                                         *
                                         *  Original source from keypad v0.3 of Mark Stanley <mstanley@technologist.com>
                                         *  (http://www.arduino.cc/playground/Main/KeypadTutorial)
                                         *
                                         *
                                         *  LICENSE
                                         *  -------
                                         *  This program is free software: you can redistribute it and/or modify
                                         *  it under the terms of the GNU General Public License as published by
                                         *  the Free Software Foundation, either version 3 of the License, or
                                         *  (at your option) any later version.
                                         *  
                                         *  This program is distributed in the hope that it will be useful,
                                         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                                         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                         *  GNU General Public License for more details.
                                         *  
                                         *  You should have received a copy of the GNU General Public License
                                         *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
                                         *
                                         *
                                         *  EXPLANATION
                                         *  -----------
                                         *  This library is designed for use with PCF8574, but can possibly be
                                         *  adapted to other I2C port expanders
                                         *
                                         *  Wiring diagrams for PCF8574 and 4x3 keypad can be found under
                                         *  examples directory. Library runs correctly without cols pull-up
                                         *  resistors but it's better to use it
                                         *
                                         *  You can change pin connections between PCF8574 and keypad under
                                         *  PIN MAPPING section below
                                         *
                                         *  IMPORTANT! You have to call Wire.begin() before init() in your code
                                         *
                                         *  ... and sorry for my poor english!
                                         */
                                        
                                        #include "i2ckeypad.h"
                                        #include <Wire.h>
                                        
                                        //extern "C" {
                                        //  #include "WConstants.h"
                                        //}
                                        
                                        
                                        /*
                                         *  PIN MAPPING
                                         *
                                         *  Here you can change your wire mapping between your keypad and PCF8574
                                         *  Default mapping is for sparkfun 4x3 keypad
                                         */
                                        
                                        #define COL0  2  // P2 of PCF8574, col0 is usually pin 3 of 4x3 keypads
                                        #define COL1  0  // P0 of PCF8574, col1 is usually pin 1 of 4x3 keypads
                                        #define COL2  4  // P4 of PCF8574, col2 is usually pin 5 of 4x3 keypads
                                        #define COL3  7  // sorry, don't have a 4x4 keypad to try it
                                        #define ROW0  1  // P1 of PCF8574, row0 is usually pin 2 of 4x3 keypads
                                        #define ROW1  6  // P6 of PCF8574, row1 is usually pin 7 of 4x3 keypads
                                        #define ROW2  5  // P5 of PCF8574, row2 is usually pin 6 of 4x3 keypads
                                        #define ROW3  3  // P3 of PCF8574, row3 is usually pin 4 of 4x3 keypads
                                        
                                        
                                        /*
                                         *  KEYPAD KEY MAPPING
                                         *
                                         *  Default key mapping for 4x4 keypads, you can change it here if you have or
                                         *  like different keys
                                         */
                                        
                                        const char keymap[4][5] =
                                        {
                                          "123A",
                                          "456B",
                                          "789C",
                                          "*0#D"
                                        };
                                        
                                        
                                        /*
                                         *  VAR AND CONSTANTS DEFINITION. Don't change nothing here
                                         *
                                         */
                                        
                                        // Default row and col pin counts
                                        int num_rows = 4;
                                        int num_cols = 3;
                                        
                                        // PCF8574 i2c address
                                        int pcf8574_i2c_addr;
                                        
                                        // PCF8574 i2c pin configuration (high low)
                                        int pcf8574_i2c_pin_cfg;
                                        
                                        // Current search row
                                        static int row_select;
                                        
                                        // Current data set in PCF8574
                                        static int current_data;
                                        
                                        // Hex byte statement for each port of PCF8574
                                        const int hex_data[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
                                        
                                        // Hex data for each row of keypad in PCF8574
                                        const int pcf8574_row_data[4] = 
                                        {
                                          hex_data[ROW1] | hex_data[ROW2] | hex_data[ROW3] |
                                          hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                          hex_data[ROW0] | hex_data[ROW2] | hex_data[ROW3] |
                                          hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                          hex_data[ROW0] | hex_data[ROW1] | hex_data[ROW3] |
                                          hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                          hex_data[ROW0] | hex_data[ROW1] | hex_data[ROW2] |
                                          hex_data[COL0] | hex_data[COL1] | hex_data[COL2] | hex_data[COL3],
                                        };
                                        
                                        // Hex data for each col of keypad in PCF8574
                                        int col[4] = {hex_data[COL0], hex_data[COL1], hex_data[COL2], hex_data[COL3]};
                                        
                                        
                                        /*
                                         *  CONSTRUCTORS
                                         */
                                        
                                        i2ckeypad::i2ckeypad(int addr)
                                        {
                                          pcf8574_i2c_addr = addr;
                                        }
                                        
                                        i2ckeypad::i2ckeypad(int addr, int r, int c, int pinc)
                                        {
                                          pcf8574_i2c_addr = addr;
                                          num_rows = r;
                                          num_cols = c;
                                          pcf8574_i2c_pin_cfg = pinc;
                                        }
                                        
                                        
                                        /*
                                         *  PUBLIC METHODS
                                         */
                                        
                                        void i2ckeypad::init()
                                        {
                                          // All PCF8574 ports high
                                          pcf8574_write(pcf8574_i2c_addr, pcf8574_i2c_pin_cfg);
                                        
                                          // Start with the first row
                                          row_select = 0;
                                        }
                                        
                                        char i2ckeypad::get_key()
                                        {
                                          static int temp_key;
                                        
                                          int tmp_data;
                                          int r;
                                        
                                          int key = '\0';
                                        
                                          // Search row low
                                          pcf8574_write(pcf8574_i2c_addr, pcf8574_row_data[row_select]);
                                        
                                          for(r=0;r<num_cols;r++) {
                                            // Read pcf8574 port data
                                            tmp_data = pcf8574_byte_read(pcf8574_i2c_addr);
                                        
                                            // XOR to compare obtained data and current data and know
                                            // if some column are low
                                            tmp_data ^= current_data;
                                        
                                            // Key pressed!
                                            if(col[r] == tmp_data) {
                                              temp_key = keymap[row_select][r];
                                              return '\0';
                                            }
                                          }
                                        
                                          // Key was pressed and then released
                                          if((key == '\0') && (temp_key != '\0'))    
                                          {
                                            key = temp_key;
                                            temp_key = '\0';
                                            return key;
                                          }
                                        
                                          // All PCF8574 ports high again
                                          pcf8574_write(pcf8574_i2c_addr, pcf8574_i2c_pin_cfg);
                                        
                                          // Next row
                                          row_select++;
                                          if(row_select == num_rows) {
                                            row_select = 0;
                                          }
                                        
                                          return key;
                                        }
                                        
                                        /*
                                         *  PRIVATE METHODS
                                         */
                                        
                                        void i2ckeypad::pcf8574_write(int addr, int data)
                                        {
                                          current_data = data;
                                        
                                          Wire.beginTransmission(addr);
                                          Wire.write(data);
                                          Wire.endTransmission();
                                        }
                                        
                                        int i2ckeypad::pcf8574_byte_read(int addr)
                                        {
                                          Wire.requestFrom(addr, 1);
                                        
                                          return Wire.read();
                                        }
                                        

                                        .h

                                        #ifndef i2ckeypad_h
                                        #define i2ckeypad_h
                                        
                                        #include <inttypes.h>
                                        
                                        #if ARDUINO >= 100
                                        #include "Arduino.h"
                                        #else
                                        #include "WProgram.h"
                                        #endif
                                        
                                        
                                        class i2ckeypad {
                                        public:
                                          i2ckeypad(int);
                                          i2ckeypad(int, int, int, int);
                                          char get_key();
                                          void init();
                                          
                                        private:
                                          void pcf8574_write(int, int);
                                          int pcf8574_byte_read(int);
                                        };
                                        
                                        #endif
                                        
                                        AWIA Offline
                                        AWIA Offline
                                        AWI
                                        Hero Member
                                        wrote on last edited by AWI
                                        #46

                                        @karl261 I compiled the thing without any errors...
                                        what I did:

                                        • All the files (including the library) in (sub)folder Keypad
                                        • Saved the sketch as Keypad.ino
                                        • Changed <i2ckeypad.h> to "i2ckeypad.h"

                                        p.s. a google search showed that the error occurs with many for no obvious reason...

                                        karl261K 2 Replies Last reply
                                        0
                                        • AWIA AWI

                                          @karl261 I compiled the thing without any errors...
                                          what I did:

                                          • All the files (including the library) in (sub)folder Keypad
                                          • Saved the sketch as Keypad.ino
                                          • Changed <i2ckeypad.h> to "i2ckeypad.h"

                                          p.s. a google search showed that the error occurs with many for no obvious reason...

                                          karl261K Offline
                                          karl261K Offline
                                          karl261
                                          wrote on last edited by
                                          #47

                                          @AWI yes, I checked Google too, but there is now real solution. I can go back to 1.6.5r5 maybe this works.

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          32

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular