How do I use a predfined GPIO's in a lambda?

I want to use a predefined output inside a lambda, but l’m getting type mismatch errors in the C++ compiler when setting the output low or high.

There is one GPIO set up for the buzzer, and another for the alarm enable switch. They are defined in the output section as local (inaccessible from homeassistant) GPIO’s. The definitions are as follows:

# buzzer (local)
  - platform: gpio
    pin: 26
    id: buzzer


# Alarm enable switch (local)
  - platform: gpio
    pin:
      number: 19
      inverted: true
      mode:
        input: true
        pullup: true
     
    id: enable_switch

Can these predefined GPIO’s be accessed somehow from within a lambda or must you use the Arduino DigitalWrite/DigitalRead functions within the lambda to control these outputs. I can’t find anything in the documentation or any examples of how to access GPIO’s which are predefined outside of the lambda

The errors are as follows:

sp32-bedroom-clock.yaml: In lambda function:
esp32-bedroom-clock.yaml:105:18: error: invalid conversion from 'int' to 'esphome::gpio::GPIOBinaryOutput*' [-fpermissive]
esp32-bedroom-clock.yaml:109:61: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
*** [.pioenvs/bedroom_clock/src/main.cpp.o] Error 1

The offending line 105 contains:

id(buzzer) = 1;

The offending line 109 contains:

        if(id(enable_switch) != id(last_enable_switch_state)){

The entire script is posted below:

substitutions:
  entity_prefix: bedroom clock

esphome:
  name: bedroom_clock
  platform: ESP32
  board: nodemcu-32s

wifi:
  # use_address: esp32-clock
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
    - ssid: !secret sec_wifi_ssid
      password: !secret sec_wifi_password
    
web_server:
  port: 80
  # https://esphome.io/components/web_server.html
  auth:
    username: admin
    password: !secret esphome_web_password


logger:
  level: INFO

globals:
    # Alarm clock hour
  - id: ac_hour
    type: int
    restore_value: yes
    initial_value: '6'

    # Alarm clock minute
  - id: ac_minute
    type: int
    restore_value: yes
    initial_value: '30'
  
  - id: ac_triggered
    type: bool
    restore_value: no
    initial_value: 'false'

  - id: last_enable_switch_state
    type: bool
    restore_value: no
    initial_value: 'false'
    
    


api:
  password: !secret esphome_api_password
  encryption:
    key: !secret api_key
  services:
    # Service to set the alarm clock time
    - service: set_alarm_time
      variables:
        alarm_clock_hour: int
        alarm_clock_minute: int
      then:
        # Copy the input variables to thier global counterparts
        - globals.set:
            id: ac_hour
            value: !lambda 'return alarm_clock_hour;'
        - globals.set:
            id: ac_minute
            value: !lambda 'return alarm_clock_minute;'
        - logger.log:
            format: "Homeassistant has set alarm hour: %d and alarm minute: %d"
            args: [ 'id(ac_hour)', 'id(ac_minute)' ]
            level: INFO
        
ota:
  password: !secret esphome_ota_password
  # https://esphome.io/components/ota

time:
  - platform: sntp
    timezone: America/Los_Angeles
    id: sntp_time
 
display:
  platform: tm1638
  clk_pin: 18
  dio_pin: 23
  stb_pin: 5
  update_interval: 500ms
  # Alarm clock logic
  lambda: |-
      static int i = 0;
      auto now = id(sntp_time).now();
      i++;
      // Clock display update and buzzer logic
      if ((i % 2) == 0){
        it.strftime("%H.%M", now);
        id(buzzer) = 0;  
      }
      else{
        it.strftime("%H%M",now);
        if(id(ac_triggered) == true)
          id(buzzer) = 1;
      }
      // Enable/disable logic
      if(id(enable_switch)){
        if(id(enable_switch) != id(last_enable_switch_state)){
          ESP_LOGI("custom", "Alarm Clock Enabled");
          id(last_enable_switch_state) = true;
        }
        // Trigger logic
        if(now.is_valid())
         if(now.hour == id(ac_hour))
           if(now.minute == id(ac_minute))
             if(now.second == 0)
               if(id(ac_triggered) == false){
                 id(ac_triggered) = true;
                 ESP_LOGI("custom", "Alarm Clock Triggered");
               }
      }
      else{
        if(id(last_enable_switch_state) != false){
          id(ac_triggered) = false;
          id(last_enable_switch_state) = false;
          ESP_LOGI("custom", "Alarm Clock Disabled");
        }
      }
           
# LED Outputs start at 0
output:
  - platform: tm1638
    id: 'led0'
    led: 0
  - platform: tm1638
    id: 'led1'
    led: 1
  - platform: tm1638
    id: 'led2'
    led: 2
  - platform: tm1638
    id: 'led3'
    led: 3
  - platform: tm1638
    id: 'led4'
    led: 4
  - platform: tm1638
    id: 'led5'
    led: 5
  - platform: tm1638
    id: 'led6'
    led: 6
  - platform: tm1638
    id: 'led7'
    led: 7

# buzzer (local)
  - platform: gpio
    pin: 26
    id: buzzer


# Alarm enable switch (local)
  - platform: gpio
    pin:
      number: 19
      inverted: true
      mode:
        input: true
        pullup: true
     
    id: enable_switch



switch:
  - platform: output
    name: ${entity_prefix} LED 0
    output: 'led0'
  - platform: output
    name: ${entity_prefix} LED 1
    output: 'led1'
  - platform: output
    name: ${entity_prefix} LED 2
    output: 'led2'
  - platform: output
    name: ${entity_prefix} LED 3
    output: 'led3'
  - platform: output
    name: ${entity_prefix} LED 4
    output: 'led4'
  - platform: output
    name: ${entity_prefix} LED 5
    output: 'led5'
  - platform: output
    name: ${entity_prefix} LED 6
    output: 'led6'
  - platform: output
    name: ${entity_prefix} LED 7
    output: 'led7'



# Keys start at 0
binary_sensor:
  - platform: tm1638
    name: ${entity_prefix} Key 0
    id: key0
    key: 0
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 1
    id: key1
    key: 1
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 2
    id: key2
    key: 2
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 3
    id: key3
    key: 3
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 4
    id: key4
    key: 4
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 5
    id: key5
    key: 5
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 6
    id: key6
    key: 6
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 7
    id: key7
    key: 7
    filters:
      - delayed_on: 10ms

A couple of comments/thoughts (but I don’t know the answer, just things which might be worth trying):

Some other things you can try:

  • Sometimes you maybe need a .state on the end like below (I forget when you do/don’t)
    id(last_enable_switch_state).state
  • Sometimes wrapping things in a int() may help.

I’ll play around with the suggestions and see if they help.

For the buzzer:

id(buzzer).turn_on();

For the enable_switch:

        if(id(enable_switch).state != id(last_enable_switch_state)){

@ Zoogara: Thanks. That was the majority of the issue. They’re objects not integers. I also had to move
the alarm enable from the output section to the binary sensors section. The script is now working as a rudimentary alarm clock with the 8 pushbuttons and LED’s for controlling things from the HA side using an automation.

The updated code is attached below:

#
# Alarm clock using 8 Digit TM1638 LED and key module and one level quad MOSFER level shifter module to convert 
# ESP32 3.3V logic levels to 5V logic levels needed by the LED and Key module.
#
# The alarm clock requires 2 additional pins for the following:
# 1. A pin an external buzzer driven by an NPN transistor and a 4.7K base current limiting resistor.
# 2. A pin for the external alarm enable slide or toggle switch.
# 
#
#
# Note: All secrets stored in a separate secrets file named secrets.yaml
#
# 

substitutions:
  entity_prefix: bedroom clock
  tm1638_clk_pin: '18'
  tm1638_dio_pin: '23'
  tm1638_stb_pin: '5'
  buzzer_pin: '26'
  alarm_enable_switch_pin: '22'



esphome:
  name: esp32-bedroom-clock
  platform: ESP32
  board: nodemcu-32s

wifi:
  use_address: esp32-bedroom-clock
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
    - ssid: !secret sec_wifi_ssid
      password: !secret sec_wifi_password
    
web_server:
  port: 80
  # https://esphome.io/components/web_server.html
  auth:
    username: admin
    password: !secret esphome_web_password


logger:
  level: INFO

globals:
    # Alarm clock hour
  - id: ac_hour
    type: int
    restore_value: yes
    initial_value: '6' # Default hour

    # Alarm clock minute
  - id: ac_minute
    type: int
    restore_value: yes
    initial_value: '30' # Default Munute

  - id: alarm_state
    type: int
    restore_value: yes
    initial_value: "0" # Alarm state defaults to 0 (idle)

api:
  password: !secret esphome_api_password
  encryption:
    key: !secret api_key
  services:
    # Service to set the alarm clock time
    - service: set_alarm_time
      variables:
        alarm_clock_hour: int
        alarm_clock_minute: int
      then:
        # Copy the input variables to thier global counterparts
        - globals.set:
            id: ac_hour
            value: !lambda 'return alarm_clock_hour;'
        - globals.set:
            id: ac_minute
            value: !lambda 'return alarm_clock_minute;'
        - logger.log:
            format: "Homeassistant has set alarm hour: %d and alarm minute: %d"
            args: [ 'id(ac_hour)', 'id(ac_minute)' ]
            level: INFO
        
ota:
  password: !secret esphome_ota_password
  # https://esphome.io/components/ota

time:
  - platform: sntp
    timezone: America/Los_Angeles
    id: sntp_time
 
display:
  platform: tm1638
  clk_pin: ${tm1638_clk_pin}
  dio_pin: ${tm1638_dio_pin}
  stb_pin: ${tm1638_stb_pin}
  update_interval: 500ms
  # Alarm clock logic
  lambda: |-
      static int i = 0;
      auto now = id(sntp_time).now();
      i++;
      // Clock display update and buzzer logic
      if ((i % 2) == 0){
        it.strftime("%H.%M", now);
        id(buzzer).turn_off();  
      }
      else{
        it.strftime("%H%M",now);
        if(id(alarm_state) == 2) // Triggered?
          id(buzzer).turn_on();
      }
      // Alarm state machine
      switch(id(alarm_state)){
        case 0: // Idle
          if(id(enable_switch).state){
              ESP_LOGI("custom", "Alarm Clock Armed");
              id(alarm_state) = 1; // Move to armed state
          } 
          break;
        case 1: // Armed
          if(id(enable_switch).state == false){  // If disabled, move to idle state
             ESP_LOGI("custom", "Alarm Clock Disarmed 1");
             id(alarm_state) = 0;
             break;
          }
          // Test current time against alarm clock time
          if(now.is_valid()){
            if(now.hour == id(ac_hour)){
              if(now.minute == id(ac_minute)){
                if(now.second == 0){
                  ESP_LOGI("custom", "Alarm Clock Triggered");
                  id(alarm_state) = 2; // Move to triggered state
                }
              }
            }
          }
          break;  
        case 2: // Triggered
          if(id(enable_switch).state == false){
             id(alarm_state) = 0; // Move to idle state
             ESP_LOGI("custom", "Alarm Clock Disarmed 2");
             break;
          }
          break;
        default:
          id(alarm_state) = 0; // Move to idle state
          break;
      }
      
   
           
# LED Outputs start at 0
output:
  - platform: tm1638
    id: 'led0'
    led: 0
  - platform: tm1638
    id: 'led1'
    led: 1
  - platform: tm1638
    id: 'led2'
    led: 2
  - platform: tm1638
    id: 'led3'
    led: 3
  - platform: tm1638
    id: 'led4'
    led: 4
  - platform: tm1638
    id: 'led5'
    led: 5
  - platform: tm1638
    id: 'led6'
    led: 6
  - platform: tm1638
    id: 'led7'
    led: 7

# buzzer (local)
  - platform: gpio
    pin: ${buzzer_pin}
    id: buzzer



switch:
  - platform: output
    name: ${entity_prefix} LED 0
    output: 'led0'
  - platform: output
    name: ${entity_prefix} LED 1
    output: 'led1'
  - platform: output
    name: ${entity_prefix} LED 2
    output: 'led2'
  - platform: output
    name: ${entity_prefix} LED 3
    output: 'led3'
  - platform: output
    name: ${entity_prefix} LED 4
    output: 'led4'
  - platform: output
    name: ${entity_prefix} LED 5
    output: 'led5'
  - platform: output
    name: ${entity_prefix} LED 6
    output: 'led6'
  - platform: output
    name: ${entity_prefix} LED 7
    output: 'led7'



# Keys start at 0
binary_sensor:
  - platform: tm1638
    name: ${entity_prefix} Key 0
    id: key0
    key: 0
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 1
    id: key1
    key: 1
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 2
    id: key2
    key: 2
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 3
    id: key3
    key: 3
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 4
    id: key4
    key: 4
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 5
    id: key5
    key: 5
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 6
    id: key6
    key: 6
    filters:
      - delayed_on: 10ms
  - platform: tm1638
    name: ${entity_prefix} Key 7
    id: key7
    key: 7
    filters:
      - delayed_on: 10ms
  # Alarm enable switch
  - platform: gpio
    name: ${entity_prefix} Alarm Enable switch
    pin:
      number: ${alarm_enable_switch_pin}
      inverted: true
      mode:
        input: true
        pullup: true
    filters:
      - delayed_on: 10ms   
    id: enable_switch

2 Likes