Uncategorized

L298N PWM speed control

Asked 
Active today
Viewed 44 times
0

I am unable to understand parts of the code

#!/usr/bin/python3
# File name   : motor.py
# Description : Control Motors 
# Website     : www.adeept.com
# E-mail      : support@adeept.com
# Author      : William
# Date        : 2018/10/12

import RPi.GPIO as GPIO
import time
# motor_EN_A: Pin7  |  motor_EN_B: Pin11
# motor_A:  Pin8,Pin10    |  motor_B: Pin13,Pin12

Motor_A_EN    = 4
Motor_B_EN    = 17

Motor_A_Pin1  = 14
Motor_A_Pin2  = 15
Motor_B_Pin1  = 27
Motor_B_Pin2  = 18

Dir_forward   = 0
Dir_backward  = 1

pwm_A = 0
pwm_B = 0

def setup():#Motor initialization
    global pwm_A, pwm_B
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Motor_A_EN, GPIO.OUT)
    GPIO.setup(Motor_B_EN, GPIO.OUT)
    GPIO.setup(Motor_A_Pin1, GPIO.OUT)
    GPIO.setup(Motor_A_Pin2, GPIO.OUT)
    GPIO.setup(Motor_B_Pin1, GPIO.OUT)
    GPIO.setup(Motor_B_Pin2, GPIO.OUT)
    try:
        pwm_A = GPIO.PWM(Motor_A_EN, 1000)
        pwm_B = GPIO.PWM(Motor_B_EN, 1000)
    except:
        pass

def motorStop():#Motor stops
    GPIO.output(Motor_A_Pin1, GPIO.LOW)
    GPIO.output(Motor_A_Pin2, GPIO.LOW)
    GPIO.output(Motor_B_Pin1, GPIO.LOW)
    GPIO.output(Motor_B_Pin2, GPIO.LOW)
    GPIO.output(Motor_A_EN, GPIO.LOW)
    GPIO.output(Motor_B_EN, GPIO.LOW)

def motor_right(status, direction, speed):#Motor 2 positive and negative rotation
    global  pwm_B
    if status == 0: # stop
        motorStop()
    else:
        if direction == Dir_forward:
            GPIO.output(Motor_B_Pin1, GPIO.HIGH)
            GPIO.output(Motor_B_Pin2, GPIO.LOW)
            pwm_B.start(100)
            pwm_B.ChangeDutyCycle(speed)
        elif direction == Dir_backward:
            GPIO.output(Motor_B_Pin1, GPIO.LOW)
            GPIO.output(Motor_B_Pin2, GPIO.HIGH)
            pwm_B.start(0)
            pwm_B.ChangeDutyCycle(speed)

def motor_left(status, direction, speed):#Motor 1 positive and negative rotation
    global pwm_A
    if status == 0: # stop
        motorStop()
    else:
        if direction == Dir_forward:#
            GPIO.output(Motor_A_Pin1, GPIO.HIGH)
            GPIO.output(Motor_A_Pin2, GPIO.LOW)
            pwm_A.start(100)
            pwm_A.ChangeDutyCycle(speed)
        elif direction == Dir_backward:
            GPIO.output(Motor_A_Pin1, GPIO.LOW)
            GPIO.output(Motor_A_Pin2, GPIO.HIGH)
            pwm_A.start(0)
            pwm_A.ChangeDutyCycle(speed)
    return direction


def destroy():
    motorStop()
    GPIO.cleanup()             # Release resource


try:
    pass
except KeyboardInterrupt:
    destroy()

Here is the link to the entire project, please check this:

What is the meaning of the lines :

  • pwm_A = GPIO.PWM(Motor_A_EN, 1000)
  • pwm_B = GPIO.PWM(Motor_B_EN, 1000)
        def motor_left(status, direction, speed):#Motor 1 positive and negative rotation
            global pwm_A
            if status == 0: # stop
                motorStop()
            else:
                if direction == Dir_forward:#
                    GPIO.output(Motor_A_Pin1, GPIO.HIGH)
                    GPIO.output(Motor_A_Pin2, GPIO.LOW)
                    pwm_A.start(100)
                    pwm_A.ChangeDutyCycle(speed)
                elif direction == Dir_backward:
                    GPIO.output(Motor_A_Pin1, GPIO.LOW)
                    GPIO.output(Motor_A_Pin2, GPIO.HIGH)
                    pwm_A.start(0)
                    pwm_A.ChangeDutyCycle(speed)
            return direction

What is the meaning of status, direction, speed in the function declaration?

Also pwm.changeDutyCycle(speed), What is the speed?

 New contributor

1

Answer

Part 1 – Over simplified explanation of the L298N Dual Bridge Motor Driver

Now let us first look at the picture below.


pwm etc


(1.1) Suppose the switches SW1 and Sw2 are in their positions as shown. The electric current will flow from +12V, following the little pink arrows, passing through the coil, I mean the motor coil, and the motor will turn happily non stop.

(1.2) Now if you flip SW1 to left, and keep SW2 stay in its current position, then +12V has no way (circuit) to pass current, and no current in coil, so the motor stops.

(1.3) Now if you repeatedly flip SW1 to right for one second, then left for one second, then right, then left, … Then you will find motor turns for one second, then stops for one seconds, and so on.

(1.4) So in one minute, you are doing left, right, left, right, … ie, you are repeating the two second action 30 times per minute. The scientists call this how many times per minute or per seconds “FREQUENCY“.

Frequency can be very high, eg 1,000 times (cycles) per second, which has a special name called “Hertz” or “Hz“. And like the unit metre, you can have km for kilo-meter, same for kHz, MHz etc.

