woutvanuytsel
Posts: 2
Joined: Thu May 03, 2018 4:41 pm

Problems with shaking servo motors

Thu May 03, 2018 5:12 pm

Hello,
for my thesis I 'm making a cocktail machine and I encountered some problems along the way but there's one problem which i haven't found a fix for. My servo motors with the bottles attached to them work just fine outside my entire program. But when i try to run my entire program they get a little vibrant. Just too much to fill a glass. I am pretty confident this is not a problem with my hardware because when i use a oscilloscope you can see the the duty cycle jump a little bit, just for a split second. Any tips on fixing this ? You can find the the casting of the bottle in the function def cocktailmaken(argument3):.
The HX711 is to measure the weight of the cocktail. And the other function is used for my lcd and buttons.

Code: Select all

import smbus
import thread
import sys
import wiringpi
import RPi.GPIO as GPIO
from RPLCD import CharLCD
from time import sleep
import time
import MySQLdb #db uitlezen

#gewichtmeting
from hx711 import HX711
GPIO.setmode(GPIO.BCM)

hx = HX711(1,16)
hx.set_reading_format("LSB", "MSB")
hx.set_reference_unit(-338)

hx.reset()
hx.tare()
#dma

GPIO.setup(6, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
GPIO.setup(5, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
fles2 = GPIO.PWM(20,60)
fles5 = GPIO.PWM(21,60)
fles3 = GPIO.PWM(13,60)
fles1 = GPIO.PWM(5,60)
fles4 = GPIO.PWM(6,60)
fles1.start(5)
fles2.start(5)
fles3.start(5)
fles4.start(5)
fles5.start(5)
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(26,0)
wiringpi.pinMode(17,0)
wiringpi.pinMode(19,0)

Str= 'tekst'
global keuze
global lcdjanee
global val
global gekozen
global startmaxthread
global cocktailgiet
cocktailgiet=0
cocktailklaar=0
gekozen="ja"
lcdjanee=0
startmaxthread=12

#database uitlezen en in tabel zetten


#db connectie openen
db = MySQLdb.connect("localhost","root","raspberry","cocktails" ) 
# cursor klaarmaken
cursor = db.cursor()
sql = "SELECT * FROM cocktails"
# Execute the SQL command
cursor.execute(sql)
# Fetch all the rows in a list of lists.
results = cursor.fetchall()

#aanmaken lijsten
idclist=[]
naamlist=[]
p1=[]
p2=[]
p3=[]
p4=[]
p5=[]
#variable
global i
i=0#teller loop
#database uitlezen
for row in results:
	IdCocktail = row[0]
	idclist.append(IdCocktail)
	NaamCocktail = row[1]
	naamlist.append(NaamCocktail)
	PartsFles1 = row[2]
	p1.append(PartsFles1)
	p1[i]=int(p1[i])
	PartsFles2 = row[3]
	p2.append(PartsFles2)
	p2[i]=int(p2[i])
	PartsFles3 = row[4]
	p3.append(PartsFles3)
	p3[i]=int(p3[i])
	PartsFles4 = row[5]
	p4.append(PartsFles4)
	p4[i]=int(p4[i])
	PartsFles5 = row[6]
	p5.append(PartsFles5)
	p5[i]=int(p5[i])
	i=i+1
	# Now print fetched result
	print "Naamcocktail=%s,Delenfles1=%d,Delenfles2=%d,Delenfles3=%d,Delenfles4=%d,Delenfles5=%d" % \
		(NaamCocktail, PartsFles1, PartsFles2, PartsFles3, PartsFles4, PartsFles5)



def hxmeting(argument2):
	global lcdjanee
	global val
	global cocktailgiet
	while(lcdjanee==1):
		while(cocktailgiet!=1):
			np_arr8_string = hx.get_np_arr8_string()
			binary_string = hx.get_binary_string()
			val = max(0, int(hx.get_weight(5)))
			print val
			hx.power_down()
			hx.power_up()
			sleep(0.5)


def cocktailmaken(argument3):
	global i
	global gekozen
	global cocktailklaar
	global cocktailgiet
	fles1down=12.6
	fles2down=13
	fles3down=12.6
	fles4down=12.6
	fles5down=12.6
	fles1up=4.7
	fles2up=5.3
	fles3up=5
	fles4up=4.8
	fles5up=5
	cocktailgiet=1
	loopteller=0
	for x in range(0,i):
		loopteller=loopteller+1
		if (naamlist[loopteller-1]==keuze):
			idgekozencocktail=loopteller-1        

	id= int(idgekozencocktail)
	print id
	print naamlist[id]
	#start gieten van flessen
	if p1[id]>0:
		print "part 1 is groter dan 0"
		#servo 1
		teller=10.01
		dutycycleservo=fles1up
		for x in range(0,200):
			teller=teller-0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo+0.039
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles1down)
                time.sleep(p1[id])# tijd beneden blijven van part1
                teller=0
                dutycycleservo=fles1down
		for x in range(0,200):
			teller=teller+0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo-0.039
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles1up)



	if p2[id]>0:
		print "part 2 is groter dan 0"
		#servo 1
		teller=10.01
		dutycycleservo=fles2up
		for x in range(0,200):
			teller=teller-0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo+0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles2down)
                time.sleep(p2[id])# tijd beneden blijven van part2
                teller=0
                dutycycleservo=fles2down
		for x in range(0,200):
			teller=teller+0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo-0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles2up)




	if p3[id]>0:
		
		print "part 3 is groter dan 0"
		#servo 2
		teller=10.01
		dutycycleservo=fles3up
		for x in range(0,200):
			teller=teller-0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo+0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles3down)
                time.sleep(p3[id])# tijd beneden blijven van part3
                teller=0
                dutycycleservo=fles3down
		for x in range(0,200):
			teller=teller+0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo-0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles3up)


		
	if p4[id]>0:
		print "part 4 is groter dan 0"
		#servo 3
		teller=10.01
		dutycycleservo=fles4up
		for x in range(0,200):
			teller=teller-0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo+0.039
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles4down)
                time.sleep(p4[id])# tijd beneden blijven van part4
                teller=0
                dutycycleservo=fles4down
		for x in range(0,200):
			teller=teller+0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo-0.039
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles4up)



	if p5[id]>0:
		print "part 5 is groter dan 0"
		#servo 3
                teller=10.01
		dutycycleservo=fles5up
		for x in range(0,200):
			teller=teller-0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo+0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles5down)
                time.sleep(p5[id])# tijd beneden blijven van part5
                teller=0
                dutycycleservo=fles5down
		for x in range(0,200):
			teller=teller+0.05
			sleep(teller*0.00135)
			dutycycleservo=dutycycleservo-0.038
			pwm.ChangeDutyCycle(dutycycleservo)
		pwm.ChangeDutyCycle(fles5up)
	cocktailklaar=1
	cocktailgiet=0

