Rotary dial + ESP32

For what it’s worth, a regular piece of ESPHome code (not a custom component, now deprecated) to make use of a the rotary dial of a vintage phone as a sensor. Can be used to trigger actions, etc.

Relevant parts of yaml below:

binary_sensor:
  - platform: gpio
    id: rotary_active
    pin:
      number: 37
      inverted: true
      mode:
        input: true
        pullup: true
    filters:
      delayed_on_off: 50ms
    on_press:
      then:
        - lambda: |-
            id(rotaryCount) = 0;
    on_release:
      then:
        - lambda: |-
            if( id(rotaryCount)>0 ){
              std::string s = id(dialed_number_string).c_str() ;
              int i = (int)id(rotaryCount) % 10 ;    // %10 : pulse count 10 corresponds to dialed number 0
              // publish the dialed number
              id(rotary_dial).publish_state( i ) ;
              // publish the entire dialed number
              s += to_string( i ) ;
              id(dialed_number_string) = s ;
              id(dialed_number).publish_state( id(dialed_number_string) ) ;
            }
        - script.execute: rotary_dial_timer_script

  - platform: gpio
    id: rotary_pulses
    pin:
      number: 39
      inverted: true
      mode:
        input: true
        pullup: true
    filters:
      delayed_on_off: 3ms
    on_press:
      then:
        - lambda: |-
            if( id(rotary_active).state ){
              id(rotaryCount)++;
            }

sensor:
  - platform: template
    name: Rotary Dial
    id: rotary_dial
    update_interval: never
    accuracy_decimals: 0

text_sensor:
  - platform: template
    name: Dialed number
    id: dialed_number
    icon: mdi:numeric
    lambda: |-
      return {};
    update_interval: never
    on_value: 
      then:
        - if:
            condition:
              and:
                - lambda: 'return id(dialed_number).state == "123" ;'
            then:
              - delay: 30ms
              - script.stop: rotary_dial_timer_script
              - script.execute: reset_dialed_number_script
              # insert here the action to trigger

globals:
  - id: dialed_number_string
    type: std::string
    initial_value: ""
    restore_value: false
  - id: rotaryCount
    type: int
    initial_value: '0'
    restore_value: false

script:
  - id: rotary_dial_timer_script
    mode: restart
    then:
      - delay: 12 sec #time-out
      - script.execute: reset_dialed_number_script

  - id: reset_dialed_number_script
    mode: restart
    then:
      - lambda: |-
          id(dialed_number_string) = "" ;
          id(dialed_number).publish_state( id(dialed_number_string) )  ;

This piece of code works with that kind of dial (here, a S63 phone dial).

  • red wire: rotary_pulses / red+white wire : gnd
  • blue wire: rotary_active / blue+white wire : gnd
2 Likes