Shop OBEX P1 Docs P2 Docs Learn Events
Servomotor Control — Parallax Forums

Servomotor Control

PivotnewbPivotnewb Posts: 18
edited 2011-10-11 08:48 in General Discussion
Explanation:
We were given a task to run a continuous servomotor for 45.5 seconds in a clockwise motion; record the number of rotations every 1/2 second and then at the end write the data to a USB to be read by "Data Logger PRO"

We deduced that we can use an RTC to help record the number of rotations.

My questions are as follows:
  1. How would we use the RTC to record the number of rotations?
  2. How would we then write down the data onto a USB (The data has to then be read by Logger Pro 3.8.2 found here: http://www.vernier.com/location/?redirect=/products/software/lp/
I'll post the code as it stands here:
' {$STAMP BS2}
' {$PBASIC 2.5}
' -----[ I/O Definitions ]-------------------------------------------------
DataIO          PIN     0
Clock           PIN     1
CS1302          PIN     2
' -----[ Constants ]-------------------------------------------------------

' -----[ Variables ]-------------------------------------------------------
servomotor VAR Word
'--------[Main routine]----------------------------------------------------
DO
FOR servomotor = 1 TO 2275
PULSOUT 14, 1250
PAUSE 20
NEXT
LOOP
Thank you!

Comments

  • ercoerco Posts: 20,259
    edited 2011-10-03 09:57
    Most continuous rotation servos are "RPM-challenged" and their peak speed is ~60 RPM or less. That's only 1 rev/second, or half a revolution in your half-second timing interval, FYI. So you will need multiple pickup points on your encoder or whatever you use. You could even thump a mechanical switch at that speed.
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-03 10:05
    Assuming that the servomotor doesn't rotate at 1 Revolution/Second; is their any way to figure out how fast it's rotating? Or do we have to grab results based on an estimation?
    I'm saying this because the results have to be taken down at the end of the duration (Which is 45.5 Seconds)

    Then again by assuming that servomotor rotates at 1 Rev/Sec I can just say that it has rotated 45.5 times and carry on my merry way; but that's not the point. What I'm trying to do is figure out a way to grab the number of times the servomotor rotates using an RTC.

    Sorry if I'm being hard to understand and thanks for all the help!
    If anything needs clarification please don't hesitate to ask me.
  • ercoerco Posts: 20,259
    edited 2011-10-03 10:39
    If you're required to add an RTC: Depending on the resolution of your RTC, you could use a low-res optical encoder with maybe 4 stripes, and use the RTC to measure the duration of the on/off interval.

    But if it were me, I'd forget the RTC and use a higher resolution encoder and the COUNT command to count how many stripes passed in a given interval. Here's how I did it, counting stripes and stopping after exactly 1 full revolution:

    http://www.youtube.com/watch?v=PfMnl4oGzs8
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-03 10:54
    erco wrote: »
    If you're required to add an RTC: Depending on the resolution of your RTC, you could use a low-res optical encoder with maybe 4 stripes, and use the RTC to measure the duration of the on/off interval.

    But if it were me, I'd forget the RTC and use a higher resolution encoder and the COUNT command to count how many stripes passed in a given interval. Here's how I did it, counting stripes and stopping after exactly 1 full revolution:

    http://www.youtube.com/watch?v=PfMnl4oGzs8

    We don't have to use the RTC. It was a suggestion brought up by another team-member.
    How would we implement this encoder into the code presented in the original post?
  • ercoerco Posts: 20,259
    edited 2011-10-03 11:03
    See PhiPi's fine work at http://www.parallax.com/dl/docs/prod/datast/ApplyEncoder.pdf

    He's doing navigation using optical encoders, so there's more geometry there than you need, but he shows how to use encoders.
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-03 11:06
    erco wrote: »
    See PhiPi's fine work at http://www.parallax.com/dl/docs/prod/datast/ApplyEncoder.pdf

    He's doing navigation using optical encoders, so there's more geometry there than you need, but he shows how to use encoders.
    Thank you very much! I'll take a look into that.

    However is there any chance of getting a simple example on how Encoders work?
    Or a code-template that I can take a look into that explains how to implement an encoder into your program?
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-03 13:38
    I'd use an encoder disk with multiple triggers per rev, say eight? You do not have to use optical.... the same could be done with hall effect, mechanical switches etc.

    By using a black/white optical disk.... even if you DID miss the transition when it happened, by alternating from black to white around the disk (as opposed to black lines on a white disk), you can still check for a change of state from the sensor.


    If you do not have the luxury of a RTC, I guess the code would look like the following:

    FOR k=0 to 91 run the inside loop 45.5 * 2 half second times
    ROUTINESTART:
    sensorflag = current sensor state
    COUNT = 0
    FOR i=0 to 25 (as in fifty checks per second (50Hz servo update).... twenty five checks per half second, which may have to be tweaked a bit)
    PULSOUT to your servo
    PAUSE 20
    IF sensorflag <> current sensor state THEN COUNT = COUNT + 1
    NEXT i

    save COUNT somewhere, or display it, whatever
    NEXT k

    DEBUG COUNT
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-03 20:41
    Spiral_72 wrote: »
    I'd use an encoder disk with multiple triggers per rev, say eight? You do not have to use optical.... the same could be done with hall effect, mechanical switches etc.

    By using a black/white optical disk.... even if you DID miss the transition when it happened, by alternating from black to white around the disk (as opposed to black lines on a white disk), you can still check for a change of state from the sensor.


    If you do not have the luxury of a RTC, I guess the code would look like the following:

    FOR k=0 to 91 run the inside loop 45.5 * 2 half second times
    ROUTINESTART:
    sensorflag = current sensor state
    COUNT = 0
    FOR i=0 to 25 (as in fifty checks per second (50Hz servo update).... twenty five checks per half second, which may have to be tweaked a bit)
    PULSOUT to your servo
    PAUSE 20
    IF sensorflag <> current sensor state THEN COUNT = COUNT + 1
    NEXT i

    save COUNT somewhere, or display it, whatever
    NEXT k

    DEBUG COUNT

    Thank you; this will help out a lot.

    However; what do you mean "Don't have the luxury of an RTC"
    Our first idea was to use an RTC - Can you clarify?

    Edit: Actually! I just realized something...
    To plot an accurate Rotations/Time graph we would still need an RTC; no matter how we gather the number of rotations we need to keep track of the time as well.
    So I think I have to stick with the RTC and now we're at the beginning again.

    How would I use an RTC to record the number of rotations?
    Can I just use the Encoder to gather the number of rotations and the RTC to record the time and then use both data in the same log?

    Thank you!

    Edit2: After some work on it; here's what I came up with.
    Can someone check it out for me? I'm sure it's not going to work in it's current state.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' =========================================================================
    '
    '   File....... Servomotor Advanced.
    '   Purpose....
    '   KAStudents...
    '   Faculty...  L. Mark Kibler (mk)
    '   E-mail.....
    '   Started....
    '
    '
    ' =========================================================================
    '
    ' -----[ Program Description ]---------------------------------------------
    
    ' -----[ Revision History ]------------------------------------------------
    '
    '
    '
    '
    '
    '
    '
    '
    ' -----[ I/O Definitions ]-------------------------------------------------
    EncPulse        PIN     10
    DataIO          PIN     0               ' DS1302.6
    Clock           PIN     1               ' DS1302.7
    CS1302          PIN     2               ' DS1302.5
    ' -----[ Constants ]-------------------------------------------------------
    WrSecs          CON     $80             ' Write Seconds
    RdSecs          CON     $81             ' Read Seconds
    CWPr            CON     $8E             ' Write Protect Register
    WPr1            CON     $80             ' Set Write Protect
    WPr0            CON     $00             ' Clear Write Protect
    WrBurst         CON     $BE             ' Write Burst Of Data
    RdBurst         CON     $BF             ' Read Burst Of Data
    WrRam           CON     $C0             ' Write RAM Data
    RdRam           CON     $C1             ' Read RAM Data
    ' -----[ Variables ]-------------------------------------------------------
    servomotor              VAR     Word    ' Servomotor control
    a                       VAR     Word    ' Number of half-rotations
    sensorflag              VAR     Word    ' Sensor
    current_sensor_state    VAR     Word    ' Sensor_State
    rotations               VAR     Word    ' Number of rotations
    reg             VAR     Byte            ' Read/Write Address
    ioByte          VAR     Byte            ' Data To/From DS1302
    secs            VAR     Byte            ' Seconds
    secs01          VAR     secs.LOWNIB
    secs10          VAR     secs.HIGHNIB
    '--------[Main routine]----------------------------------------------------
    reg = CWPr                            ' Initialize DS1302
    ioByte = WPr0                         ' Clear Write Protect
    GOSUB RTC_Out                         ' Send Command
    a = 0
    sensorflag = current_sensor_state
    rotations = 0
    DO
    FOR servomotor = 0 TO 25
    PULSOUT 14, 1250
    a = a + 1
    PAUSE 20
    IF sensorflag <> current_sensor_state THEN rotations = rotations + 1
    IF a = 91 THEN GOTO finish
    NEXT
    LOOP
    finish:
    GOSUB Get_Time
    DEBUG rotations / secs
    END
    
    RTC_Out:
      HIGH CS1302                           ' Select DS1302
      SHIFTOUT DataIO, Clock, LSBFIRST, [reg, ioByte]
      LOW CS1302                            ' Deselect DS1302
      RETURN
    
    Get_Time:                               ' DS1302 Burst Read
      HIGH CS1302                           ' Select DS1302
      SHIFTOUT DataIO, Clock, LSBFIRST, [RdBurst]
      SHIFTIN DataIO, Clock, LSBPRE, [secs]
      LOW CS1302                            ' Deselect DS1302
      RETURN
    
    Would that work and solve my problem?
    Please note that I still haven't programmed the Encoder; but I'll work on that soon.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-04 08:33
    Well technically it can easily be done and my pseudo-code should work, WITHOUT a RTC.... it just won't be dead accurate.... meaning it's possible you might be off a few usec somewhere, but you're not developing this for NASA :)

    The idea is, you know with fair certainty how long it takes to execute the loop, so multiplying that time by some number of times through the loop, you come up with a decent time base. :D

    I've not used a RTC before and I can't check your code through right now, but it looks like it'll work. Heck, try it and see! The worst that happens is.... it don't work and you have to troubleshoot it :) DEBUG statements will be your friend for that. Don't worry about timing until the routines work though. DEBUG statements take an eternity to execute in the uC world.

    Good luck!

    EDIT: Code notes
    Ok, #1 I made a mistake in that it should be FOR....1 to 25, which would execute 25 times and #2 the "rotations" variable name is as valid as any name, but it'll be a little misleading if you have multiple triggers around the encoder disk.... That's up to you though.
  • ercoerco Posts: 20,259
    edited 2011-10-04 08:35
    How accurate does your 45.5 second interval have to be? You can still do it without a RTC by adjusting your timing loops and counting transitions.
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-04 21:01
    erco wrote: »
    How accurate does your 45.5 second interval have to be? You can still do it without a RTC by adjusting your timing loops and counting transitions.

    Ok guys; sorry again!
    But I can't use an encoder at all apparently; the reason for this is because this (As I figured out recently) is a test for the hardware team for their project. They will not be using an encoder in the project so their is no reason for them to learn how to wire one up to a circuit-board. But they will be using an RTC so to clarify the project is to.

    1) Run a servomotor for 45.5 seconds
    2) Record number of servomotor rotations using only an RTC.
    3) Record the data on a USB to be used later by Logger pro.

    Sorry for the trouble.
  • ercoerco Posts: 20,259
    edited 2011-10-04 22:05
    A RTC measures time, not rotations. It will be a good trick measuring rotations without some kind of encoder feedback. Suggest you clarify with your instructor.
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-05 01:17
    That's what I said; I asked him as to how I could logically think of a way to measure rotations with a Servomotor? The programming wouldn't be a problem... but how do you... do it?
    I'll ask him today.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-05 11:21
    Wow, servo revs are a function of load, voltage, current available and moon phase. Maybe an average per unit time?
  • ercoerco Posts: 20,259
    edited 2011-10-05 11:23
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-05 23:27
    erco wrote: »

    Not so sure about this; But my instructor did indeed say that we were to only use an RTC and a Servomotor and then gather data (Number of servomotor rotations).
    As to how to do it; that's up to me.

    I still can't think of it logically; how would you record rotations using only an RTC?
  • ercoerco Posts: 20,259
    edited 2011-10-05 23:44
    You gotta go outside the 9 dots. Redefine "RTC" as rotary transmissive chopper, AKA a rotary encoder disk with slots that "chops" a transmitted light beam and is sensed by a phototransistor. Piece of cake now!
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-06 06:52
    I wonder if the voltage line feeding the servo sags as the motor armature passes the magnet? You could amplify this with an opamp, count the sags, divide by the number of poles, the gear ratio and have revolutions.

    average revs per second multiplied by elapsed time would work..... kinda. It'd be like throwing darts though.

    That's all I have with no encoder :)
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-09 11:26
    JUST FOUND OUT SOMETHING!

    The simple way out of this is to make the Servomotor rotate at a fixed Revolutions/Second (Maybe 1 or 2)
    So now my new question is:

    How can I make my Servomotor rotate at 1 Rev/Sec using the Pulsout command?

    Pulsout port, XXXX? What value should I set for XXXX to get it to rotate at 1 Rev/Sec

    Cheers.

    I should mention that we are using a continuous servomotor not a standard.

    This is what I have so far:
    ' -----[ Variables ]-------------------------------------------------------
    servoPulse      VAR     Word    ' Servomotor control
    halfRot         VAR     Byte    ' Number of Half-Rotations
    '--------[Main routine]----------------------------------------------------
    DEBUG "Initializing!", CR
    halfRot = 0    ' We haven't started so number of Half-Rotations = 0.
    PAUSE 3000     ' Give time to initialize.
    DEBUG "Initalized successfully!", CR
    DO UNTIL halfRot = 91
    FOR servoPulse = 1 TO 25
    halfRot = halfRot + 1
    PULSOUT 14, 1250
    PAUSE 20
    NEXT
    LOOP
    

    The reason I think this would work as
    Pulsout 14,1250 should do a 180 degree turn on the servomotor which can be considered a half rotation
    So if 50 pulses = 1 second in the "For servoPulse = 1 to 25" then it should take 0.5 seconds for a 180 degree turn and 1 seconds for a full turn.

    Therefore it should run for 91 half-turns in 45.5 seconds.

    I can't tell whether what I'm doing is right or wrong at this point and would appreciate some help!
    Thank you.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-09 17:57
    Pivotnewb wrote: »
    How can I make my Servomotor rotate at 1 Rev/Sec using the Pulsout command?

    Pulsout port, XXXX? What value should I set for XXXX to get it to rotate at 1 Rev/Sec

    There is no correlation between the number you PULSOUT and the servo rotate speed across any two servos due to different gear ratios, quality, bearing type, etc. I would suspect even two servos of the same make and model may be a little different. Get yourself a stopwatch, run the servo for one minute using PULSOUT 1250... count the revs and divide. The number you PULSOUT should relate to the speed linearly..... I think....

    Once you get your number, take note of the voltage, cause you're going to need to keep that constant between tests and on your presentation.
  • Mike GMike G Posts: 2,702
    edited 2011-10-09 18:07
    Pivotnewb, erco creatively gave you the answer several times... encoder.
  • ercoerco Posts: 20,259
    edited 2011-10-09 18:20
    @Pivotneweb: It sounds like you haven't yet tried the servo, or something would have clicked by now. Get some hands-on testing done and come back when you have some relevant findings about pulsout and rpm.
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-10 00:31
    Mike G: My instructor specifically told me not to use an encoder.
    Spiral; I could do that but I'm supposed to figure out how to make it run at a steady rate that I can control.
    Erco: I've run the program countless times.

    First mistake was that the 91 half-rotations didn't work and I'm working on that at the moment.
    As for the Rev/Sec I need to figure out how to control it within the program.
    Thank you anyways.
  • ercoerco Posts: 20,259
    edited 2011-10-10 05:48
    Without an encoder, the best you can do is to determine servo run time through brute force experimentation. Per Spiral, servo RPM is fairly linear over most of the pulsout range until it trails off at peak RPM, so I second your suggestion to run at peak RPM, which may be somewhat constant. Your program will have multiple nested loops, carefully calibrated to deliver however many pulses it takes to get to 45.5 revolutions. You'll be fighting many variables, including servo temperature and battery voltage, so testing & consistency is key. I'm guessing that (with great care) you might get within +/- 1 revolution of 45.5 revolutions.

    You'll find out when you want to stop that there are 2 ways. First, just stop sending pulsouts, and your servo will gently coast to a stop. Or if instead you send pulsout 750s, the servo will stop suddenly using dynamic braking.

    Be sure to let us know how the class does!
  • PivotnewbPivotnewb Posts: 18
    edited 2011-10-10 23:23
    Thank you Erco for all the help!
    Everything going great in class - I've managed to borrow the Circuit board with the Data-logger, Servomotor, RTC attached so me and a couple of my team-mates can work on it in our free time (We live in a boarding school)

    So right now we're working in and out of class to finish this A.S.A.P

    This is all a practice run for a bigger project later on that we haven't decided on as of now.

    I can consider this thread solved!

    Most sincere thanks to Erco/Spiral you both had great suggestions and helped me think of many new and different ways to finish this program.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-10-11 08:48
    Your welcome and most of all have fun with it!
Sign In or Register to comment.