#lcd aansturen in multithread
def lcd(argument):
	x=1
	global startmaxthread
	global lcdjanee
	global i
	global keuze
	global gekozen
	global eerstekeer
	global naamlist
	global val
	global cocktailklaar
	lcd=CharLCD(cols=20, rows=4, pin_rs=7, pin_e=8,pins_data=[25,24,23,18], numbering_mode=GPIO.BCM)
	lcdjanee=0
	while True:
		if(cocktailklaar==1):
			while (val>200):				
				lcd.clear()
				lcd.cursor_pos = (0, 0)
				lcd.write_string(u'De cocktail is')
				lcd.cursor_pos = (1, 0)
				lcd.write_string(u'klaar')
				lcd.cursor_pos = (3, 0)
				lcd.write_string(u'Massa:')
				lcd.cursor_pos = (3,6)
				lcd.write_string(u'%s' %(val))
				sleep(1)
			if (val<200):
				cocktailklaar=0
				lcdjanee=0
				lcd.clear()

		if(lcdjanee==0):
			tellergram=0
			if wiringpi.digitalRead(26):
				print "pin 26 hoog"
				lcd.clear()
				x=x+1
				if (x>i):
					x=i
			while wiringpi.digitalRead(26):
				pass
			sleep(0.05)
			if wiringpi.digitalRead(17):
				print "pin 17 hoog"
				lcd.clear()
				x=x-1
				if x<1:
					x=1
				while wiringpi.digitalRead(17):
					pass
			time.sleep(0.05)
			lcd.cursor_pos = (0, 0)
			lcd.write_string(u'cocktails:')
			lcd.cursor_pos = (1, 2)
			lcd.write_string(u'->')
			lcd.cursor_pos = (1, 5)
			if (x<=i-2):
				lcd.write_string(u'%s' %(naamlist[x-1]))
				lcd.cursor_pos = (2, 5)
				lcd.write_string(u'%s' %(naamlist[x]))
				lcd.cursor_pos = (3, 5)
				lcd.write_string(u'%s' %(naamlist[x+1]))
				time.sleep(0.5)
				keuze=naamlist[x-1]
			if (x>(i-2)):
				if (x>=(i-1) and x<i):
					lcd.write_string(u'%s' %(naamlist[x-1]))
					lcd.cursor_pos = (2, 5)
					lcd.write_string(u'%s' %(naamlist[x]))
					lcd.cursor_pos = (3, 5)
					lcd.write_string(u' ')
					time.sleep(0.5)
					keuze=naamlist[x-1]
				if (x==i):
					lcd.write_string(u'%s' %(naamlist[x-1]))
					lcd.cursor_pos = (2, 5)
					lcd.write_string(u' ')
					lcd.cursor_pos = (3, 5)
					lcd.write_string(u' ')
					time.sleep(0.5)
					keuze=naamlist[x-1]
		if(lcdjanee==1):
			sleep(0.5)
			lcd.cursor_pos = (0, 0)
			lcd.write_string(u'Plaats u glas')
			lcd.cursor_pos = (1, 0)
			lcd.write_string(u'Dan start de machine')
			lcd.cursor_pos = (2, 0)
			lcd.write_string(u'Automatisch')
			lcd.cursor_pos = (3, 0)
			lcd.write_string(u'keuze:')
			lcd.cursor_pos = (3,6)
			lcd.write_string(u'%s' %(gekozen))
			if (val>115):
				tellergram=tellergram+1
			if tellergram>=3 and startmaxthread==0:
				#maak nieuwe thread
				startmaxthread=1
				thread.start_new_thread(cocktailmaken,(0,))
			if (eerstekeer==1):
				lcd.clear()
				eerstekeer=0

			
			
