1

iam new to raspberry pi and i got an error while a running servo motor in my object detection script i need to run the servo whenever my if condition is true so the same pin run multiple times if condition satisfies i have done giving servoPIN = 22 GPIO.setmode(GPIO.BCM) GPIO.setup(servoPIN, GPIO.OUT) out of the for loop but doesn't work

Here is the part of the code all import functions are given on top of code(full script :https://github.com/aswinr22/waste-model/blob/master/picamera1.py)

for i in range (classes.size):

    if(classes[0][i] == 2 and scores[0][i]>0.5):

      servoPIN = 22
      GPIO.setmode(GPIO.BCM)
      GPIO.setup(servoPIN, GPIO.OUT)
      p = GPIO.PWM(servoPIN, 50)  #this line shows the error
      p.start(2.5) # Initialization
      try:

        p.ChangeDutyCycle(5)
        time.sleep(4)
        p.ChangeDutyCycle(10)
        time.sleep(4)
      except KeyboardInterrupt:
        p.stop()
      except:
          #print ("exception")

    GPIO.cleanup()

output:(motor turns on and immediately showing below error)

Traceback (most recent call last):
  File "Object_detection_picamera.py", line 150, in <module>
    p = GPIO.PWM(servoPIN, 50) # GPIO 17 for PWM with 50Hz
RuntimeError: A PWM object already exists for this GPIO channel

I dont know why this happening please help me

tlfong01
  • 4,384
  • 3
  • 9
  • 23
rah
  • 11
  • 3
  • Can I cut irrelevant details to make it as simple as possible, as below? count = 0; while count < 4: { keep positiong servo; sleep 20 mS;}; count = count + 1; – tlfong01 May 12 '19 at 01:28
  • where should i use this and how its work – rah May 12 '19 at 04:30
  • Let me see. I am a servo newbie, but Rpi python ninja. You are on the other side of the mirror, a servo ninja, Rpi newbie. Perhaps we can learn together to fix the problem. Now watch my answer. :) – tlfong01 May 12 '19 at 06:03

2 Answers2

1

Question

For loop to move servo BCM mode GPIO pin #22 does not work. Why?

Short Answer

Well, I think you are using the wrong pin. BCM GPIO Pin #22 cannot do PWM. See the chart in the long answer below.

Long Answer

I suggest to first write the following little test function.

 def sequentialMoveServo(positionList)
    for position in positionList
       if (position > 0) AND (position < 180)
           moveServo(position)
       else
           pass
    return

Then we can the function like below:

sequentialMoveServo([+30, +45, -20, +180, +230])

The servo should move sequentially to the positions as below:

30, 45, and 150 degrees, skipping -20 and +230 degrees

Servo research notes

I read the tutorial "Raspberry Pi Servo Motor Control" and find everything OK. The tutorial uses the TowerPro MG996R servo. I remember I also used the same servo a couple of years ago, using Arduino. I am going to search my junk box to find one.

I luckily found one MG996R. I then skimmed the datasheet and find it OK. I moved to tutorials by SparkFun, SourceForge, and Electronic Wing, and found them good. The AdaFruit's tutorials as usual are for Arduino guys. So I skipped Lady Ada, ...

I found ElectronicWing's picture on PWM pins assignment very good. So I borrowed them and pasted here.

servo picture

I found Rpi ahs 4 PWM pins. I decided to use Pin 18 to test the water. Below is the hardware setup.

servo motor hardware setup

Now I have debugged a python program to do the following.

  1. Set GPIO pin 18 high for 2 seconds, to switch on Blue LED to full brightness.

  2. Set the same GPIO pin 18 to output PWM of 1kHz, 50% duty cycle, to switch on/off Blue LED to result half brightness.

# Servo_test32 tlfong01 2019may12hkt1506 ***
# Raspbian stretch 2019apr08, Python 3.5.3

import RPi.GPIO as GPIO
from time import sleep

# *** GPIO Housekeeping Functions ***

def setupGpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    return

def cleanupGpio():
    GPIO.cleanup()
    return

# *** GPIO Input/Output Mode Setup and High/Low Level Output ***

def setGpioPinLowLevel(gpioPinNum):
    lowLevel = 0
    GPIO.output(gpioPinNum, lowLevel)
    return

def setGpioPinHighLevel(gpioPinNum):
    highLevel = 1
    GPIO.output(gpioPinNum, highLevel)
    return

def setGpioPinOutputMode(gpioPinNum):
    GPIO.setup(gpioPinNum, GPIO.OUT)
    setGpioPinLowLevel(gpioPinNum)
    return

# *** GPIO PWM Mode Setup and PWM Output ***

def setGpioPinPwmMode(gpioPinNum, frequency):
    pwmPinObject = GPIO.PWM(gpioPinNum, frequency)
    return pwmPinObject

def pwmPinChangeFrequency(pwmPinObject, frequency):
    pwmPinObject.ChangeFrequency(frequency)
    return

def pwmPinChangeDutyCycle(pwmPinObject, dutyCycle):
    pwmPinObject.ChangeDutyCycle(dutyCycle)
    return

def pwmPinStart(pwmPinObject):
    initDutyCycle = 50
    pwmPinObject.start(initDutyCycle)
    return

def pwmPinStop(pwmPinObject):
    pwmPinObject.stop()
    return

# *** Test Functions ***

def setHighLevelGpioPin18():
    print('  Begin setHighLevelGpioPin18, ...')
    gpioPinNum   = 18
    sleepSeconds =  2    
    setupGpio()
    setGpioPinOutputMode(gpioPinNum)
    setGpioPinHighLevel(gpioPinNum)
    sleep(sleepSeconds)
    cleanupGpio()
    print('  End setHighLevelGpioPin18, ...\r\n')
    return

