Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 09:58 19 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Software modding servos

Author Message
Dylan
Regular Member

Joined: 17/06/2013
Location: Netherlands
Posts: 81
Posted: 06:36am 16 Jul 2013
Copy link to clipboard 
Print this post

So a while back I bought some servos second hand. They turned out to be continuous rotation, which is not really what I want for panning. In MMBasic I managed to mod them (using bitbang ;-) to act as if regular, doing the timing by hand.

Today I finally got around to finishing the PC-based webserver for Android client, as well as getting Arduino to drive both the continuous one better than before and the regular (9g) tilt one.

Ping time from App Inventor (very much for prototyping) generally ranges from 100 to 150 ms. That's acceptable (5 updates per second in production). What is less acceptable is that the sweet little servos will do their very best to move as fast as possible!

SO: there are two very different(ial?) problems to solve. One is to tell a regular servo to move at a certain rate over the next period of time t from angle alpha to angle beta. The other is to integrate - accurately - over time what the changes in angle have been.

Oddly, the latter seems easier to me. That's probably because I already have a potential solution. Not that I know it will work. But the obvious idea of delay(20) for PWM does not work, I can tell you that much!

Does anybody have experience with 20ms timer interrupts for precise PWM?
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 06:59pm 16 Jul 2013
Copy link to clipboard 
Print this post

Hi Dylan,
I've been using a little Tower Pro SG90 servo (standard type, not continuous) and I've found that 50 Hz (20mS) is about the fastest rate you can re-issue the PWM command. You can see this if you you put the command inside a DO loop - the servo won't run until you delay each iteration of the loop by about 20mS. You can do that with e.g. a SETTICK interrupt calling the loop or a PAUSE inside the loop. Geoff has noted that this is probably because of the time required to set up registers etc for the PWM output.

This doesn't really change things from the servos point of view anyway though because the pulse rate being sent to the servo is normally about 50Hz, i.e. you shouldn't be trying to get it to change what it's doing any more often than that. The width of those individual pulses going to the servo at 50Hz is what controls its position, not the rate at which the pulses are being sent.

Another thing to watch is that versions of MMBasic before the latest V4.4 release had a bug which created a 'jumpy' output to servos if PWM was used to control them. This has been fixed in the latest V4.4 release.

To control the rate of translation you'll have to re-issue PWM or PULSE commands with a small increment or decrement of pulse width at some regular interval that you've previously determined is appropriate for your travel rate. This 'regular interval' will presumably be considerably more than the standard 20mS pulse update rate of the servo - and this has potential to cause vibration. I guess expensive servos would also have some means of controlling current or voltage to the motor to change the rate. To accurately get it's position you'll probably need to add a pulse or absolute encoder and read that with the program.

The program below which I used to calibrate and test my SG90 model servo might (or not) give you some other useful info. (I've fiddle with this recently so there may be bugs!)

Greg

'SERVO - Program to test the Micro Power SG90 servo motor using
' the original mono-colour Maximite and MMBasic V4.4
' ----------------------------------------------
'Normal analogue servos hold position dependant on the incoming pulse width on
'the control lead. The pulse stream needs to be maintained to hold servo
'position and the normal pulse repetition rate is approx 50Hz but this is not
'critical over quite a wide range.
'The centre (neutral) posn'n for most servos is at a pulse width of approx.
'1.5mS and the full pulse width range for most servos is approx 1mS to 2mS.
'The pulse width range needs calibrating for different servos so as to achieve
'their full movement range but not over-drive and thus possibly damage them.
'Pulse width Vs position is usually not fully linear, i.e. mid pulse width is
'not necessarily the centre servo position. Shorter pulses rotate the SG90 arm
'clockwise but this can be different for other servos.
'
'The SG90 has three leads:
' a) Gnd (usually brown)
' b) 5v supply (usually red - and usually the centre lead). This draws
' typically 50-80mA when moving and 5-10mA when holding or when
' there is no control pulse input. If over-driven the current can be
' above 200mA and damage may occur. Monitoring current on the servo
' lead is a good idea when testing!
' c) pulse control lead (usually yellow).
'
'Testing is conveniently done using a 10K linear pot connected across the
'Maximite's 3.3v supply and connecting the pot wiper to one of the Maximite
'analogue input pins via a 220 ohm resistor. Voltage at that pin can then be
'read by the program and scaled to provide the control pulses. The amplitude
'of the control pulses is not critical but should not exceed the 5v servo
'supply voltage. 3.3v pulses work well.
'
'The servo can be controlled with either the PULSE or PWM command. Control
'using PULSE requires the program to maintain the pulse stream. Control using PWM
'is simple and provides a continuous pulse stream in the program background till 'changed with another PWM command or stopped with a PWM STOP command. Another
'method is to connect the PWM output running at 50Hz to an input interrupt pin
'and issue PULSE commands within the interrupt routine.
'When using the PWM command the first argument is frequency and the second
'argument is a percentage of the period. At 50 Hz the period is 20mS, thus e.g.
'10% of that equates to a 2mS pulse.
'
'NOTE 1: versions of MMBasic prior to V4.4 had a bug which limited the accuracy
'of the pulse width (it's 'resolution') to about 1%, i.e. 0.2mS at 50Hz which
'equates to around 10% of the full servo range. Thus using PWM control with
'MMBasic versions earlier than V4.4 creates very 'stepped' output. With V4.4 the
''resolution' is 0.1%, i.e. 0.02mS at 50hZ which gives fine control.
'
'NOTE 2: when using PWM control, the Maximite's PWM output circuit must have
'the voltage divider network removed to supply the full 3.3v pulse height.
'
' -----------------------------------------------------
'Rough SG90 pulse width Vs position calib'n using the PULSE command.
' Full range on the SG90 is: 2.4 mS (~90o) to 0.6mS (~270o) clockwise.
'
'Rough SG90 PWM command Vs position calib'n when running at 50Hz (20mS period).
' Full range: 12.4% (~90o) to 3.2% (~270o) clockwise.
' -----------------------------------------------------
'
Initialise:
SetTick 0,0: SetPin 11,0: SetPin 5,0: PWM STOP
Print "Input type of servo control to use:"
Print "1=Keybd_PULSE, 2=Keybd_PWM, 3=Pot_PULSE, 4=Pot_PWM"
Input controltype
On controltype GoTo Keybd_PULSE,Keybd_PWM,Pot_PULSE,Pot_PWM

