This is to do with driving an R/C Servo from a Raspberry Pi.  I have this 
working with motors driving my car, but this takes two pins at opposing 
polarities for change of direction. An R/C servo works differently: Instead of 
two wires of opposite polarity for the motor direction there is only one 
control wire using pulse width modulation between 1 and 2 milliseconds for full 
control.

An HTML program calls the python program to drive the car as here:

--------- ---------

#  2018-04-05 Modified from Les Pounder program to handle two motors
# one for steering and one for motion
# steering is Left = 10, right = 11
# changing it trying to add Turn for motor control
# 2018-10-31 changing toggle LED to stop motors

from flask import Flask, render_template
from gpiozero import LED, Motor
from time import sleep

# led = LED(25)
motor = Motor(forward=18, backward=23)
turn  = Motor(forward=10, backward=11)


app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/motor-stop/')
def on():
    motor.stop()
    return render_template('index.html')

@app.route('/motor-forwards/')
# 31/1/19 modified to test double push on button to stop. see notes.
def motorforwards():
    if motor.value == 0:
        motor.forward()
    elif motor.value > 0:
        motor.stop()
    return render_template('index.html')

@app.route('/motor-backwards/')
def motorbackwards():
    motor.backward()
    return render_template('index.html')

@app.route('/motor-left/')
def motorleft():
    turn.forward()
    sleep(1)
    turn.stop()
    return render_template('index.html')

@app.route('/motor-right/')
def motorright():
    turn.backward()
    sleep(1)
    turn.stop()
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')


----------- ---------- ------------

A python test program that drives the Servos, and works. This quite long 
because the guy that wrote it documented every step.

---------- ---------- -------------


# This gives us control of the Raspberry Pi's pins.
import RPi.GPIO as GPIO

# This is only used for time delays... standard Python stuff.
import time

# Tell i which pin number we'll  be using to refer to the GPIO pains.
# We will use the physical pin ordering.
GPIO.setmode(GPIO.BOARD)

# We will tell the Broadcom CPU which pins do what.
# There are many pins and most have up to 5 different functions,
# each with a default.  Check the pinout to find non-specialized
# "GPIO" pins.  We'll use P!-Pin_11 (using BOARD reference),
# which is the same as GPIO17 (Broadcom / BCM reference).
# We need our pin to use the GPIO digital output function, so we just
# tell it to designate this pin for OUTPUT.
pin_number = 18
GPIO.setup(pin_number, GPIO.OUT)

# Now we can use PWM on pin 18.  It's software PWM, so don't expect perfect
# results.  Linux is a multitasking OS so other processes could interrupt
# the process which generate the PWM signal at any time.
# Raspberry Pi has a hardware PWm channel, but this Pythong library
# does not yet support it.
frequency_hertz = 50
pwm = GPIO.PWM(pin_number, frequency_hertz)


# How to position a servo?  All servos are pretty much the same.
# Send repeated purses of an absolute duration (not a relative duty cycle)
# between 0.40 ms and 2.5 ms in duration.  A single pulse will only move it
# a short distance in the desired direction.  Repeated pulses will continue
# its movement and then once it arrives at the specified position it will
# insruct the motor to forcefully hold its position.
left_position = 0.40
right_position = 2.5
middle_position = (right_position - left_position) / 2 + left_position

# I'll store a sequence of positions for use in a loop later on.
positionList = [left_position, middle_position, right_position, middle_position]

# total number of milliseconds in a a cycle.  Given this, we will then
# know both how long we want to pulse in this cycle and how long tghe
# cycle itself is.  That is all we need to calculate a duty cycle as
# a percentage.
ms_per_cycle = 1000 / frequency_hertz

frequency_hertz = 50
pwm = GPIO.PWM(pin_number, frequency_hertz)


# How to position a servo?  All servos are pretty much the same.
# Send repeated purses of an absolute duration (not a relative duty cycle)
# between 0.40 ms and 2.5 ms in duration.  A single pulse will only move it
# a short distance in the desired direction.  Repeated pulses will continue
# its movement and then once it arrives at the specified position it will
# insruct the motor to forcefully hold its position.
left_position = 0.40
right_position = 2.5
middle_position = (right_position - left_position) / 2 + left_position

# I'll store a sequence of positions for use in a loop later on.
positionList = [left_position, middle_position, right_position, middle_position]

# total number of milliseconds in a a cycle.  Given this, we will then
# know both how long we want to pulse in this cycle and how long tghe
# cycle itself is.  That is all we need to calculate a duty cycle as
# a percentage.
ms_per_cycle = 1000 / frequency_hertz

