Shop OBEX P1 Docs P2 Docs Learn Events
Execution times — Parallax Forums

Execution times

Spiral_72Spiral_72 Posts: 791
edited 2011-03-04 21:16 in General Discussion
I'm working on a PING mounted servo and the servo is running pretty choppy.

The inside loop reads the PING and updates the servo:

to fire the PING I send a 0.000004ms pulse (4us)
PING burst is 0.2ms
the PING returns with a maximum 18.5ms echo time
Delay before next measurement ( I assume is pin hold time ) 0.2ms

Send one byte at 9600 baud ~1ms
update the servo position: ~2ms


so if I total all that up it's 21.9ms worst case. Why is the servo running so choppy?? What am I missing? Are any of my times wrong?
«1

Comments

  • Mike GMike G Posts: 2,702
    edited 2011-02-24 17:26
    Post your code.
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-24 17:34
    Are you doing any calculations? I assume since you say you send one byte that you are doing a calculation on the ping length as typical ping counts would exceed 255.

    I also think it may be optimistic to assume that serout only consumes 1mS to do the entire job of sending one byte. The actual transmit time should be around 1mS, but the total time includes formatting time if you are using any formatting and probably some housekeeping.

    BTW, I finally ordered a BS2 OEM and a PING from Digi-Key today so I can retire that old BASIC ATOM.

    C.W.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-24 17:36
    Figuring out timing based on what you think is happening is great when it works. When it doesn't work, the most likely reason is that one of your assumptions is wrong. In your case, you've got a "worst case" time of essentially 22ms. Servos require a control pulse about that often. If any of your assumptions are wrong, you could easily go over that. Servos are not usually specified in terms of the maximum delay between control pulses, so anything over 20ms is suspect.
  • Mike GMike G Posts: 2,702
    edited 2011-02-24 17:58
    And to second
    the most likely reason is that one of your assumptions is wrong

    Does the servo have enough time to reach the desired angular position before being commanded to another position?
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-24 18:02
    Alright Mr. Mike G:

    My inside loop and called subroutine:
    TOGGLE TXRXLED
    FOR i=lastSVA TO SVA STEP 1        ' run servo from last position to current
    PULSOUT SVA_PIN,i                  ' update the servo
    GOSUB Get_Sonar                    ' retrieve distance information from the PING
    SEROUT 16,16780,[inches]           ' send measurement in inches to the PC
    NEXT
    TOGGLE TXRXLED
    
    
    
    
    
    
    Get_Sonar:
      Ping = 0                                      ' make trigger 0-1-0
      PULSOUT Ping, 4                               ' activate sensor
      PULSIN  Ping, 1, rawDist                      ' measure echo pulse
      rawDist = rawDist */ $0CD                     ' convert to uS
      rawDist = rawDist >>1                         ' remove return trip
      inches = rawDist ** 889                       ' convert to inches
      RETURN
    
    There are some LCD updates and other stuff, but it's all outside this loop. This routine gets PING data, sends the distance then moves the servo..... then all over again.

    The "STEP 1" is because I've changed it 50 times.... so I just left it in there. "1" is just the latest iteration. I also made a little pause routine that changed delay based on the delta-T of the PING echo, in an attempt to at least move the servo consistently regardless of the distance measured. Before (and this routine) the closer the PING measured, the faster the servo travels. I removed it just to make it easier to read. This routine drives the servo very choppy at distances greater than about 24"

    The servo can be adjusted from 750 to 2500..... PULSOUT SVA_PIN, i which would be 0.2ms at 2500 plus execution time for PULSOUT
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-24 18:30
    Mike G wrote: »
    And to second
    Does the servo have enough time to reach the desired angular position before being commanded to another position?

    Yea, I guess one of my assumptions are wrong. Maybe it just won't work, but I've seen videos where it DOES work.

    Oh, yea. The servo is fast - fast. 150ms for a 60 degree sweep. I can drive it with raw code no problem..... update, pause 20, update and it'll sweep beautifully.


    I could just use the un-calculated rawdist and bitshift it to something Byte sized..... or even send Words for that matter, but I don't think the three calculations are eating my clocks. Could be wrong though. I can try it.

    Quite honestly I ignored actual execution times of each command because we're talking microseconds to execute an instruction.... again, I could be wrong.


    I looked at Mr. Allen's work on Stamp timings, but it doesn't include the BS2px, neither does it include much information for the next slower 20Mhz versions :( Maybe this data is not available.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-24 19:05
    Alright sirs.

    I removed the calculations and just used the Word size "Rawdist" value the PING returns. I still get a choppy servo. If I put my hand ~3" away from the PING I get smooth motion..... 24"+ or so, it gets choppy.

    That leaves the PULSOUT for the servo, the PULSIN for the PING and SEROUT. One or all are taking longer than I thought. Phooey.


    I commented out the SEROUT instruction and there is no change in servo behavior. At least that's taking a minimal amount of time :)
    I moved the PING routine into my inside loop to get rid of the two branch instructions GOSUB and RETURN. No change.

    That leaves the PULSOUT for the servo and the PULSIN for the PING. I'm kinda stuck I guess.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-24 19:25
    Going by Mr. Allen's work and BS2 (not the much faster BS2px) execution times:
    FOR i=lastSVA TO SVA STEP 1 '825us
    PULSOUT SVA_PIN,i           '230+200us
    Ping = 0                    '576us
    PULSOUT Ping, Trigger       '230+3.5us
    PULSIN Ping, 1, rawDist     '240+200us + 18.5ms (MAX)
     NEXT                       ' 0us included in FOR above
    
    for a grand total of 21.004ms on a much slower BS2. ARG!!!!!! The servo should be running perfectly given this!


    Ignoring the PULSOUT for the servo, because the PULSOUT and PAUSE 20 runs the servo just perfect...... that leaves the PULSIN for the PING. It must be taking MUCH longer than the manual says.

    It may be time to email Parallax about the PING. At least I'll know for sure.
  • Mike GMike G Posts: 2,702
    edited 2011-02-24 19:30
    I would help to provide the current state of your code...

    In the code you posted I see...

    Move the servo the smallest distance possible. In that time do a PING, a calculation, and send the result to a PC.

    1) The PC could do the math not the STAMP?
    2) The servo could have a larger sweep?
    3) you could start the Ping, pulse the servo, read the result, pulse the servo?

    I'm still not sure what you're trying to do. Where does lastSVA and SVA get set?
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-24 19:54
    Mike G.

    #1 Thank you for the reply. Post #9 is the most recent with all the options removed. It shows everything that's happening on the inside loop. I removed the calculations, no DEBUG, no PAUSE, just what you see and the servo runs erratic depending on the distance the PING senses.... the longer the distance the more "crunchy" the servo runs. at a PING distance of about 3", the servo runs perfectly just like PULSOUT and PAUSE 20 would perform. The point is, given this information one could surmise it takes 20ms for the PING to detect an object 3" away.

    #2 The servo can have a larger sweep.... the larger the sweep, the more erratic the servo performs in THIS program.
    If I run the following program to only update the servo 5 or 10 or 15 positions at a time with a PAUSE 20 it'll really walk the dog..... nice and smooooth :)
    FOR i=750 to 2500 STEP 10
    PULSOUT SVA_PIN,i
    PAUSE 20
    NEXT

    #3 Yessir' that's exactly what the last code does (Post #9)

    I'm just trying to get a consistent and smooth servo operation with a mounted PING. Theoretically and from what I understand from the docs, this would be quite simple since I thought the total execution time for the loop would be very close to the 20ms frequency the servo requires to move properly.

    lastSVA is SerVo A's start position (the previous end position)
    SVA is SerVo A's end position (The position we are moving to this time through the loop)
    Both variables are set outside the loop. Sorry, I figured it would be easier to read if I posted only the work routine instead of the 100 or so lines of the full program.
  • Mike GMike G Posts: 2,702
    edited 2011-02-25 05:44
    No in post 9 you do a
    PULSOUT Ping, Trigger       '230+3.5us
    PULSIN Ping, 1, rawDist     '240+200us + 18.5ms (MAX)
    

    What about something like this
    Ping = 0 
    FOR i=lastSVA TO SVA STEP 2 
     PULSOUT Ping, Trigger 
     PULSOUT SVA_PIN,i-1      
     PULSIN Ping, 1, rawDist 
     PULSOUT SVA_PIN,i    
    NEXT 
    
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 07:08
    Hmmmm, interesting idea. So you;re kind of half-wave driving the servo? I can try it tonight.....We'll see if it works :)
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-25 07:30
    Mike G wrote: »

    What about something like this
    Ping = 0 
    FOR i=lastSVA TO SVA STEP 2 
     PULSOUT Ping, Trigger 
     PULSOUT SVA_PIN,i-1      
     PULSIN Ping, 1, rawDist 
     PULSOUT SVA_PIN,i    
    NEXT 
    

    I don't think that will work. There is a 750uS delay from the falling edge of the trigger pulse before the rising edge of the detection pulse. The PULSOUT to the servo will be roughly in the 1000uS to 2000uS range, so the PULSIN won't see the rising edge of the sonar detection pulse.

    C.W.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 07:40
    I'm not so sure about that. PULSEIN and PULSOUT will hold the processor for as long as it takes the pin to change states.

    So look at it this way: PULSIN ping, 1,rawdist....... If we were measuring the distance from Earth to the Moon with the PING :) the PING might hold the pin HIGH for 20seconds, the time it could take to receive the echo back, the BS2 will sit there and do nothing for 20 seconds until it sees the pin change state.

    I AM a little worried about the fact that the servo PULSOUTs are sent like 75% time apart.... like if the routine took 30ms to execute we send a PULSOUT at 1ms and 25ms, then again at 31ms... We'll see though. It would very cool if it works!
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-25 07:54
    I'm not positive about how PULSIN works, but it would be a problem either way.

    1) If PULSIN does not start counting until is sees a rising edge on its pin, it won't start counting because the the pin will aready be high when PULSIN is executed. The documentation says "PULSIN is like a fast stopwatch that is triggered by a change in state (0 or 1) on the specified pin", so I think this is the case.

    2) If PULSIN starts counting if the pin is already in the desired state when PULSIN is executed, you will see a count, but it will be inconsistent because of the variable delay caused by the PULSOUT to the servo.

    The example also leaves out spending any time to send the data via serial, so that would also be an issue.

    I have an idea bouncing around in my head, I'll try to put together some pseudo code at lunch.

    C.W.
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-25 09:00
    OK, here is my example:
    ' This is to adjust step size
    ' Using your assumptions of 750 min travel to 2500 max travel there would be 875 steps with an increment of 2.
    ' Given the beam width of the PING, I would use something more like an increment of 10 to speed things up.
    ' Should be a multiple of 2
    increment = 2
    
    FOR i = lastSRA TO SVA STEP increment
    	'Ping Phase
    	PULSOUT SVA_PIN, i
    	PULSOUT Ping, Trigger
    	PULSIN Ping, 1, rawDist
    	'delay with adjustment for ping time
    	'this is to make the Ping Phase consume close to 20uS from end of servo pulse to start of Transmit Phase
    	'this assumes rawDist / 1234 will NOT exceed 19
    	'which should not occur with Ping 18.5 mS max measurement period.
    	PAUSE 19 - rawDist / 1234
    	
    	'Transmit Phase
    	PULSOUT SVA_PIN, i + increment / 2
    	rawDist = rawDist */ $0CD                     ' convert to uS
      	rawDist = rawDist >>1                         ' remove return trip
      	inches = rawDist ** 889                       ' convert to inches
      	SEROUT 16,16780,[inches]
      	'this is to make the Transmit Phase consume close to 20uS from end of servo pulse to start of next Ping Phase
    	PAUSE 17	' may need some adjustment, i just assumed 3mS was used for serout and calcs			
    NEXT
    
    
  • sam_sam_samsam_sam_sam Posts: 2,286
    edited 2011-02-25 10:18
    I have played with the ping my self
    I have seen this my self up close to the ping works real fast far away take longer to run through the code routine
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 10:31
    I have played with the ping my self
    I have seen this my self up close to the ping works real fast far away take longer to run through the code routine

    Yea, it's very noticeable too! Do you have any actual times?? I don't have a real time clock, and I can't run the PING off my computer.... no parallel port :(

    I need to order some parts to play with this some more.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 10:36
    ctwardell wrote: »
    OK, here is my example:

    [/code]

    Thank you sir. The code looks good. I'll try it out and let you know what happens. The real solution for this is to run the Parallax servo controller.... That's probably where I'll end up :(

    I bought these real nice HiTec Karbonite geared servos. They are fast and strong. I just hate the idea of sending pulses to them off-frequency because that means the motor stops and starts at high frequency.... That can't be good.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-02-25 10:42
    Spiral_72 wrote:
    The real solution for this is to run the Parallax servo controller.
    ... or the ServoPAL (on sale).

    -Phil
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-25 10:51
    Spiral_72 wrote: »
    I bought these real nice HiTec Karbonite geared servos. They are fast and strong. I just hate the idea of sending pulses to them off-frequency because that means the motor stops and starts at high frequency.... That can't be good.

    Those sound nice, would be a shame to treat them harshly.

    Another alternative is the Propeller. I think you mentioned on one of the other posts that the prop was on your horizon in the future. There are objects in the OBEX for servo control, serial comms, etc., should not be too hard to get going.

    I've got a couple props and the PEK here, I've done some playing around but nothing serious yet, maybe this gives me an excuse to dive a little deeper. :-)

    C.W.
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-25 10:54
    ... or the ServoPAL (on sale).

    -Phil

    That's a clever little device.

    C.W.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 11:40
    ... or the ServoPAL (on sale).

    -Phil
    Ah, that's actually what I meant.... my mistake. Parallax makes a servo controller too don't they?

    <sigh> The Prop. I would love to get my hands on that :) I can just imagine. Hey COG#1 do this, hey COG#2 do that. Hey, COG#3 let me know when they're done and calculate all this Smile and send it over serial while #1 and #2 is busy running their stuff at the same time. BwaAHAHAHA!
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-25 11:45
    Alright, anyways. I'm going to try CTWardell's code and see what happens. After that I'm afraid I'll either have to swap out for a Smile servo and live with what I got, redesign it with a laser HA! or use a ServoPAL or Prop. Otherwise this ain't looking good.

    Thank you for all the suggestions though, really. They've all been a big help.... and to Mike Green for pointing out what I didn't want to accept :(
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-02-28 07:47
    ctwardell wrote: »
    OK, here is my example:

    I've been quite busy sir. I haven't touched my project in four days I think. I now hope to try your program tomorrow night. Tonight is booked up already :(
  • ctwardellctwardell Posts: 1,716
    edited 2011-02-28 07:50
    Totally understand.

    My OEM stamp and PING))) arrived Saturday, I built the stamp and modified my Atom code to work, but have not had a chance to do anything else. I doubt I have a chance to do anything else with it until next weekend.

    C.W.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-03-03 17:52
    ctwardell wrote: »
    OK, here is my example:

    HA!HA!HA! It's kind of hard to put this into words, but I'll try.

    So I have this flimsy plastic quarter roller hot glued to the top of the servo (Hey it's the first thing I found!!) then the PING hot glued to that so the sensor is perpendicular to the floor. I load your program into the BS2.....execute the PC end program and give it a servo position and. WHAT THE!???!!

    So the servo is shaking violently from side to side, very very fast, like a dog after a bath.... the PING looks like a pair of eyes and they are just a blur. HAHA! Was hilarious man. I guess you had to be there.

    Anyways, the problem was easy to find (because I just made the same mistake about 2 weeks ago) and fix with a set of parenthesis.

    PULSOUT SVA_PIN, i + (increment >>1)
    I bit shifted instead of your divide..... same thing.


    The pause works very nicely. The PING reads 3" away or 100", the servo is constant speed, it is however brutally slow. It doesn't seem to want to tune out either.... I can hear the motor energize about thirty times a second with a little tick, tick, tick.....I THINK it's because we're updating the servo every 1 and 35ms.... or essentially once every 40ms. I'll play with your code a bit more.... I think that's it though :)


    EDIT:
    NO, I looked at your code again... You ARE updating the servo position every 20ms. Once at the start with "i" then after the PING stuff.... corrected to 20ms..... with "i+1"

    Hmmm, let me work with this some more.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-03-03 18:36
    Alright Mr. CTWARDELL

    You wrote a nice routine actually. The sweep is very consistent regardless of the PING data. It works, "pretty" well, but the servo is still rough and I don't know why. To me it looks like it should run perfectly. The best I've been able to tune so far is:
                increment = 8
                FOR i = lastSVA TO SVA STEP increment
                    'Ping Phase
                    PULSOUT SVA_PIN, i
                    PULSOUT Ping, Trigger
                    PULSIN Ping, 1, rawDist
                    char = 6 - (rawDist >> 12)
            IF char>20 THEN char = 100
            PAUSE char
    
                    'Transmit Phase
                    PULSOUT SVA_PIN, i + (increment >>1)
                    rawDist = rawDist */ $0CD                     ' convert to uS
                  rawDist = rawDist >>1                         ' remove return trip
            SEROUT 16,16780,[rawdist]
                    PAUSE 18
                NEXT
    
  • ctwardellctwardell Posts: 1,716
    edited 2011-03-04 06:39
    Spiral_72,

    Cool, glad it is getting closer to what you want.

    When I put that code together I didn't realize that the stamps do left to right evaluation, so that is why I didn't use parens when I should have.
    I discovered that the hard way when I converted some code for my OEM Stamp last weekend, ended up with my servo slammed against it's stop groaning loudly...

    I'm not sure if you can really tune out the "tick-tick" because unless you sweep the servo at it's natural rate of rotation it will stop briefly at each commanded location.

    C.W.
  • Spiral_72Spiral_72 Posts: 791
    edited 2011-03-04 08:50
    That's true, but looking at your code it seems like it would work. You update the servo position in the PING phase, and correct the elapsed time to 20ms.. this routine seems to work as it servo is constant speed regardless of the PING measurement. Then you update the servo position in the transmit phase with half the next step and correct elapsed time to 20ms...... So THEORETICALLY you are updating the servo every 20ms!

    The only thing I can think of that makes sense is the PING is actually taking longer than 20ms for ANY reading and we're offsetting that 20ms to the next 20 for a total of 40ms. That would update the servo, wait 40ms, update the servo, wait 20ms, then over again. I can't verify that without a RTC though.
Sign In or Register to comment.