Air refreshener ESPHome/Wi-Fi controlled

Automotive door lock actuator in the tank, pulling on the flush lever.

I’ve finalized this topic…
As I said - batteries are removed, power supply via wall charger.
I added button for manual activation or check if all is working.
The on-board blue LED I used as pre-warning blinking (~3 sec. before spray),
to avoid spray in someone eyes, etc.

Here is the code - if someone has some suggestions - please provide proposal for changes/improvement…

#version: BS08122020
esphome:
  name: air_refreshener_bath_small
  platform: ESP8266
  board: esp07

wifi:
  ssid: "My-Wi-Fi"
  password: "12345"
  
# Manual IP
  manual_ip:
    static_ip: 192.168.1.167
    gateway: 192.168.1.1
    subnet: 255.255.255.0
    dns1: 8.8.8.8
    dns2: 8.8.4.4

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Air Refreshener Bath Small"
    password: "12345"
    
captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

switch:
# manual activation/switch in HA
  - platform: gpio
    name: "Air Refreshener Bath Small"
    pin: GPIO12
    id: dc_motor

# on board blue led visual action spray
  - platform: gpio
    name: "On board Blue LED"
    id: onboard_blue_led
    pin:
        number: GPIO2
        mode: OUTPUT
        inverted: true
    restore_mode: ALWAYS_OFF
    
  - platform: template
    id: air_refreshener_single_click_spray_small_bathroom
    name: "Air Refreshener Single Click Spray Small Bathroom"
    lambda: |-
      if (id(dc_motor).state) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
        - switch.turn_on: dc_motor
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: dc_motor
        - switch.turn_off: onboard_blue_led
        
# Define scrip 'spray 2 times with LED blinking'
script:
   - id: spray_2_times
     mode: restart
     then:
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - delay: 0.5s
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - delay: 0.5s
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - switch.turn_on: dc_motor
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: dc_motor
        - switch.turn_off: onboard_blue_led
        - delay: 15s
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - delay: 0.5s
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - delay: 0.5s
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: onboard_blue_led
        - switch.turn_on: dc_motor
        - switch.turn_on: onboard_blue_led
        - delay: 0.5s
        - switch.turn_off: dc_motor
        - switch.turn_off: onboard_blue_led
        
binary_sensor:
# Manual button to activate manually spray
# On board blue LED will blik 5 times befor spray
# then dc_motor is activated,
# then 15s break and the same is repeated
  - platform: gpio
    name: "Air Refreshener Manual Button Spray Small Bathroom"
    pin:
      number: GPIO14
      mode: input_pullup
      inverted: true
    internal: true
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - script.execute: spray_2_times

# Timer part, scheduled for work-days and holiday-days
# WORKING DAYS
time:      
# the night cycle, working days, 03:00
  - platform: sntp
    id: cycle_0_wd_night
    on_time:
      - seconds: 0
        minutes: 00
        hours: 3
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the morning cycle, working days, 05:25
  - platform: sntp
    id: cycle_1_wd_morning
    on_time:
      - seconds: 0
        minutes: 25
        hours: 5
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the morning cycle, working days, 06:00		  
  - platform: sntp
    id: cycle_2_wd_morning
    on_time:
      - seconds: 0
        minutes: 0
        hours: 6
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the morning cycle, working days, 06:15	  
  - platform: sntp
    id: cycle_3_wd_morning
    on_time:
      - seconds: 0
        minutes: 15
        hours: 6
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times          
# the morning cycle, working days, 06:45	  
  - platform: sntp
    id: cycle_4_wd_morning
    on_time:
      - seconds: 0
        minutes: 45
        hours: 6
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times             
# the afternoon cycle, working days, 15:30		  
  - platform: sntp
    id: cycle_5_wd_afternoon
    on_time:
      - seconds: 0
        minutes: 30
        hours: 15
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the afternoon cycle, working days, 16:00		  
  - platform: sntp
    id: cycle_6_wd_afternoon
    on_time:
      - seconds: 0
        minutes: 00
        hours: 16
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the evening cycle, working days, 18:30
  - platform: sntp
    id: cycle_7_wd_evening
    on_time:
      - seconds: 0
        minutes: 30
        hours: 18
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the evening cycle, working days, 19:00
  - platform: sntp
    id: cycle_8_wd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 19
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the evening cycle, working days, 20:00
  - platform: sntp
    id: cycle_9_wd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 20
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the evening cycle, working days, 21:00
  - platform: sntp
    id: cycle_10_wd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 21
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# the evening cycle, working days, 22:15
  - platform: sntp
    id: cycle_11_wd_evening
    on_time:
      - seconds: 0
        minutes: 15
        hours: 22
        days_of_week: MON-FRI
        then:
          - script.execute: spray_2_times
