Shop OBEX P1 Docs P2 Docs Learn Events
Writing a driver for two steppers is harder than I thought! - Page 2 — Parallax Forums

Writing a driver for two steppers is harder than I thought!

2»

Comments

  • lardomlardom Posts: 1,659
    edited 2011-12-29 15:02
    @idbruce, I tried to the best of my ability to impliment your code and I can't figure it out. "FutureTime" is one of several variables that I can't wrap my head around. In addition, I have to ignore features like ramping until I find out what's preventing me from driving my steppers independently. I have to consider that you've spent time writing code for my benefit.There is only one response; Thank you.

    Your code is a bit too advanced for me. I can accept annoyance at my apparent lack of mental acuity. I have to compensate for it with persistance. Thanks again for trying to help me.
  • JonnyMacJonnyMac Posts: 9,235
    edited 2011-12-29 15:12
    I think this doesn't work because of the of an offset within the external object (having to do with the way the compiler arranges code so that it can be reused by more than one cog). The first call is getting lucking and works; sort of -- but it never returns. I added these lines:
    result := cognew(L.Start, @stack)
      pst.dec(result)
      pst.newline
    

    ... and nothing is getting printed to the terminal, indicating an error in the call. What should have been reported is the cog id.

    In the end, though, this *violates* the method construction for standard objects (in addition to being just plain bad by using embedded pin and timing constants). All programming languages have requirements, and just because you or I think a given language *should* behave in a certain way doesn't mean it will.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-29 15:41
    pedward,

    I'm not sure why you expected the following to work:
    PUB main
      pst.start(115200)             'debug output
    '  cognew(Left,@stack)
    '  cognew(Right,@stack[50])
      coginit(1,R.Start,@stack)
      coginit(2,L.Start,@stack[50])
    

    The PST object has already claimed cog 1, when you do the coginit for that cog. So now I'm going to climb into my pulpit once again. Never, never, NEVER (with an infinitessimally vanishing number of exceptions -- and then only if you know what the hell you're doing) use coginit. Always use cognew to start a cog.

    Also, let me echo Jon's comment: The Spin compiler has been beaten to death for more than five years. Any bugs would have been found by now. (There are some questionable "features", but that's another story.) So, it's never helpful, when debugging a programming, to assume the compiler is at fault.

    -Phil
  • JonnyMacJonnyMac Posts: 9,235
    edited 2011-12-29 16:00
    The Spin compiler has been beaten to death for more than five years.

    ...and for nearly that many years prior to being released.
  • lardomlardom Posts: 1,659
    edited 2011-12-29 16:12
    @JonnyMac and Pedward, I based what I wrote on the "Blink" objects in chapter 5 of the PE Kit lab and could not see what was different.
    Reading the phrase "how a compiler arranges code" is a new concept. I will study until I get a thorough understanding of everything written here. Thanks again.
  • pedwardpedward Posts: 1,642
    edited 2011-12-29 16:32
    pedward,

    I'm not sure why you expected the following to work:
    PUB main
      pst.start(115200)             'debug output
    '  cognew(Left,@stack)
    '  cognew(Right,@stack[50])
      coginit(1,R.Start,@stack)
      coginit(2,L.Start,@stack[50])
    

    The PST object has already claimed cog 1, when you do the coginit for that cog. So now I'm going to climb into my pulpit once again. Never, never, NEVER (with an infinitessimally vanishing number of exceptions -- and then only if you know what the hell you're doing) use coginit. Always use cognew to start a cog.

    Also, let me echo Jon's comment: The Spin compiler has been beaten to death for more than five years. Any bugs would have been found by now. (There are some questionable "features", but that's another story.) So, it's never helpful, when debugging a programming, to assume the compiler is at fault.

    -Phil

    It wasn't important because I wasn't using PST. Yes, bad form, but I was trying to debug the COGNEW function call by substituting the macro code that COGNEW actually calls. I knew the caller was 0 and just picked 1 and 2 to reinitialize.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-29 16:55
    pedward wrote:
    It wasn't important because I wasn't using PST.
    Whether you actually used it or not, calling PST's start method the way you did launches cog 1, blocking your subsequent coginit. But, as you've discovered, that's not the only problem with the code. See post #41.

    -Phil
  • pedwardpedward Posts: 1,642
    edited 2011-12-29 17:04
    Whether you actually used it or not, calling PST's start method the way you did launches cog 1, blocking your subsequent coginit. But, as you've discovered, that's not the only problem with the code.

    -Phil

    Yeah, I was just looking at the compiler output to see if it was any different, in both cases it called the function first and never got to launching a cog.
  • idbruceidbruce Posts: 6,197
    edited 2011-12-29 17:05
    Larry

    Let me explain:
    PUB SimultaneousSteppers | WaitForFutureTime
    
      WaitForFutureTime := CLKFREQ * 3 + CNT
    
      COGNEW(Full(8, 11, WaitForFutureTime), @RightWheelStack)
      COGNEW(Full(12, 15, WaitForFutureTime), @LeftWheelStack)
    
    

    In the Pub function SimultaneousSteppers, the local variable WaitForFutureTime is assigned the current value of the system counter plus three seconds. Of course the three seconds could be much smaller, but both of the new cogs need time to initialize. WaitForFutureTime is passed to the PUB Full method in both of the COGNEW calls. Picture this, both cogs have been called and initialized, but you still want both of the cogs to start moving the steppers at the same time. So the FutureTime puts them both in sybcronization, because they are both waiting for the same future clock cycle to actually start.

    Bruce
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-29 17:09
    And what happened next is that the value returned by the function was used as a hub address for launching a PASM cog.

    BTW, I was wrong about cog 1's usage blocking your coginit. The coginit always stops, overwrites, and restarts the chosen cog.

    -Phil
  • pedwardpedward Posts: 1,642
    edited 2011-12-29 17:10
    Larry,

    Here is a very simple test program that is nearly identical to the one you posted the Youtube video about. I rewrote the Left/Right to work properly, this should be an example of what you need to do. It is written for the Quickstart board LEDs.
  • pedwardpedward Posts: 1,642
    edited 2011-12-29 17:13
    And what happened next is that the value returned by the function was used as a hub address for launching a PASM cog.

    BTW, I was wrong about cog 1's usage blocking your coginit. The coginit always stops, overwrites, and restarts the chosen cog.

    -Phil

    There is nothing wrong with the result of a function being used as the address to then launch a COG, but for the behavior to change depending on the calling environment AND this not being documented, is a problem. Obviously the solution is to update the documentation to specifically mention this usage as something to avoid.
  • idbruceidbruce Posts: 6,197
    edited 2011-12-29 17:16
    Larry

    I tried to write that snippet for a quick easy test using pins 8-15 to control 8 LEDs, just like you are attempting. Just upload to a prop as is, without any additional calls or programming and it should work. If it doesn't try altering these values.

    Distance := 10
    Duration := 4
    Rate := Distance / Duration
  • JonnyMacJonnyMac Posts: 9,235
    edited 2011-12-29 17:22
    Obviously the solution is to update the documentation to specifically mention this usage as something to avoid.

    When in doubt, read the latest version of the manual before suggesting that it is lacking something. Page 80 of the version 1.2 manual specifically states that you cannot launch a new cog with cognew using object.method as the first parameter.
    1024 x 640 - 121K
  • idbruceidbruce Posts: 6,197
    edited 2011-12-29 17:30
    I feel like I am just wasting my breath. :(
  • pedwardpedward Posts: 1,642
    edited 2011-12-29 17:33
    JonnyMac wrote: »
    When in doubt, read the latest version of the manual before suggesting that it is lacking something. Page 80 of the version 1.2 manual specifically states that you cannot launch a new cog with cognew using object.method as the first parameter.

    If there was only some way I could magically hit the "update" button on my dead tree copy! :innocent:
  • lardomlardom Posts: 1,659
    edited 2011-12-29 18:24
    @ JonnyMac, That's the answer on pages 80 and 81! :smile: An added bonus is it explains why the "stop" command is needed.
    @ idbruce, I did learn a few important things from you. I am still a relative novice so when you said to use variables as opposed to hard coded values the light went on in my head. Maybe it's no big deal to you but to me...Aha!
  • idbruceidbruce Posts: 6,197
    edited 2011-12-30 01:24
    Larry
    I did learn a few important things from you. I am still a relative novice so when you said to use variables as opposed to hard coded values the light went on in my head.

    JonnyMac had to beat that concept into my head with a sledge hammer :) But he finally got through my thick skull. I now try to write my code so that all I/O pins are established as constants, and where possible, values that use CLKFREQ to determine some type of setting, should also be set up as a constant to make quick and easy changes throughout the program.
    Maybe it's no big deal to you but to me...Aha!

    As for this comment, I have stuck by your side and tried to help, but you still have not answered my question. I will test simultaneous cogs on my own, however it will be more difficult for me, because I do not have a spare board. A simple upload to the prop and you could have given me an answer.

    On second thought... Aha!

    Bruce
  • lardomlardom Posts: 1,659
    edited 2011-12-30 08:50
    @idbruce. Aha! :smile:
    Becoming aware of the distinctions between hard coding vs variables has made developing code much easier for me. I start by trying to define a problem with a series of logical statements. I express them quantitatively and convert those statements to Spin. Hard coding exposes flaws more quickly because I can debug it with a calculator. If I'm satisfied I can then rewrite it so I can pass values to it. That insight has sped things up.
    I'm not a genius so I don't grasp everything people try to explain to me. My progress is relatively slow but the "Aha!" experience spikes my endorphins.
    I'm still studying what you have written.
  • lardomlardom Posts: 1,659
    edited 2011-12-30 21:04
    :cool: It works. I'm smiling.
    I think I may annotate my video with the rule governing the cognew command. I'm sure it will help someone else the same as it has helped me. Thanks everyone.
Sign In or Register to comment.