Motor speed controller - what am I missing?

I have an ESP32 using GPIO19 into an L298N PWM controller.

Config is as below:

output:
  - platform: ledc
    pin: 19
    id: fish_feed_motor

script:
  - id: run_motor
    then:
      - output.set_level:
          id: fish_feed_motor
          level: 10%
      - output.ledc.set_frequency:
          id: fish_feed_motor
          frequency: 500Hz
      - output.turn_on: fish_feed_motor
      - binary_sensor.template.publish:
          id: feed_motor_running
          state: ON

When I turn the ouput on, the motor runs.

However, changing level and frequency values, in the config above, makes no difference to motor speed.

Am I missing something obvious here?

Looking at the docs on that motor controller, it seems that you need at least two GPIO signals to vary speed, but your code seems to use only one.

There’s only three pins:

Forward, reverse and speed control.

Which docs have you seen?

This is it being used with Arduino.

I saw this one:

And I see that it would appear that with your device only one signal would be needed for variable-speed one-direction. So I’m stumped. Sorry.

So, I assume that GPIO19 is connected to Enable A and you haven’t connected anything to Input 1 or Input 2? My understanding was that with the L298N module if you neither set Input 1 or Input 2 to HIGH then the motor should not go anywhere. So that might be something to further investigate.

I have just recently built a pool chlorinator pump with a L298N connected to an ESP32, and can share my configuration for comparison:

output:
  - platform: ledc  # or esp8266_pwm if on ESP8266
    pin: GPIO25
    id: motor_speed_pin
  - platform: gpio
    pin: GPIO26
    id: motor_direction_1_pin
  - platform: gpio
    pin: GPIO27
    id: motor_direction_2_pin

switch:
  - platform: template
    name: "Motor"
    id: motor
    icon: "mdi:chemical-weapon"
    turn_on_action:
      # Clockwise direction:
      - output.turn_off: motor_direction_1_pin
      - output.turn_on: motor_direction_2_pin
      - delay: 500ms
      - output.set_level:
          id: motor_speed_pin
          level: 90%
      - switch.template.publish:
          id: motor
          state: ON
    turn_off_action:
      - output.turn_off: motor_direction_1_pin
      - output.turn_off: motor_direction_2_pin
      - output.turn_off: motor_speed_pin
      - switch.template.publish:
          id: motor
          state: OFF

In my case, I noticed that I cannot go below about 70% with my particular motor under load, otherwise it wouldn’t start at all. I haven’t actually changed the frequency at all.

Thanks for the reply.

IN1 is high and the motor runs. However, I have no control over the speed. It always runs 100%, regardless of what I set frequency or level at.

Is the frequency something you would adjust on a motor? I thought it was a fixed value base on the motor specs. Have you tried use an adjustable pwm output to change the values on the fly? Speed fan should allow you to ramp the motor up/down via a slider.

1 Like

Frequency should be set to whatever the L298N recommends. Its docs will probably say something to the effect of “frequency doesn’t matter, ideally set it between here and here.”
That’s because varying the frequency is not what controls the motor speed.

What matters is the PWM ratio, a.k.a. the duty-cycle of the PWM; how much time the pulse is on versus off.
Your motor may in fact be slowing down when you vary the PWM duty cycle, but if there isn’t any load on it you may not notice the change.

Thank you, @glyndon, I’ll take a look at that in the morning.

There’s an L293 arriving tomorrow. I’ll see how I get on with that.

No, not necessarily. I’m just trying to get a response of some kind at the moment.

I’ve just hooked up a scope to GPIO19 and the output just goes to 3.3V when I ask the motor to run. No sign of PWM!

I’ve now changed over to using the fan: component and have full control of the speed all the way down to 20% of max.

Thank you, @Mikefila, for pointing me in that direction.

The issue I have now is the automating of speed control.

I have the motor (“fan”) configured as below:

output:
  - platform: ledc
    pin: 19
    id: fish_feed_motor

fan:
  - platform: speed
    output: fish_feed_motor
    name: "Fish feed motor"
    speed_count: 10
    id: feed_motor

My run script is:

script:
  - id: run_motor
    then:
      - fan.turn_on: 
          id: feed_motor
          speed: 10

I need to be able to control the speed from the front end using an input_number and have tried this:

      - fan.turn_on: 
          id: feed_motor
          speed: !lambda 'return id(feed_rate);'

but it does not change the speed. Speed is always 100%.

Hard coding the speed makes no difference either, however, using the front-end fan component slider does.

Additionally, on reboot of the ESP32, the fan speed returns to 100%.

Any ideas?

Solved!

Whist the Speed Fan option was working to a degree, it was a bit of a fudge.

Going back to my original post, using output.turn_on was the issue. This sets the output to ‘on’, ignoring any PWM setting and the motor runs at 100%.

Just using output.set_level runs the output at the required PWM rate and output.turn_off stops it.

1 Like

I run a bunch of PC fans with the speed fan component and it’s the same deal, turn_on will bring the fan to 100%. You have to call fan.set_percentage, then you can supply a value from 0-100.

Yes, I realise that now. I need the motor to always start at the same speed, hence Fan being a bit of a fudge for me.

Thank you for your help. I appreciate it.

1 Like

At the request of @mofonics, here’s the config that works for me.

I’m using an L293D to drive one motor.

Define the pins:

output:
  - platform: ledc
    pin: 19
    id: fish_feed_motor_pwm
  
  - platform: 
    pin: 18
    id: enable_motor

Start the motor: (This is part of a longer script. I’ve just included the relevant parts. The !lambda can be replaced by a float).

script:
  - id: run_motor
    then:
      - output.set_level:
          id: fish_feed_motor_pwm
          level: !lambda 'return id(feed_rate);'

Stop the motor: (I use another script here).

script:
  - id: stop_motor
    then:
      - output.turn_off: fish_feed_motor_pwm

Pretty simple now that I know what I’m doing!

1 Like

Thank you, @ashscott!