# HOLIDAY DAYS
# the night cycle, holiday days, 03:00
  - platform: sntp
    id: cycle_12_hd_night
    on_time:
      - seconds: 0
        minutes: 00
        hours: 3
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the morning cycle, holiday days, 07:25
  - platform: sntp
    id: cycle_13_hd_morning
    on_time:
      - seconds: 0
        minutes: 25
        hours: 7
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the morning cycle, holiday days, 06:00		  
  - platform: sntp
    id: cycle_14_hd_morning
    on_time:
      - seconds: 0
        minutes: 0
        hours: 6
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the morning cycle, holiday days, 08:30  
  - platform: sntp
    id: cycle_15_hd_morning
    on_time:
      - seconds: 0
        minutes: 30
        hours: 8
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times          
# the morning cycle, holiday days, 09:15	  
  - platform: sntp
    id: cycle_16_hd_morning
    on_time:
      - seconds: 0
        minutes: 15
        hours: 9
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times  
# the morning cycle, holiday days, 11:15	  
  - platform: sntp
    id: cycle_17_hd_morning
    on_time:
      - seconds: 0
        minutes: 15
        hours: 11
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the afternoon cycle, holiday days, 14:00		  
  - platform: sntp
    id: cycle_18_hd_afternoon
    on_time:
      - seconds: 0
        minutes: 00
        hours: 14
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the afternoon cycle, holiday days, 16:00		  
  - platform: sntp
    id: cycle_19_hd_afternoon
    on_time:
      - seconds: 0
        minutes: 00
        hours: 16
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 18:30
  - platform: sntp
    id: cycle_20_hd_evening
    on_time:
      - seconds: 0
        minutes: 30
        hours: 18
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 19:00
  - platform: sntp
    id: cycle_21_hd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 19
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 20:00
  - platform: sntp
    id: cycle_22_hd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 20
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 21:00
  - platform: sntp
    id: cycle_23_hd_evening
    on_time:
      - seconds: 0
        minutes: 00
        hours: 21
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 22:15
  - platform: sntp
    id: cycle_24_hd_evening
    on_time:
      - seconds: 0
        minutes: 15
        hours: 22
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
# the evening cycle, holiday days, 23:15
  - platform: sntp
    id: cycle_25_hd_evening
    on_time:
      - seconds: 0
        minutes: 15
        hours: 23
        days_of_week: SAT-SUN
        then:
          - script.execute: spray_2_times
#END

Hi there

Could you detail the circuit? I’m interested on achieving the same as you did!

Best regards
HP

The circuit diagram is in 1st post…
There are only 4 electronic components.
R1 is 0,33kOhm.

What other detailed info you want?

My version of the implementation of an air freshener with the determination of the presence of a balloon and the determination of the aroma of the balloon. Watch the video.

Smart air freshener with detection of the presence of the balloon and the aroma of the balloon

The project used an automatic air freshener from the company Glade with replaceable cylinders at 2400 spray, which I redesigned and integrated into the Home Assistant.

What opportunities does the redesigned air freshener provide?

  1. Spray the balloon with Home Assistant automation tools
  2. Spray the balloon with a built-in timer
  3. Sensor pressing the physical button on the air fresheners
  4. Determines the presence of a balloon
  5. Determines the aroma of the balloon
  6. It is possible to keep a record of the consumption of each cylinder or only a single one
  7. Write your own code for sensor output and air freshener control in ESP Home
  8. Battery powered
  9. Mains power

Necessary details

1) Glade Automatic Air Freshener - 1 pc.

2) ESP Wemos mini - 1 pc.

3) Step-down voltage converter GSMIN MP1584EN DC-DC - 1 pc.

4) Resistors, of any nominal value from 100 kOhm to 2 ohms, you can take a set of resistors

5) Connector power socket 5.5mm - 1 pc.

6) Conductive glue for heating threads (with nickel) NANOPROTECH - N pieces to choose from

7) Any power supply 9V 2A (9V/2A), plug 5.5*2.1mm

8) Neodymium Powerful Flat Magnets Rectangles Rosmagnit 5x5x1 mm - 20pcs

9) Print the platform on a 3D printer


Filling on ESP Wemos mini firmware to control the air freshener

In ESP Home, we create a project to control the air freshener
substitutions:
  board_name: Glade Air Freshener
  node_name: airfreshener_glade

esphome:
  name: ${node_name}
  comment: WeMos D1 Mini Air Freshener