# Iterate through the positions sequence 3 times.
for i in range(3):
        # This sequence contains positions from left to right
        # and then back again.  Move the motor to each position in order.
        for position in positionList:
                duty_cycle_percentage = position * 100 / ms_per_cycle
                print("Position: " + str(position))
                print("Duty Cycle: " + str(duty_cycle_percentage))
                print("")
                pwm.start(duty_cycle_percentage)
                time.sleep(.5)

# Done.  Terminate all signals and relax the motor.
pwm.stop()

# We have shut all our stuff down but we should do a complete
# close on all GPIO stuff.  There's only one copy of real hardware.
# We need to be polite and put it back the way we found it.
GPIO.cleanup()

----------- ----------- ---------------

Combining the two for my test. This seems to work, the print statement works, 
but the servo's don't move.  Both programs use pin 18, despite any comments 
otherwise.

------------- ------------ -------------

# 2019-06-11 This is a combining of RC car-7 that works and adding the code
# from 
https://github.com/NUNUG/scary-gadgets-1/blob/master/raspberrypi-src/servocontrol.py
# to use PWM to drive servo motors appropriately for an R/C glider
# one GPIO for up/down and one for left/right.
# steering is Left = 10, Up/down is 18
# also to use the actual pin numbers rather than the functional number.
from flask import Flask, render_template

# This gives us control of the Raspberry Pi's pins.
import RPi.GPIO as GPIO

# This is only used for time delays... standard Python stuff.
import time

# Tell it which pin number we'll  be using to refer to the GPIO pains.
# We will use the physical pin ordering.
GPIO.setmode(GPIO.BOARD)


u_d_pin_no = 18
GPIO.setup(u_d_pin_no, GPIO.OUT)

# Now we can use PWM on pin 18.

frequency_hertz = 50
pwm = GPIO.PWM(u_d_pin_no, frequency_hertz)


# How to position a servo?  All servos are pretty much the same.
# Send repeated purses of an absolute duration (not a relative duty cycle)
# between 0.40 ms and 2.5 ms in duration.  A single pulse will only move it
# a short distance in the desired direction.  Repeated pulses will continue
# its movement and then once it arrives at the specified position it will
# insruct the motor to forcefully hold its position.
left_position = 0.40
right_position = 2.5
middle_position = (right_position - left_position) / 2 + left_position

# total number of milliseconds in a cycle.  Given this, we will then
# know both how long we want to pulse in this cycle and how long the
# cycle itself is.  That is all we need to calculate a duty cycle as
# a percentage.
ms_per_cycle = 1000 / frequency_hertz

# now lets get into Flask

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/motor-stop/')
def on():
    # motor.stop()
    duty_cycle_percentage = middle_position * 100 / ms_per_cycle
    print("Duty Cycle: " + str(duty_cycle_percentage))
    print("")
    pwm.start(duty_cycle_percentage)
    time.sleep(.5)
    # Done.  Terminate all signals and relax the motor.
    pwm.stop()
    return render_template('index.html')


@app.route('/motor-forwards/')
# First test pwm 17/6/19
def motorforwards():
    duty_cycle_percentage = left_position * 100 / ms_per_cycle
    print("Duty Cycle: " + str(duty_cycle_percentage))
    print("")
    pwm.start(duty_cycle_percentage)
    time.sleep(.5)
    # Done.  Terminate all signals and relax the motor.
    pwm.stop()
    return render_template('index.html')

@app.route('/motor-backwards/')
def motorbackwards():
    duty_cycle_percentage = right_position * 100 / ms_per_cycle
    print("Duty Cycle: " + str(duty_cycle_percentage))
    print("")
    pwm.start(duty_cycle_percentage)
    time.sleep(.5)
    # Done.  Terminate all signals and relax the motor.
    pwm.stop()
    return render_template('index.html')



# We have shut all our stuff down but we should do a complete
# close on all GPIO stuff.  There's only one copy of real hardware.
# We need to be polite and put it back the way we found it.

GPIO.cleanup()


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

------------- ------------- -------------

Hope that it is not too long. Any suggestions welcome,

Peter M.

--
 Next meeting: BEC, Bournemouth, Tuesday, 2019-07-02 20:00
 Check to whom you are replying
 Meetings, mailing list, IRC, ...  http://dorset.lug.org.uk/
 New thread, don't hijack:  mailto:dorset@mailman.lug.org.uk

Reply via email to