Keybd_PULSE:
SetPin 11,8 'set pin 11 as digital out
Pin(11)=0 'set pin 11 to 0 (in case it's at 1)
Input "Input pulse width in mSecs: ",width 'range approx 0.6 to 2.4 mS
SetTick 20,Pulseout 'set timer interrupt for pulse out every 20mS (50Hz)
GOSUB Wait
goto Keybd_PULSE

Keybd_PWM:
Input "Input pulse width in mSecs: ",width 'range approx 0.6 to 2.4 mS
percent = width*5 'assuming frequency of 50Hz (i.e. 20mS period), thus %=width*100/20
PWM 50,percent 'start 50 Hz continuous pulse train
GOSUB Wait
goto Keybd_PWM

Pot_PULSE:
SetPin 11,8 'set pin 11 as digital out
Pin(11)=0 'set pin 11 to 0 (in case it's at 1)
SetPin 5,1 'set pin 5 as analog in
SetTick 20,Pulseout 'interrupt for pulse out every 20mS (50Hz)
Do
volts = Pin(5) 'read wiper voltage at the pot position
width = (0.5454*volts)+0.6 'from: slope=(2.4-0.6)/3.3 and y=Sx+c

key$ = Inkey$
If key$ <> "" GOTO Initialise
loop

Pot_PWM:
SetPin 5,1 'set pin 5 for analog input
do
volts = Pin(5) 'read wiper voltage at the pot position
width = (0.5454*volts)+0.6 'from: slope=(2.4-0.6)/3.3 and y=Sx+c
percent = width*5 'assuming frequency of 50Hz (i.e. 20mS period), thus %=width*100/20
PWM 50,percent 'start 50 Hz continuous pulse train
Pause 20 'delay needed for PWM at 50Hz otherwise no pulse output

key$ = Inkey$
If key$ <> "" GOTO Initialise
loop

Pulseout:
Pulse 11,width
IReturn

Wait:
key$ = Inkey$
If key$ = "" GOTO Wait 'wait for a keyboard press to input another pulse width
return
Edited by paceman 2013-07-18
 
Dylan
Regular Member

Joined: 17/06/2013
Location: Netherlands
Posts: 81
Posted: 09:12am 17 Jul 2013
Copy link to clipboard 
Print this post

Thank you paceman, but unfortunately we are at roughly the same level of understanding. But that is the best documented code I have ever seen. Nice!

Unfortunately for me, the continuous servo is hard to calibrate. To be more specific, I programmed a PWM to last one second, with whatever angle I sent over serial. It took almost exactly 7 such commands at the lowest anti-clockwise setting. However, 7000ms had to be changed to about 5800. (I then gave up).

Since I really like the idea of continuous rotation, and with pot meters not being an option, it looks like an IR bridge + disk will be needed.
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024