#start lcd uitlezen 1 keer
thread.start_new_thread(lcd,(0,))


#main programma
try:
	global val
	global keuze
	global lcdjanee
	global eerstekeer
	global gekozen
	global startmaxthread
	while True:
		"""hx.power_down()
		hx.power_up()
		sleep(0.5)"""
		if wiringpi.digitalRead(19):
			gekozen=keuze
			startmaxthread=0
			print "pin 19 hoog"
			lcdjanee=1
			eerstekeer=1
			thread.start_new_thread(hxmeting,(0,))
		while wiringpi.digitalRead(19):
			pass
		sleep(0.05)
finally:
	lcd=CharLCD(cols=20, rows=4, pin_rs=7, pin_e=8,pins_data=[25,24,23,18], numbering_mode=GPIO.BCM)   
	lcd.clear()
Thanks !

pcmanbob
Posts: 4084
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Problems with shaking servo motors

Fri May 04, 2018 9:18 am

Hi.

If your servos are twitching across there entire range then its probably because you are using software pwm.

As raspbian does other things like update the screen talk to the network access the SD card the pwm signal gets slightly changed which results in the twitching you see.

you could used a different gpio software to drive your servos like pigpio, servoblaster, or you could use a dedicated servo driver card, which will handle the servo control and all you have to do is send it the required servo position.
Remember we want information.......................no information no help
The use of crystal balls & mind reading is not supported

PiGraham
Posts: 3313
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Problems with shaking servo motors

Fri May 04, 2018 9:37 am

There may be better options for servo PWM than RPi.GPIO.
I think the trick is to use DMA. PIGPIO does that. I think you can use that through GPIOZERO or it has a Python interface.
You could also look at Servoblaster.
You can't get 100% perfectly stable PWM on general gpio under Linux because it's not realtime but you can get very good PWM for driving servos by using hardare features to schedule the software control.

User avatar
OutoftheBOTS
Posts: 618
Joined: Tue Aug 01, 2017 10:06 am

Re: Problems with shaking servo motors

Fri May 04, 2018 7:51 pm

In most cases if I want to drive servos I will use an external chip to create the PWM signal like the PCA9685. There is lots of manufactures out there making great servo controller boards with this chip.

woutvanuytsel
Posts: 2
Joined: Thu May 03, 2018 4:41 pm

Re: Problems with shaking servo motors

Wed May 23, 2018 6:31 pm

Hello,
Since the time posting this not much has changed.. :roll:
been busy working on another project for school repairing a old westerstrand clock.
First of all I want to thank you all for posting a reply! I will thank you guys in the end of my thesis.
I found out stopping the pulses to the other servo's does a lot! Doing a simple Dma.stop() to the others while one servo is working stops the shaking. Will keep you all updated if there are anymore changes!
Thanks

Return to “Python”

Who is online

Users browsing this forum: ashbashmash and 15 guests