Shop OBEX P1 Docs P2 Docs Learn Events
Doing big number math in spin, need help. — Parallax Forums

Doing big number math in spin, need help.

KyeKye Posts: 2,200
edited 2009-05-14 22:12 in Propeller 1
Hey guys, I'm trying to make a piece of custom code for a servo driver using a counter, however I'm having trouble getting the math of one part down.

phsa := -((clkfreq * servoPosition) / 1000000)

Basically the idea was taken right out the of counter app note section. FRQA is set to one and after a certaint number of cycles the output of the counter goes low. And then I repeat this action is a tight loop starting with the counter output high.

The problem is that when you plug lets say (80_000_000 * 1000)·in there the value is way to big... 80Mhz ...·1us servo pulse.

Is there a way to do this math correctly? Does spin do multiplication is 64 bits?

I don't want to just assume the user·is running at over 1MHZ and do ((clkfreq / 1000000) * servoPosition) which would work.

Any ideas???

I was looking at the multiply high operator but I really don't know how to use that.

Thanks,

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-13 02:13
    Kye,

    Take a look at my umath object in the OBEX.

    -Phil
  • KyeKye Posts: 2,200
    edited 2009-05-13 02:32
    Any way of doing that without the whole library in about 1 line?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-13 03:24
    Well, you could just copy the guts from the routine that you need.

    -Phil
  • KyeKye Posts: 2,200
    edited 2009-05-13 05:10
    Eh, done with the driver. That code isn't needed. 40 longs including var space. Pretty small.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-13 06:36
    Why don't you simply divide before??

    -(clkfreq/1000000 *servoPosition)

    If you want your code work in slow RC mode as well you can divide in two portions. Of course in this case servoPosition can't be as big as in the upper example before the result exceeds long size.

    -( (clkfreq/10000 * servoPostion)/100
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-05-13 06:37
    MagIO2,

    you beat me to it... lol

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2009-05-13 07:18
    You could do that with a first integer division followed by a correction using the remainder:

    phsa := -((clkfreq / 1000000 * servoPosition) + (clkfreq // 1000000 * servoPosition / 1000000))

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
  • KyeKye Posts: 2,200
    edited 2009-05-13 15:39
    Check it:

    ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐               
    │ Servo Engine                                                                                                                │
    │                                                                                                                             │
    │ Author: Kwabena W. Agyeman                                                                                                  │                              
    │ Updated: 5/12/2009                                                                                                          │
    │ Designed For: P8X32A                                                                                                        │
    │                                                                                                                             │
    │ Copyright (c) 2009 Kwabena W. Agyeman                                                                                       │              
    │ See end of file for terms of use.                                                                                           │               
    │                                                                                                                             │
    │ Driver Info:                                                                                                                │
    │                                                                                                                             │
    │ The servo engine interfaces with two standard servos.                                                                       │
    │                                                                                                                             │ 
    │ The driver, is only guaranteed and tested to work at an 80Mhz system clock or higher. The driver is designed for the P8X32A │
    │ so port B will not be operational.                                                                                          │
    │                                                                                                                             │
    │ Nyamekye,                                                                                                                   │
    └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 
     
    Object "servoEngine[noparse][[/noparse]2]" Interface:
     
    PUB  setPositionA(degrees)
    PUB  setPositionB(degrees)
    PUB  servoEngine
     
    Program:      32 Longs
    Variable:      8 Longs
    
     5v
     
     └─ Servo 5V Power
     ─ Servo Pulse Width Pin 
     ┌─ Servo Ground 
     
     5v
     
     └─ Servo 5V Power
     ─ Servo Pulse Width Pin 
     ┌─ Servo Ground 
                                   
    __________________________
    PUB  setPositionA(degrees)
     
     4 Stack Longs - Ignore Return Value
    
     ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
     │ Sets the standard servo to the desired position. For continuous rotation servos 90 degrees is the brake while 0 degrees  │
     │ may be full forward and 180 degrees may be full reverse.                                                                 │
     │                                                                                                                          │
     │ Degrees - The desired position in degrees the shaft should be set at. Continuous rotation servos just keep spining a set │
     │           number of degrees from the center 90 degree point. So near 90 is slower and farther away from 90 is faster.    │
     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    __________________________
    PUB  setPositionB(degrees)
     
     4 Stack Longs - Ignore Return Value
    
     ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
     │ Sets the standard servo to the desired position. For continuous rotation servos 90 degrees is the brake while 0 degrees  │
     │ may be full forward and 180 degrees may be full reverse.                                                                 │
     │                                                                                                                          │
     │ Degrees - The desired position in degrees the shaft should be set at. Continuous rotation servos just keep spining a set │
     │           number of degrees from the center 90 degree point. So near 90 is slower and farther away from 90 is faster.    │
     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    ________________
    PUB  servoEngine
     
     4 Stack Longs
    
     ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
     │ Initializes the servo driver to run on a new cog.                                                                        │
     │                                                                                                                          │
     │ Returns the new cog's ID on sucess or -1 on failure.                                                                     │
     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    
     
    ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                                   TERMS OF USE: MIT License                                                 │                                                            
    ├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation   │ 
    │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,   │
    │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the        │
    │Software is furnished to do so, subject to the following conditions:                                                         │         
    │                                                                                                                             │
    │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the         │
    │Software.                                                                                                                    │
    │                                                                                                                             │
    │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE         │
    │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR        │
    │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  │
    │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                        │
    └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • KyeKye Posts: 2,200
    edited 2009-05-13 15:42
    Only 32 longs and 8 vars. Tiny and compact. The driver has been upload to the obex under the motors section. Its fully documented and optimized wasting no byte space. I also include the ability to tinker with the maximum and minimum pulse widths for each servo so you can adjust the object to your partiular need.

    Simply pass the angle you want the servo to go to and it goes to that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-13 17:45
      repeat
        phsa := -(servoPositionA * (clkfreq / 1000000))
        phsb := -(servoPositionB * (clkfreq / 1000000)) 
        
        result += (clkfreq / constant(1000 / ((Servo_Duty_Cycles <# 1000) #> 1)))
        waitcnt(result)  
    
    

    Hi Kye,

    I did not work with servos yet, so maybe my annotation is of little use here, but maybe in other programs it's worth to think about:

    I'm not sure if it is wise to change the clockfrequency in such an application during runtime. But that would be the only case where your calculations make sense inside the loop. If you can live with the restriction that changing the clockfrequency during runtime is not allowed, you could pre-calculate some stuff outside of the loop.
    1. -clkfreq/10000000 and
    2. (clkfreq/constant(....

    The advantage is that you decrease the runtime of the loop which would allow to increase the frequency.

    PUB servoEngine '' 4 Stack Longs
      servoPositionA := constant((((Servo_Max_Pulse_Width_A <# 1000000) #> Servo_Min_Pulse_Width_A) - ((Servo_Min_Pulse_Width_A <# Servo_Max_Pulse_Width_A) #> 0)) + ((Servo_Min_Pulse_Width_A <# Servo_Max_Pulse_Width_A) #> 0))
      servoPositionB := constant((((Servo_Max_Pulse_Width_B <# 1000000) #> Servo_Min_Pulse_Width_B) - ((Servo_Min_Pulse_Width_B <# Servo_Max_Pulse_Width_B) #> 0)) + ((Servo_Min_Pulse_Width_B <# Servo_Max_Pulse_Width_B) #> 0))
    


    Can't you simply call your 2 setter methods to initialize servoPositionA and B? Could save some bytes?!
  • KyeKye Posts: 2,200
    edited 2009-05-13 23:49
    Magic, calling methods actually uses more space. Notice that those huge setences are only that big because I used descripted names and limiters. However they are all calculated before hand. Most of that code does its work during compile time.

    The reason I do all my calculations within a loop is to save space. My driver only uses one variable (the result variable) and has a stack size of 6 longs. Taking your suggestions into consideration would actualy increase the driver size and offer no benefits.

    I must say, if what works under the hood does what you want it to do and does it well, then don't blast it.

    (Sorry for ranting, but I get ticked when its implied I don't know what I'm doing. When I release a driver the last thing I want to hear is someone picking at the way I wrote my code giving less than helpful suggestions. I would rather hear - "Hey can you add this feature" or cool "thank you". Not "I think your code could be written better". If your going to give non-positive feedback please make it about problems which I should fix. Not about problems that don't exist.)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,

    Post Edited (Kye) : 5/14/2009 5:43:16 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-14 03:47
    I'm so sorry ... I did not realize that I was argueing with a god. ... and on the first glance you looked so friendly ...

    If you can't live with the comments that come, why don't you put your driver to the obEx without posting?

    But I learned my lesson: Don't try to be helpful if Kye is posting
  • KyeKye Posts: 2,200
    edited 2009-05-14 17:40
    Eh, sorry, maybe I went overboard there. Was a bit angry that day - lost my cool, I try not to do that when you only have the best intentions also.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-14 20:10
    Just because I was interested in the result I changed the servoEngine to:
      setPositionA(0)
      setPositionB(0)
    
    

    And ... no difference in memory usage ... still 32 Longs·for code and 8·Longs for Variables. The difference ... well runtime and stack-usage ... but we talk about initialization and the stack space is the one of the main-progam and not the one for the object. The advantage ... for such a small program it's not such a big advantage but - you only define the formula once. So, when ever there is a need to adjust it, you only have to change it in one place - that's what functions are good for.
    So, I was wrong with my feeling that is could save some bytes, but that's only due to the fact that the formula is nearly constant.


    ·
  • KyeKye Posts: 2,200
    edited 2009-05-14 20:31
    =)

    But remember the is the center position is 90 degrees, not zero. And spin needs more space to store numbers that aren't zero or one. My the servo engine sets both servos to 90 degrees when started.

    Anwyay, this tread should die since its vastly off topic now.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-14 22:12
    Hey Kye ...

    it seems that you are such a negative person, that it's always no pleasure posting with you. Why don't you simply ignore this thread then?
    Edit:·I said this with the·two following snippets in mind·
    [color=purple](Sorry for ranting, but I get ticked when its implied I don't know what I'm doing. When I release a driver the last thing I want to hear is someone picking at the way I wrote my code giving less than helpful suggestions. I would rather hear - "Hey can you add this feature" or cool "thank you". Not "I think your code could be written better". If your going to give non-positive feedback please make it about problems which I should fix. Not about problems that don't exist.)[/color]
     
     
    [color=purple]Anwyay, this tread should die since its vastly off topic now.[/color]
    

    I personally learned something here:
    1. Center position is 90 degrees (I already stated that I did not work with servos yet)
    2. Spin needs one byte more for storing two times the number 90 instead of two times the number 0 - strange but interesting
    3. A friendly picture makes no friendly person out of you someone per se. What I meant is that a friendly picture is not enough .. you have to behave friendly as well. Future will show.
    4. A boy that's smart enough to write perfect code in terms of memory usage has to ask for how to deal with big numbers - strange as well
    ( Isn't commutative law subject of elementary school )
    [color=purple]Check it: 
     
    [size=2][code]
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;               
    &#9474; Servo Engine                                                                                                                
    



    Only 32 longs and 8 vars. Tiny and compact. The driver has been upload to the obex under the motors section. Its fully documented and optimized wasting no byte space.[/color]
    [/code][/size]
    What I find strange here is that the self-confidence you showed in that post and that you got ticked by simple replies does not fit to the original post where you ask for help on a question someone with such a self-confidence should have solved by it's own.

    I did not criticize you - the word criticize has a little bit of a negative touch to me.. I only made some suggestions and I guess in a way which made·clear that I did not proove the suggestions yet. What I also wanted to say - at least with the first two topics of my learned-list - is that this thread should not die only because you can't cope with the direction it went to.

    Post Edited (MagIO2) : 5/15/2009 1:26:45 PM GMT
Sign In or Register to comment.