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      : [email protected]
# 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?

6

1 Answer 1

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 CYCLE. duty 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

l298n pwm mode pin

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.


Part 3 - Understanding the python code to turn servo using AdaFruit PCA9685 PWM Controller Library]

My answer is coming to end. The OP should now have a rough idea of how to use the Rpi's four GPIO pins in output mode and two GPIO pins in PWM mode to change direction and speed of the Mars Rover.

The OP also asks about the turn.py code which is different from the motor.py code explained here. What causes confusion is the both codes use PWM: motor.py using GPIO pins in PMW mode, turn.py, on the other hand, uses the AdaFruit PCA968 PWM controller library to turn the three servos (car direction, supersonic sensor, and Rpi camera).

Adeept Mars Rober turn.py [Using AdaFruit PCM9685 PWM Controller Library]

The code turn.py is simple and easy to understand, because all the complex code of PCM9685 is hidden in the library functions which is off topic, therefore not touched here..


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      : [email protected]
# 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()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.