ESPhome matrix keypad layout change from ABCD to EFGH and vice versa

Hi,
So, I am using a 4 x 4 matrix keypad for a project. But I like to be able to change the layout of the keys using an automation, boolean or a switch inside HA. For instance change ABCD to EFGH and back. or 1234567890 to other digests or characters. Any suggestions?

Thanks

just create a second keypad in your config that’s identical to the one you have except give this one a new name and ID, also change the keys to letters instead of numbers. You can then create a switch that either read the input from keypad1 or keypad2. You could likely create an automation for example if “*5” then toggle keypad to the other one. This way you can switch back and forth from the keypad itself rather than having to go to HA and toggle a switch.

Ive already tried different methods but nothing worked so far.
I tried creating two different key collectors for each layout, that didn’t work.
The keys are defined in key configuration and cant be modified. So, I tired to have two different key configuration or add the extra digests, that didn’t work either.
Could you be a bit more specific as to what you mean by second keypad?
Thanks

you make a second keypad in your config just like the one you have now except give it a new name, ID, and instead of making the keys (123…) you make the keys (abcd…)

matrix_keypad:
  id: mykeypad
  rows:
    - pin: 21
    - pin: 19
    - pin: 18
    - pin: 5
  columns:
    - pin: 17
    - pin: 16
    - pin: 4
    - pin: 15
  keys: "123A456B789C*0#D"
  has_diodes: false

  id: mykeypad2
  rows:
    - pin: 21
    - pin: 19
    - pin: 18
    - pin: 5
  columns:
    - pin: 17
    - pin: 16
    - pin: 4
    - pin: 15
  keys: "ABCDEFGHIJKL"
  has_diodes: false

you make a second keypad just like the first one except give it a new name/id and change the keys from numbers to letters. This will give you 2 keypads, keypad1 returns numbers and keypad2 returns letters.

Ive tried this but I got an error "Duplicate key “id” ".

matrix_keypad:
 - id: mykeypad
   rows:
     - pin: 21
     - pin: 19
     - pin: 18
     - pin: 5
   columns:
     - pin: 17
     - pin: 16
     - pin: 4
     - pin: 15
   keys: "123A456B789C*0#D"
   has_diodes: false

 - id: mykeypad2
   rows:
     - pin: 21
     - pin: 19
     - pin: 18
     - pin: 5
   columns:
     - pin: 17
     - pin: 16
     - pin: 4
     - pin: 15
   keys: "ABCDEFGHIJKL"
   has_diodes: false

What are you trying to do with a letter keypad? You don’t have the full alphabet so you cant use it as a makeshift keyboard, so whats the point?

Well… if I could get the layout to change I could have full alphabet, that was the idea. I am working on a project to build a box to control HA. My first attempt went pretty well, with OLED screen, a knob, LED lights and a keypad. Then I thought having to type things would make it a lot easier to trigger automation or do more with the box. it works great so far where I type AC and it toggles my AC On/Off.

Oh, I see. I had thought of doing something similar with my keypad but instead of switching to an alphabet, just using numeric codes but, my use case was much more specific to my garage where the keypad is installed and there would just be a few entities to remember codes for. That’s a cool idea though but it seems like it could easily get confusing which layout your using without some kind of external indicator as you’d need at least 3 seperate key collectors to incorporate a usable alphabet. Just throwing this out there if you want it. before going with an actual keypad i made a project that uses a button, rotary encoder, and a 4x20 lcd. The idea was for it to work like a combination lock so it starts at zero and clockwise rotation increases the numbers, and decreses on counter-clockwise. when you stop on a number and push the button it locks that number in on the lcd and then moves to the next space for a new number etc. If the numbers entered match a pre-set code it performs an action based on what code is entered. If you want that code, you could easily modify it to rotate through an alphabet or numbers and you can actually see if your selecting a number or a letter. It fully works, I never moved it off my workbench due to the waterproofing needs i needed because it was going to be installed outdoors.

That’s really cool! could you share it please?

Sorry for some reason it didn’t notify me that you replied.

captive_portal:
globals:
  
- type: int[3]
  restore_value: no  
  id: code
  
- type: int
  restore_value: no
  id: count
  initial_value: '0'



binary_sensor:
  - platform: gpio
    pin:
      number: 14
      inverted: true
      mode:
        input: True
        pullup: true
    id: rotary_push
    on_multi_click:     
    - timing:
       - ON for .1s to 1s
       - OFF for at least 0.1s
    
      then:
         - lambda: |-
             
             ESP_LOGD("CLICK", "%d %f %d", id(count), id(my_rotary_encoder).state, int(id(my_rotary_encoder).state));
             id(code)[id(count)] = id(my_rotary_encoder).state;
             id(count)+=1;
             ESP_LOGD("CLICK", "new count %d", id(count));
             id(lcd).update();
         - if:
             condition:
               lambda: return (id(count) == 3);
             then:
               - delay: 1500ms
               - lambda: |-
                   if ((id(code)[0] == 11) && (id(code)[1] == 22) && (id(code)[2] == 25))                   
                   id(open_door).execute();
                   id(count) = 0;
                   id(lcd).update();
               - sensor.rotary_encoder.set_value:
                  id: my_rotary_encoder
                  value: 0     
    - timing:
      - ON for at least 2s 
      
      then:
           - lambda: |-
              id(count) = 0;
              id(lcd).update();
           - sensor.rotary_encoder.set_value:
               id: my_rotary_encoder
               value: 0 
       

script:
  - id: open_door
    mode: single
    then:
      - homeassistant.service:
         service: "cover.open"
         data:
           entity_id: "cover.barn_overhead2"
     
    



sensor:
  - platform: rotary_encoder
    name: "Combo"
    min_value: 0
    max_value: 100
    id: my_rotary_encoder
    publish_initial_value: true
    restore_mode:
       ALWAYS_ZERO
    on_value:
      - component.update: lcd
    filters:
      throttle: 100ms 

    pin_a: 
      number: 27
      inverted: true
      mode:
        input: true
        pullup: true
      

    pin_b: 
      number: 32
      inverted: true
      mode:
        input: true
        pullup: true    
i2c:
  sda: GPIO19
  scl: GPIO18        
display:
  - platform: lcd_pcf8574
    dimensions: 20x4
    address: 0x27
    id: lcd
    
      
    
    lambda: |-
       ESP_LOGD("DISPLAY", "%d %f %d", id(count), id(my_rotary_encoder).state, int(id(my_rotary_encoder).state));
       it.printf(0, 0, "Enter code: %3d", int(id(my_rotary_encoder).state));
       if (id(count) > 0) it.printf(1, 1, "%03d", id(code)[0]);
       if (id(count) > 1) it.printf(6, 1, "%03d", id(code)[1]);
       if (id(count) > 2) it.printf(11, 1, "%03d", id(code)[2]);

you would have to change it around to make it work for what you are doing but you should be able to just fine. This expects the user to enter 3 integers and you would likely need a different number for different things.

If you want to use it as is and make a digital combination lock, this is where you’d set the code. So here the correct code is 11-22-25.

you could also just duplicate this section and make multiple “if” statements for different codes like this and then depending on which code you enter, you can have different actions happen.

- if:
             condition:
               lambda: return (id(count) == 3);
             then:
               - delay: 1500ms
               - lambda: |-
                   if ((id(code)[0] == 11) && (id(code)[1] == 22) && (id(code)[2] == 25))                   
                   id(open_door).execute();
                   id(count) = 0;
                   id(lcd).update();
               - sensor.rotary_encoder.set_value:
                  id: my_rotary_encoder
                  value: 0     

- if:
             condition:
               lambda: return (id(count) == 3);
             then:
               - delay: 1500ms
               - lambda: |-
                   if ((id(code)[0] == 23) && (id(code)[1] == 62) && (id(code)[2] == 55))                   
                   id(turn_on_lights).execute();
                   id(count) = 0;
                   id(lcd).update();
               - sensor.rotary_encoder.set_value:
                  id: my_rotary_encoder
                  value: 0     

- if:
             condition:
               lambda: return (id(count) == 3);
             then:
               - delay: 1500ms
               - lambda: |-
                   if ((id(code)[0] == 45) && (id(code)[1] == 67) && (id(code)[2] == 78))                   
                   id(do_something_else).execute();
                   id(count) = 0;
                   id(lcd).update();
               - sensor.rotary_encoder.set_value:
                  id: my_rotary_encoder
                  value: 0     

Thank you so much!

no problem. If you don’t mind, I’d love to see what your building. I’ve been struggling to come up with new things to build and i’m always looking for ideas and inspiration even if it isn’t a finished project.


This is the “MyBox” project I am currently working. It’s my first attempt but it needs some adjustments. I shouldn’t have used keypad.
I have created 6 pages for the OLED so far, showing me the status of some sensors from HA. Ive also created some automations to turn On/Off some lights or devices using certain key strokes on the keypad.

The box is a second gen Apple TV that I gutted out. The brain is an EPS32 (30 pin)

that’s cool. I started to do something similar with Display Menu — ESPHome but lost interest in it.