esp8266:
  board: d1_mini
  framework:
    version: recommended
  restore_from_flash: true #We save the preset settings. After a reboot, the settings are not reset

#Resetting data to the flash drive to reduce the wear of the flash drive
preferences:
  flash_write_interval: 1min

#Wi-Fi credentials for connecting the board to the home network
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: on

#If there is no connection with WiFi, then the access point will rise
  ap:
    ssid: !secret ap_esp_ssid
    password: !secret ap_esp_password

#The captive portal dE SP Home component is a backup mechanism in case the connection to the configured Wi-Fi fails.
captive_portal:

#Web server
web_server:
  port: 80

#Logging
logger:

#OTA и API
ota:
  password: "esphome"
api:
  password: "esphome"



#####################################################################################
################################## Sensor###########################################
sensor:
#Wi Fi signal strength sensor
  - platform: wifi_signal
    name: ${board_name} RSSI WiFi
    icon: mdi:wifi
    update_interval: 60s

#Hidden sensor uptime in seconds
  - platform: uptime
    name: ${board_name} Uptime sec
    icon: mdi:clock-outline
    id: uptime_sensor
    internal: False 

#Hidden service sensor for pressing the button
  - platform: template
    name: ${board_name} Click Spray
    id: sensor_spray
    internal: True

#Resistance sensor for measuring resistance and determining the cylinder
#Component Analog To Digital Sensor
  - platform: adc
    pin: A0
    id: source_sensor
    name: ${board_name} ADS
    update_interval: 1s
  - platform: resistance
    id: resistance_sensor
    sensor: source_sensor
    configuration: DOWNSTREAM
    resistor: 5.6kOhm
    name: ${board_name} Resistance
    on_value:
      - if:
          condition:
            - lambda: |-
                return int(x) < 30;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "The balloon is removed"
      - if:
          condition:
            - lambda: |-
                return int(x) < 140 and int(x) > 100;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "Peony and juicy berries"
      - if:
          condition:
            - lambda: |-
                return int(x) < 190 and int(x) > 160;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "Freshness of the morning"
      - if:
          condition:
            - lambda: |-
                return int(x) < 270 and int(x) > 250;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "Freshness of linen"
      - if:
          condition:
            - lambda: |-
                return int(x) < 650 and int(x) > 620;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "Ocean Oasis"
      - if:
          condition:
            - lambda: |-
                return int(x) > 2000;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "Japanese Garden"
#####################################################################################
################################## Бинарный сенсор ##################################
binary_sensor:
#Hidden service binary sensor for pressing the button, which, when the status changes, turns on/off the switch for spraying
  - platform: gpio
    pin: GPIO13
    name: ${board_name} Spray Button Press
    internal: True
    id: button_sensor_d7
    on_press:
      then:
        - switch.turn_on: switch_spray
        - delay: 5s
        - switch.turn_off: switch_spray

#A visible binary sensor for status display, this can be useful in Home Assistant automation
  - platform: template
    name: ${board_name} Status Spray
    icon: mdi:spray
    id: switch_state
    internal: false
    lambda: |-
      if (id(switch_spray).state) {
        return true;
      } else {
        return false;
      }
#####################################################################################
################################## Switch######################################
#Hidden service switch for spraying
switch:
  - platform: gpio
    pin: GPIO15
    name: ${board_name} Single Click Spray
    internal: True
    id: switch_spray
    icon: mdi:spray
    restore_mode: ALWAYS_OFF
    on_turn_on:
      then:  
        - number.set:
            id: id_counter
            value: !lambda |-
              return ((id(id_counter).state)+1);
        - sensor.template.publish:
            id: sensor_spray
            state: !lambda return id(switch_spray).state;
        - component.update: id_counter
        - delay: 10s
        - switch.turn_off: switch_spray
        - sensor.template.publish:
            id: sensor_spray
            state: !lambda return id(switch_spray).state;

#####################################################################################
###################################### Counter ######################################
number:
#Spray counter
  - platform: template
    name: ${board_name} Counter
    icon: mdi:counter
    id: id_counter
    restore_value: true
    update_interval: 30s
    min_value: 0
    max_value: 3000
    mode: box #slider/box
    step: 1
    optimistic: true

#####################################################################################
####################################### Button ######################################
button:
#Reboot
  - platform: restart
    name: ${board_name} Restart
    icon: mdi:restart

#Spray
  - platform: template
    name: ${board_name} Click Spray
    icon: mdi:spray
    on_press:
      then:  
       - switch.turn_on: switch_spray