def setPwmModeGpioPin18():
    print('  Begin setPwmModeGpioPin18, ...')
    
    gpioPinNum   =   18
    sleepSeconds =   10
    frequency    = 1000
    dutyCycle    =   50

    setupGpio()
    setGpioPinOutputMode(gpioPinNum)
    
    pwmPinObject = setGpioPinPwmMode(gpioPinNum, frequency)
    pwmPinStart(pwmPinObject)
    pwmPinChangeFrequency(pwmPinObject, frequency)
    pwmPinChangeDutyCycle(pwmPinObject, dutyCycle)
    sleep(sleepSeconds)
    pwmPinObject.stop()
    cleanupGpio()   

    print('  End   setPwmModeGpioPin18, ...\r\n')

    return

# *** Main ***

print('Begin testing, ...\r\n')
setHighLevelGpioPin18()
setPwmModeGpioPin18()
print('End   testing.')

# *** End of program ***

'''
Sample Output - 2019may12hkt1319
>>> 
 RESTART: /home/pi/Python Programs/Python_Programs/test1198/servo_test31_2019may1201.py 
Begin testing, ...

  Begin setHighLevelGpioPin18, ...
  End setHighLevelGpioPin18, ...

  Begin setPwmModeGpioPin18, ...
  End   setPwmModeGpioPin18, ...

End   testing.
>>> 

>>> 


'''

The blue LED switch on full and half bright. So far so good. I am going to use a scope to check out if the PWM waveform is clean and sharp.

Ah, Sunday afternoon tea time, see you later, ... :)

Now I am checking out the timing requirements of the servo. servo timing

Now I know that the timing for servo to move to middle position is 50Hz, 7%, 1.4mS. So I wrote the test function below, and checked the output.

def servoPwmBasicTimingTestGpioPin18():
    print('  Begin servoPwmBasicTimingTestGpioPin18, ...')

    gpioPinNum         =   18
    sleepSeconds       =  120
    frequency          =   50
    dutyCycle          =    7

    setupGpio()
    setGpioPinOutputMode(gpioPinNum)

    pwmPinObject = setGpioPinPwmMode(gpioPinNum, frequency)
    pwmPinStart(pwmPinObject)
    pwmPinChangeFrequency(pwmPinObject, frequency)
    pwmPinChangeDutyCycle(pwmPinObject, dutyCycle)

    sleep(sleepSeconds)

    pwmPinObject.stop()
    cleanupGpio()   

    print('  End   servoPwmBasicTimingTestGpioPin18, ...\r\n')

    return

Pin18 PWM output looks good.

servo timing 03

Now I can implement the following condition/action table

Condition Action Table

  1. Middle condition = servo moves to Middle action

  2. Leftmost = servo moves to LeftMost action

  3. RightMost condition = servo moves to RightMost action

I have written a little program to loop the above conditions, as show in the following youTube.

Condition Servo Action Program YouTube Demo

/ servo research notes to continue, ...

References

Raspberry Pi Servo Motor control - Rpi Tutorials

Servo MG996R Datasheet - TowerPro

Python (RPi.GPIO) API - SparkFun

Using PWM in RPi.GPIO - SourceForge

Raspberry Pi PWM Generation using Python and C - ElectronicWing

Servo Tutorial - Lady Ada

PWM Tutorial - Lady Ada

Servo Motors Using Arduino - AdaFruit

tlfong01
  • 4,384
  • 3
  • 9
  • 23
  • okay i will try and let you know – rah May 12 '19 at 06:29
  • No hurry. I am a slow learner. I will first read the servo tutorials and then do some elementary experiments. You might like to remind me if I am making any servo newbie silly mistakes. – tlfong01 May 12 '19 at 06:35
  • Now I have completed all the servo functions that enables me to start any servo movement (action) according to a condition (command). You may like to let me know what are the specific "conditions" and the corresponding servo movements. I am going to eat. See you tomorrow. Have a nice weekend. – tlfong01 May 12 '19 at 09:40
0

The script appears to be initialising PWM on the same pin multiple times in the for loop.

Do the p = GPIO.PWM(servoPIN, 50) just once in the script.

joan
  • 67,803
  • 5
  • 67
  • 102
  • yes i given p = GPIO.PWM(servoPIN, 50) out of the for loop but it still gives same error on this line – rah May 11 '19 at 18:05
  • @rahraj are you sure that there is nothing else in the code before the snippet that you have posted? – Ghanima May 11 '19 at 18:38
  • yeah sure , please help me – rah May 11 '19 at 19:00
  • @rahraj You need to post the complete script. – joan May 11 '19 at 19:52
  • basically script is about object detection , my class id is retrieved in the for loop the task is that i have 3 classes so whenever class id =1 then a servo motor should work , similiarly for other classes the corresponding motor should work (the script is so large and hard to indentify thats why i didnt posts the whole script) – rah May 12 '19 at 04:26
  • here it is the full script https://github.com/aswinr22/waste-model/blob/master/picamera1.py – rah May 12 '19 at 06:16
  • @rahraj, Oh my goodness, your "full script" belongs to an "advanced" Google AI TensorFlow object detection project. The servo part is sort of just a 1 page out of a 500 pages book. Any way, let me give you an answer to your python GPIO PWM servo servo program troubleshooting question, in the form of a "Servo Newbie Getting Started Guide", :) – tlfong01 Nov 09 '19 at 02:19
  • May I suggest that you create a small file that compiles, runs, and illustrates the problem. Try to find the smallest program that demonstrates the problem. That way you would be able to communicate the problem to us without a huge file. – NomadMaker Dec 08 '19 at 07:30