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