#Reset the counter
  - platform: template
    name: ${board_name} Reset Counters Spray
    icon: mdi:restart
    on_press:
      then:  
        - number.set:
            id: id_counter
            value: 0
#####################################################################################
################################### Text Sensor################################
#Uptime
text_sensor:
  - platform: template
    name: ${board_name} Ballon
    icon: mdi:spray
    id: ballon
    update_interval: 60s

  - platform: wifi_info
    ip_address:
      name: ${board_name} IP
#    ssid:
#      name: ${board_name} SSID
#    bssid:
#      name: ${board_name} BSSID
#    mac_address:
#      name: ${board_name} Mac
#    scan_results:
#      name: ${board_name} Latest_Scan_Results

#####################################################################################
####################################### Time #######################################
time:
  - platform: sntp
    id: sntp_time
    timezone: Europe/Moscow


Assembling

We extract the native board and do as in the diagram

Increased native board size for understanding.

  1. The yellow wire is soldered to the second leg on the right to the chip. This wire is soldered to the esp board, to the contacts D8 GPIO15
  2. Solder the resistor to 1K, and a green wire to it. Next, solder the wire from the resistor to the esp board, to the contacts D7 GPIO13
  3. The orange wire is +3.3V and soldered to the esp board, to the contacts +3.3V
  4. The blue wire is soldered to the esp board, to the GND contacts
  5. We cut the contact on the track of the textolite coming from the yellow wire. This is necessary so that we can control the dispenser when the timer is off

  1. We cut the spring with the + contact for the battery compartment and solder the diode (highlighted with a red marker). Why is this necessary? This is necessary to protect the esp board from failure for the reason that if there are batteries in the air freshener and we still connect it to the network, then the chip responsible for voltage conversion will not try to charge the battery and will not get very hot, which can fail. The diode prevents current from flowing in the opposite direction to the battery

  1. On the esp, we solder wires and a 5.1 kOhm resistor (there are resistors included) or 5.6 kOhm. The resistor is soldered to contacts A0 and GND. Solder two wires from contacts A0 (brown wire in the photo) and to +3.3V (black wire in the photo) and stretch to the very bottom of the cylinder body

  1. We install a 5.5 mm power socket connector into the housing hole, solder the wires from the connector to the step-down of the GSMIN MP1584EN DC-DC voltage converter, and from the step-down to the esp. On the step-down we set the voltage 2.2-3.3v and check the motor power. If the lever is pressed hard into the limiter and starts to crack, then lower the voltage to 2.2V and it should be so that the lever rests against the limiter and at the same time the motor does not have enough strength to push the lever and could not wear off the gears

  1. We stretch two wires from contacts A 0 and +3.3V and apply hot glue so that there is a circle in the center and an arc at the back. I filled the wires with conductive glue - there is no need to solder.

Important! Conductive glue does not fit well on the smooth surface of the plastic, it begins to swell and peel off. Be sure to sand or scratch the smooth surface thoroughly, then the conductive glue will lie perfectly


  1. We print the platform on a 3d printer, install 2 magnets to enhance magnetization, install a resistor in the hole and cover it with conductive glue. The consumption of conductive glue can be different, therefore, if there are several platforms, it is advisable to take several pieces. I took 5 packs. The STL model can be downloaded from here

image

Hi,

I have made my glade automatic air freshener smart.
The PCB from the post above was not the same as mine.
The decision was to use only the motor of the air freshener and get rid of everything else.

My approach:

  • Control the dc motor by ESP8266 with DRV8833 h-bridge and a dc/dc buck converter in between to get 3V.
  • Providing a “Spray” button to trigger the air freshener.

The repository is an early state.

Things to do:

  • Add Spray counter to ESPHome YAML
  • Add internal boolean to avoid a new spray command while moving the motor
  • Create automations like:
    • Spray if toilet was flushed and door opened and closed again (will be handled in Home Assistant)
    • Time scheduled spraying at Home Assistant

The documentation can be found here:

1 Like

Very interesting… How do you monitor flushing the toilet? What kind of sensor do you use…?

Currently it is not installed but I think an aqara door and window sensor should to the job.
The sensor will be opened, two reeds installed in parallel instead of one. The magnets will be attached at the toilet button plate.
I do not know how it works at your home, ours look like that:

O.K. You have build-in wall system… In my case all is ceramic and outside (old fashioned type)…

Very interesting. My region only have this version of the Glade and I have search the net to find one post that said it is not possible to quite challenging to to be smart. I used a relay to intercept the power. Where it turns on for a 10 seconds, spray and shut off. Works great, but it still uses the battery.