(1.5) Now what is duty cycle? Suppose you flip SW1 to left for one second, then right for three seconds, then the percentage of current on, or motor moving is 1 second / (1 + 3) seconds = 1/4 = 25%. Then we say 20% DUTY CYCLEduty cycle

(1.6) Now what about speed? If you use a stop watch to count how many motor “turns” or “revolutions” are there in one minute, then that is “SPEED“, say 3,600 revolutions per minute or 3,600 rpm.

(1.7) Now finally, PWM, which means Pulse Width Modulation. I would suggest you to ask Lady Ada of AdaFruit (See Ref 2 below), because I don’t know how to explain PWM using my broken English.


Part 2 – Understanding the python code to move motor change speed

In Part 1, we explained how to flip SW1 to pass current 25% of the time (duty cycle = 25%). We can also using other duty cycle, say 50%, to turn the motor clockwise faster. By the same token, to turn motor counter clockwise and change speed, we change the duty cycle of SW2. In the real L298N, the lazy EE guys do not change the duty cycle of SW1 and SW2 separately. Instead, they use a “main” switch called “Enable” switch, to enable or disable both switches SW1 and SW2 AT THE SAME TIME, as illustrated below.

pwm speed control

Referring to the schematic above,

(1) SW1, SW2 (actually In1, In2, connected to two Rpi GPIO pins in output mode) are used to turn motor A clockwise or counter clockwise.

(2) Enable switch (actually EnA, connected to one GPIO pin in PWM mode) is used to change speed of motor A by changing the duty cycle of enabling the SW1. SW2 at the same time.

The full listing of the Mars Rover’s real code motor.py is given in Appendix A below. I might later, sprinkle a couple of comments to make the code more newbie friendly to read and understand. The OP, if impatient to wait, can DIY figuring out how the code works.


References

(1) PWM (Pulse Width Modulation) – Wikipedia

(2) Adafruit PCA9685 16-Channel PWM / Servo Controller Tutorial – Lady Ada

(3) Hertz -Wikipedia

(4) Heinrich Hertz – Wikipedia

Appendices

Appendix A – Motor.py to control speed of left and right motors, using two GPIO pins as PWM pins

# File name   : motor.py
# https://github.com/adeept/Adeept_PiCar-B/blob/master/server/motor.py

#!/usr/bin/python3
# File name   : motor.py
# Description : Control Motors 
# Website     : www.adeept.com
# E-mail      : support@adeept.com
# Author      : William
# Date        : 2018/10/12

import RPi.GPIO as GPIO
import time

# motor_EN_A: Pin7         |  motor_EN_B: Pin11
# motor_A:  Pin8, Pin10    |  motor_B: Pin13, Pin12

Motor_A_EN    = 4
Motor_B_EN    = 17

Motor_A_Pin1  = 14
Motor_A_Pin2  = 15
Motor_B_Pin1  = 27
Motor_B_Pin2  = 18

Dir_forward   = 0
Dir_backward  = 1

pwm_A = 0
pwm_B = 0

def setup():#Motor initialization
    global pwm_A, pwm_B
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Motor_A_EN, GPIO.OUT)
    GPIO.setup(Motor_B_EN, GPIO.OUT)
    GPIO.setup(Motor_A_Pin1, GPIO.OUT)
    GPIO.setup(Motor_A_Pin2, GPIO.OUT)
    GPIO.setup(Motor_B_Pin1, GPIO.OUT)
    GPIO.setup(Motor_B_Pin2, GPIO.OUT)
    try:
        pwm_A = GPIO.PWM(Motor_A_EN, 1000)
        pwm_B = GPIO.PWM(Motor_B_EN, 1000)
    except:
        pass

def motorStop():#Motor stops
    GPIO.output(Motor_A_Pin1, GPIO.LOW)
    GPIO.output(Motor_A_Pin2, GPIO.LOW)
    GPIO.output(Motor_B_Pin1, GPIO.LOW)
    GPIO.output(Motor_B_Pin2, GPIO.LOW)
    GPIO.output(Motor_A_EN, GPIO.LOW)
    GPIO.output(Motor_B_EN, GPIO.LOW)

def motor_right(status, direction, speed):#Motor 2 positive and negative rotation
    global  pwm_B
    if status == 0: # stop
        motorStop()
    else:
        if direction == Dir_forward:
            GPIO.output(Motor_B_Pin1, GPIO.HIGH)
            GPIO.output(Motor_B_Pin2, GPIO.LOW)
            pwm_B.start(100)
            pwm_B.ChangeDutyCycle(speed)
        elif direction == Dir_backward:
            GPIO.output(Motor_B_Pin1, GPIO.LOW)
            GPIO.output(Motor_B_Pin2, GPIO.HIGH)
            pwm_B.start(0)
            pwm_B.ChangeDutyCycle(speed)

def motor_left(status, direction, speed):# Motor 1 positive and negative rotation
    global pwm_A
    if status == 0: # stop
        motorStop()
    else:
        if direction == Dir_forward:#
            GPIO.output(Motor_A_Pin1, GPIO.HIGH)
            GPIO.output(Motor_A_Pin2, GPIO.LOW)
            pwm_A.start(100)
            pwm_A.ChangeDutyCycle(speed)
        elif direction == Dir_backward:
            GPIO.output(Motor_A_Pin1, GPIO.LOW)
            GPIO.output(Motor_A_Pin2, GPIO.HIGH)
            pwm_A.start(0)
            pwm_A.ChangeDutyCycle(speed)
    return direction


def destroy():
    motorStop()
    GPIO.cleanup()             # Release resource


try:
    pass
except KeyboardInterrupt:
    destroy()

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: