1

I am developing a robot with raspberry pi model b along with three servo motors. I have two functions which are defined for obtain robot behaviours. In the first function my servos are working well. After completing first function, second function start. But their is problem. My servos are not working at all in the second function. I have attached my code below. I tried for days about this issue. But I couldn't find it out.

import RPi.GPIO as GPIO
import time
import threading
import datetime

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

#set up GPIO pin outputs for servo motors
GPIO.setup(11, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)

#set up pwm for the pins
pwm1 = GPIO.PWM(11, 50)
pwm2 = GPIO.PWM(13, 50)
pwm3 = GPIO.PWM(15, 50)

#set up controlling boolean values
boolean_1 = False
boolean_2= False
boolean_3= False
boolean_4= False

def function3():
    global boolean_1 , pwm3
    pwm3.start(0)
    while boolean_1:
        for i in range(70, 110):
            position = 1./18.*(i)+2
            pwm3.ChangeDutyCycle(position)
            time.sleep(0.015)
        for i in range(110, 70, -1):
            position = 1./18.*(i)+2
            pwm3.ChangeDutyCycle(position)
            time.sleep(0.015)
    for i in range(70, 90):
        position = 1./18.*(i)+2
        pwm3.ChangeDutyCycle(position)
        time.sleep(0.001)
    pwm3.stop()

def function2():
    global boolean_2, pwm1, pwm2
    pwm1.start(0)
    pwm2.start(0)
    while boolean_2:
        for i in range(60, 120):
            position_1 = 1./18.*(i)+2
            position_2 = 1./18.*(180-i)+2
            pwm1.ChangeDutyCycle(position_1 )
            pwm2.ChangeDutyCycle(position_2 )
            time.sleep(0.005)
        for i in range(120, 60, -1):
            position_1 = 1./18.*(i)+2
            position_2 = 1./18.*(180-i)+2
            pwm1.ChangeDutyCycle(position_1 )
            pwm2.ChangeDutyCycle(position_2 )
            time.sleep(0.05)
    pwm1.stop()
    pwm2.stop()

def function1():
    global boolean_1 , boolean_3 , boolean_4 
    t_start = datetime.datetime.now()
    start_time = (round(t_start.microsecond/1000000) + t_start.second + t_start.minute*60 + t_start.hour*3600)
    boolean_1 = True
    t1 = threading.Thread(target = function3, args=())
    t1.start()
    t2 = threading.Thread(target = function5, args=())
    t3 = threading.Thread(target = function4, args=())
    while True:
        t_cur = datetime.datetime.now()
        current_time = (round(t_cur.microsecond/1000000) + t_cur.second + t_cur.minute*60 + t_cur.hour*3600)                  
        if((current_time - start_time) < 10):
            if not boolean_3 :
                boolean_3 = True
                t2.start()
        elif((current_time - start_time) >= 10 and (current_time - start_time) < 20):
            if boolean_3 :
                boolean_3 = False
                t2.join()
            if not boolean_4 :
                boolean_4 = True
                t3.start()
        elif((current_time - start_time) >= 20):
            boolean_4 = False
            t3.join()
            boolean_1 = False
            t1.join()
            break

def function4():
    global boolean_4
    pwm2.start(0)
    while boolean_4:
        for i in range(60, 120):
            position = 1./18.*(180-i)+2
            pwm2.ChangeDutyCycle(position)
            time.sleep(0.001)
        for i in range(120, 60, -1):
            position = 1./18.*(180-i)+2
            pwm2.ChangeDutyCycle(position)
            time.sleep(0.01)
    pwm2.stop()           

def function5():
    global boolean_3
    pwm1.start(0)
    while boolean_3:
        for i in range(60, 120):
            position = 1./18.*(i)+2
            pwm1.ChangeDutyCycle(position)
            time.sleep(0.001)
        for i in range(120, 60, -1):
            position = 1./18.*(i)+2
            pwm1.ChangeDutyCycle(position)
            time.sleep(0.01)
    pwm1.stop()

def function_controll():
    global boolean_2
    t5 = threading.Thread(target = function1, args=())
    t5.start()
    t5.join()
    boolean_2 = True
    function2()
    boolean_2= False

if __name__ == "__main__":
    t1 = threading.Thread(target = function_controll, args=())
    t1.start()
    t1.join()
    GPIO.cleanup()

Here, function3, function4 and function5 are functions use in function1. This might be a very basic thing with servos. But since I new to this stuff i need a help. Any help would be grateful.

I have updated..

Thank you very much !

1
  • @joan Sorry for the mistake, I have updated the code Commented Dec 17, 2018 at 17:45

2 Answers 2

0

I'm the author of pigpio so treat everything I say with all due scepticism.

I think you may have come across a RPi.GPIO issue. There seem to be several problems with the PWM implementation. See https://sourceforge.net/p/raspberry-gpio-python/tickets/

After a while the pulses rather than been sent at 50Hz (standard servo rate) appear to be sent at 1kHz with the actual pulses about a tenth of a millisecond (way shorter than the normal minimum of 1 millisecond). This will totally confuse a servo.

Here is a piscope screen shot showing what happens.

piscope screen shot

There may be a work around if you look through the tickets.

However I think you are going down a dead alley. Software PWM is really not great for servos. When the system gets busy they will start to twitch, get hot, and wear out pretty fast.

I'd be looking for a hardware timed PWM solution. E.g. external hardware, or servoblaster, or my pigpio.

Also there is RPIO.GPIO which is meant to be a "drop in" replacement for RPi.GPIO but adds hardware timed servo pulses. If you have a large investment in code that is certainly worth a look.

2
  • Do i need to change the whole code. I have never used your library before. Is it a my code implementation problem or common problem Commented Dec 17, 2018 at 18:21
  • @iuhettiarachchi I forgot to mention RPIO.GPIO, see end of my edited post.
    – joan
    Commented Dec 17, 2018 at 18:31
0

My suggestion is to use the hardware PWM of BCM2835 chip. The problem is, this chip have only 2 PWM channels, connected to 4 GPIO connector pins. You can control 3 servos, providing only two of them are used in the same time. I described this in http://kempny.stanpol.com.pl/pwm/pwm.php (C language and wiringPi library), unfortunately only in polish. If google translator does not help, please email me.

Your Answer

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

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