I would imagine my unit version would still work with your setup since it does have a motor? The little issue I would run into is that the unit is quite small and I will need to mount everything outside.

I think it should be possible.
Not sure which motor is used (could also be 1.5V).
First you should measure the voltage on the motor when spraying.
DRV8833 can operate with 3-10V.

I’ve found the post. The shell is different but the internal looks the same down the the pc board. The post said the motor to be 2.5v.

Hey there,
alternative approach: I’ve hacked an Air Wick Freshmatic. The 3D printed cover houses the ESP, which switches the device on and off by acting as a AA battery. The device releases one spray 15 seconds after the power was connected. Assuming this delay is acceptable to you the electrical solution and further HA automation is rather simple. Works perfectly in two bathrooms for the last two years. :slight_smile:

Happy to share details and code.

1 Like

Very clean setup. For this particular Air Wick model without converting it to smart, how does it activate?

For my model, it spray once motion is detected AND every 30 minutes( something like that) throughout the day whether it detects motion or not. Marketing scheme to make you constantly buy the refills.

This particular model sprays 15 seconds after activated, then every 30min or so. This initial spray is what made this clean setup possible. From Home Assistant I simply turn the device on when no one is in the room and turn it off some time after. If you ignore the 15 seconds you could say I have direct control of it spraying.

Here’s a simplified copy of my rules.

On:

  - trigger:
      - platform: state
        entity_id: binary_sensor.bathroom_door
        to: "off"
        for:
          seconds: 5
    condition:
      - condition: state
        entity_id: light.bathroom
        state: "off"
    action:
      - service: switch.turn_on
        entity_id: switch.airwick

Off:

  - trigger:
      - platform: state
        entity_id: light.bathroom
        to: "on"
      - platform: state
        entity_id: switch.airwick
        to: "on"
        for:
          minutes: 30
    condition:
      - condition: state
        entity_id: switch.airwick
        state: "on"
    action:
      - service: switch.turn_off
        entity_id: switch.airwick

No magic on the ESP either. It’s running standard Tasmota with one “Switch” GPIO.

Hey Daxi,

This is great, thank you so much for sharing. I’d love to see more pictures of the inside as well as the reassembled Air freshener. For example, where does the USB cable enter the air freshener?

Thank you in advance!

@rodri2566: Project is updated and pictures of the final air freshener added:

  • Added spray counter as readonly data
  • Added reset button to set spraycounter back to 0
  • Changed timings for glade cans (previously worked fine for airwick cans but not glade cans)
  • Spraying logic moved to a script
  • Avoiding multiple script executions by the button which avoids motor stress.
  • Moved ESPHome YAML to its own file

Thank you so much for sharing @Daxi . It’s a very elegant solution, both in terms of hardware as well as software.

Hey Daxi.
Added a lock to your code at the end of 2400 sprays and the presence of a spray in the can.

script:

  - id: do_spray
    then:
      - if:
          condition: 
            lambda: 'return id(spray_counter).state < 2400 ;'
          then:
            - number.increment: spray_counter
            - component.update: spray_counter
            - fan.hbridge.brake: spray_motor
            - fan.turn_on:
                id: spray_motor
                speed: 80
                direction: forward
            - delay: 350ms
            - fan.hbridge.brake: spray_motor
            - fan.turn_on:
                id: spray_motor
                speed: 80
                direction: reverse
            - delay: 200ms
            - fan.hbridge.brake: spray_motor
            - fan.turn_off:
                id: spray_motor
            - delay: 500ms

sensor:

  - platform: template
    name: ${friendly_name} ${friendly_suffix_counter}
    icon: mdi:counter
    id: spray_counter_template
    state_class: measurement
    unit_of_measurement: ""
    accuracy_decimals: 0
    lambda: |-
      return id(spray_counter).state;
    update_interval: 1s
    on_value:
      - if:
          condition:
            - lambda: |-
                return id(spray_counter).state <= 2399 ;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "The balloon is ok"
      - if:
          condition:
            - lambda: |-
                return id(spray_counter).state >= 2400 ;
          then:
            - text_sensor.template.publish:
                id: ballon
                state: "empty balloon"


text_sensor:

  - platform: template
    name: ${friendly_suffix_button_spray} Ballon
    icon: mdi:spray
    id: ballon
    update_interval: 60s

If it is not, change the GPIO pins at forward and reverse pin.

I’ve received all my parts and have done soldering. When I test the motor, it is turning the opposite direction. I am confused of what to change as I have tried a couple of ways, but the motor does not change direction.

I have tried swapping the gpio pins on the d1 mini. Change the pin id labels in the config file.