Shop OBEX P1 Docs P2 Docs Learn Events
Need infinite loop in method while ina[leftstop]==1 — Parallax Forums

Need infinite loop in method while ina[leftstop]==1

cnelson700cnelson700 Posts: 31
edited 2010-06-15 22:04 in Propeller 1
I want to turn a motor, used for steering, left until the left limit switch is pressed (left LS is NC(1) so it is open(0) when pressed).
When the left LS is pressed (ina[noparse][[/noparse]leftstop]==0) I then want to slowly turn right until the left LS is not pressed (ina[noparse][[/noparse]leftstop]==1) and then stop the motor.

Then I want to read the value from a potentiometer and then turn fast right until the right LS is pressed (ina[noparse][[/noparse]rightstop]==0)



My code is not working.



("turnmotor" is a PUB with (Pin, Speed) controlling HB-25 which drives the motor and that code works so I left it out of the below sample code)




[size=2][code]
PUB main

    calibrate  

 

 

PUB calibrate
  repeat
    case ina[noparse][[/noparse]leftstop]

           0 : turnmotor(steering, steerstop)

                leftcalibrate

 

 
     
     case ina[noparse][[/noparse]rightstop]

           0 : turnmotor(steering, steerstop)

                rightcalibrate

 

PUB leftcalibrate

    repeat while ina[noparse][[/noparse]leftstop] == 0

           turnmotor(steering, sright)

 

    turnmotor(steering, steerstop)

     

    <here is where I put code to read pot value>

 

    turnmotor(steering, fright)

 

 


PUB rightcalibrate

    repeat while ina[noparse][[/noparse]rightstop] == 0

           turnmotor(steering, sleft)

 

    turnmotor(steering, steerstop)

     

    <here is where I put code to read pot value>

 

    turnmotor(steering, fleft)


[/code][/size]




when I run this code, I expect that when the leftstop LS is pressed (ina[noparse][[/noparse]leftstop]==0):

the motor will stop



PUB leftcalibrate is called:



the motor will turn slowly to the right until the leftstop LS is no longer pressed (ina[noparse][[/noparse]leftstop]==1)

the motor will stop

The pot value will be stored

the motor will turn full speed right.



PUB leftcalibrate is done and processing continues in PUB calibrate after the line that called PUB leftcalibrate.







My observation is that when the leftstop LS is pressed, the motor stops and turns right and stops and turns right rapidly and repeatedly until the leftstop LS is no longer pressed and then turns fast right.



It appears to me that the 'repeat while' code





    repeat while ina[noparse][[/noparse]leftstop] == 0

           turnmotor(steering, sright)







is being ignored.

Which means that PUB leftcalibrate keeps getting called and completed rapidly and repeatedly while the leftstop LS == 0 as if there were no 'repeat while leftstop==0' condition.



Shouldn't the 'repeat while ina[noparse][[/noparse]leftstop] == 0' keep the cog stuck looping 'turnmotor(steering, sright)' until 'ina[noparse][[/noparse]leftstop]==1' and then process the rest of the PUB leftcalibrate?



c

Post Edited (cnelson700) : 6/14/2010 8:20:31 PM GMT

Comments

  • cnelson700cnelson700 Posts: 31
    edited 2010-06-14 20:07
    I also tried to use 'WAITPEQ (%100000000000000, 14, 0)' and that appeared to be ignored also.
    (the leftstop LS is on pin 14)
  • T ChapT Chap Posts: 4,223
    edited 2010-06-14 20:23
    What is going on here with this indention and CASE usage?


    PUB calibrate
      repeat
        case ina[noparse][[/noparse]leftstop]
               0 : turnmotor(steering, steerstop)
                    leftcalibrate
         case ina[noparse][[/noparse]rightstop]                     '<<<<<<<<<<<<<<<<<<<<  indented 1 space
               0 : turnmotor(steering, steerstop)
                    rightcalibrate
    
    




    When you have code spread out like that with all the spaces between, it is hard to keep track of your indention.

    A suggestion might be to implement some type of visual or audible feedback to help diagnose the issue. When I am trying to track things down, I either use an LCD to pop up a visual que or a piezo speaker. This way you can place feedback at different sections of code to see where things are getting to or not getting to. With the piezo or other speaker off a Prop pin, you can set the frequency to different values that let you know where you are in the loop. ie, 500 hz for the first pub, 1000 hz for 2nd, 1500 for 3rd etc.

    Post Edited (Todd Chapman) : 6/14/2010 8:32:42 PM GMT
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-14 20:27
    Sorry... The 'case ina[noparse][[/noparse]rightstop]' was indented 1 space too far in the example.
    Good eye!
  • T ChapT Chap Posts: 4,223
    edited 2010-06-14 20:30
    Did it have any effect on the problem?
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-14 20:34
    The code posted is not copy/paste'd from propeller tool.
    I typed it here. My code has more components to it that are not relevant to my question so I just typed up the stuff that would help clarify my question.
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-14 20:49
    Just incase it might help, I have attached the complete Object that this code is in.
    It is a bit messy, I'll clean it up after I get it to work the way I want it to.

    Thanks,
    c
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 14:28
    I have cleaned and simplified my code to focus on my problem.
    I have run this code and I get the same undesirable result.

    I get:
    Slow turn left until left LS pressed
    Stop
    slow turn right, stop, slow turn right, stop, slow turn right, stop, slow turn right, stop, slow turn right, stop......
    until the left LS is not pressed and then fast turn right.


    I want:
    slow turn left until left LS pressed
    stop
    slow turn right until left LS is not pressed
    1 second pause
    fast turn right

    Why is the repeat while ina[noparse][[/noparse]leftstop] == 0 not repeating while ina[noparse][[/noparse]leftstop] == 0?

    {{hb-25 test
    turn until switch input is low
    pause 1 second
    then turn the other way until other switch input is low
    pause 1 second
    repeat
    }}
     
    CON
      _xinfreq=5_000_000            
      _clkmode=xtal1+pll16x                 'The system clock is set at 80MHz (this is recommended for optimal resolution)
      rightstop = 13                                                             'input pin for right LS
      leftstop = 14                                                              'input pin for left LS
      steerstop = 1500   
      ssleft = 1550      
      sleft = 1700       
      fleft = 2000       
      ssright = 1450     
      sright = 1300      
      fright = 1000
      steering = 16                                                              'output pin for HB-25     
     
    PUB steercalstart
        dira[noparse][[/noparse]rightstop]~                                                            'make right LS pin an input
        dira[noparse][[/noparse]leftstop]~                                                             'make left LS pin an input
        dira[noparse][[/noparse]steering]~~                                                            'make pin for HB-25 an output
        outa[noparse][[/noparse]steering]~                                                             'hold pin for HB-25 low
        waitcnt((clkfreq*3)+cnt)                                                    'for 3 seconds
        if ina[noparse][[/noparse]leftstop] == 1                                                       'if leftLS is 1 (not tripped)
            steermotor(steering, sleft)                                             'start slow left turn of steering wheels
        repeat while ina[noparse][[/noparse]leftstop] == 1                                             'turn slowly left until hit left LS
            steermotor(steering,sleft)
                 
        steercalLR          
     
    PUB  steercalLR
        repeat 
            
          case ina[noparse][[/noparse]leftstop] + ina[noparse][[/noparse]rightstop]                                       'If both left and right LS are low
               0 : steermotor(steering, steerstop)                                  'Stop steering motor
                   WAITPEQ(%000000000, %100000000, 0)                               'Wait for reset pin to go low
                         
          case ina[noparse][[/noparse]rightstop]                                                       'If Right LS is pressed (0)
              0 :  steermotor(steering, steerstop)                                  'stop motor
                   rightcal                                                         'goto rightcal
              
          case ina[noparse][[/noparse]leftstop]                                                        'If Left LS is pressed (0)
              0 :  steermotor(steering, steerstop)                                  'stop motor
                   leftcal                                                          'goto leftcal
                                                                                       
    PUB rightcal
          if ina[noparse][[/noparse]rightstop] == 0                                                    'If right LS is pressed (0)
            repeat while ina[noparse][[/noparse]rightstop] == 0                                        'while Right LS is pressed
              steermotor(steering, sleft)                                           'keep turning slow left
             
          steermotor(steering, steerstop)                                           'then stop motor
          waitcnt (clkfreq+cnt)                                                     'wait 1 second
          steermotor(steering, fleft)                                               'go fast left
     
    PUB leftcal
          if ina[noparse][[/noparse]leftstop] == 0                                                     'If Left LS is pressed (0)
            repeat while ina[noparse][[/noparse]leftstop] == 0                                         'while Left LS is pressed
              steermotor(steering, sright)                                          'keep turning slow right
                   
          steermotor(steering, steerstop)                                           'then stop motor
          waitcnt (clkfreq+cnt)                                                     'wait 1 second
          steermotor(steering, fright)                                              'go fast right                  
    
    PUB steermotor(motor, speed)
    
            outa[noparse][[/noparse]steering]~~                                                        'pulse high
            waitcnt((speed * (clkfreq / 1_000_000))+cnt)                            'keep pulse high for 1.5ms for stop
            outa[noparse][[/noparse]steering]~                                                         'pulse low                                  
            waitcnt (clkfreq/1000_000*6500+cnt)                                     'min hold-off time between pulses is 5.25ms 
    




    I have also attached the object for review.
  • T ChapT Chap Posts: 4,223
    edited 2010-06-15 14:49
    This will not solve anything, but I am curious why you are passing a parameter to the method steermotor called 'steering', but you never use the parameter when it gets there? Motor is never used after it gets assigned in the method. If you don't need parameters, it would make for cleaner code to keep track of if you leave out the excess.



    PUB steermotor(motor, speed)    '<<<<<<<  MOTOR  is never used after this line
    
            outa[noparse][[/noparse]steering]~~                                                        'pulse high
            waitcnt((speed * (clkfreq / 1_000_000))+cnt)                            'keep pulse high for 1.5ms for stop
            outa[noparse][[/noparse]steering]~                                                         'pulse low                                 
            waitcnt (clkfreq/1000_000*6500+cnt)                                     'min hold-off time between pulses is 5.25ms
    




    It looks like you have extra pins to spare, I would at a minimum put an LED on a spare output pin, and turn the LED ON when ina[noparse][[/noparse]left] == 0 so you can start seeing in real time whatever the code is seeing to better analyze things. In a case like yours, you have to implement diagnostics when things don't make sense to track down where it is off.

    Also, the way you are trying to pulse the line is not going to be precisely how you intend, since you are introducing extra code in the loop that takes time. If you have cogs to spare, you should park the pulse management code in a cog by itself, which updates from the master, then the pulses can be more precise.

    Post Edited (Todd Chapman) : 6/15/2010 2:58:09 PM GMT
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 14:55
    That is correct. I will replace outa[noparse][[/noparse]steering] with outa[noparse][[/noparse]motor] when I get this issue fixed because I am going to use this PUB for the drive motors also.


    I have been using a voltmeter to watch the input and also using the ina[noparse][[/noparse]leftstop]+ina[noparse][[/noparse]rightstop] fault detection by pressing both LS's to make the motor stop.· In my more complex version of this code, I have the fault displayed in serial terminal.

    I am not sure what you mean regarding extra code or how to get more precise pulses.

    Thanks for looking and replying.

    Post Edited (cnelson700) : 6/15/2010 3:05:25 PM GMT
  • T ChapT Chap Posts: 4,223
    edited 2010-06-15 15:00
    In the code below, your indention suggests that in all cases the last three lines (steermotor(steering, steerstop) and steermotor(steering, fright) ) WILL ALWAYS occur regardless of ina[noparse][[/noparse]leftstop]. I am not sure if you want this or not. Maybe you intended this, but if not, then your last 3 lines might need to line up with the Repeat, not the IF. As is, the IF statement has nothing to do with whether the last three lines will run, they run automatically every iteration.


    PUB leftcal
          if ina[noparse][[/noparse]leftstop] == 0                                                     'If Left LS is pressed (0)
            repeat while ina[noparse][[/noparse]leftstop] == 0                                         'while Left LS is pressed
              steermotor(steering, sright)                                          'keep turning slow right
                  
          steermotor(steering, steerstop)                                           'then stop motor
          waitcnt (clkfreq+cnt)                                                     'wait 1 second
          steermotor(steering, fright)                                              'go fast right
    

    Post Edited (Todd Chapman) : 6/15/2010 3:06:19 PM GMT
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 15:09
    What I want is when the leftcal is called, the motor will keep slowly turning right until the left LS is not pressed - and then immediately stop the motor, wait 1 sec, and then go fast right.


    But when leftcal is called, the motor stops, waits 1 sec, pulses right, stops, waits 1 sec, pulses right, stops, waits 1 sec...... until the leftstop LS is not pressed and then goes fast right.

    It is not doing the 'slowly turn right until the left stop is not pressed' part.
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 15:13
    leftcal is called when leftstop==0 so leftcal is supposed to be stuck in the repeat while loop until the leftstop==1 and then do the last 3 lines.

    But it does not continue looping in the repeat while loop.
  • T ChapT Chap Posts: 4,223
    edited 2010-06-15 15:25
    Just guesses to test out:

    Try turning off all the case statements except LEFT to isolate the left case as the problem.

    Put a short delay after the repeat while line before it hits the last three lines.

    Look at the left stop pin with a scope to see what kind of noise is on it that might be causing the repeat to jump out and start all over again. Put a .1 cap from the pins to GND near the 2 stop inputs and see if that helps. There is no obvious reason in the code why it would stop repeating until the switch is released.

    Check if the Prop is resetting between each 'pulse' (add some indication to the steercalstart init to inidicate that it had restarted)
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 15:33
    I'll give that a try...
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-15 15:47
    Do you use debounced buttons? Because I don't see any code which debounces the input. So it's very likely that bouncing causes the problem - maybe only additional problems ;o)

    Which propeller board do you use? Maybe you can disconnect the buttons and simulate the user input with another COG which uses the input pins of your code as output. As this will create clear signals you can test the code this way.
    If you can't disconnect the buttons you can maybe use other pins.
  • T ChapT Chap Posts: 4,223
    edited 2010-06-15 15:52
    Quick and simple debounce:

    case ina[noparse][[/noparse]leftstop]                                                        'If Left LS is pressed (0)
              0 :  if  ina[noparse][[/noparse]leftstop] == 0    'make sure it is really a 0
                       waitcnt(10_000 + cnt)   ' lets wait to be sure
                       if   ina[noparse][[/noparse]leftstop] == 0     'check again
                          steermotor(steering, steerstop)                                  'stop motor
                          leftcal                                                          'goto leftcal
                                                                                       
    PUB leftcal
       if ina[noparse][[/noparse]leftstop] == 0   
          waitcnt(10_000 + cnt)   ' lets wait to be sure
          if ina[noparse][[/noparse]leftstop] == 0                                                     'If Left LS is pressed (0)
            repeat while ina[noparse][[/noparse]leftstop] == 0                                         'while Left LS is pressed
              steermotor(steering, sright)                                          'keep turning slow right
                  
       steermotor(steering, steerstop)                                           'then stop motor    
       waitcnt(clkfreq+cnt)                                                     'wait 1 second
       steermotor(steering, fright)                                              'go fast right
    
    
    
    
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 16:57
    I will be adding the debounce code - great suggestion.

    I did the tests Todd suggested at 8:25 AM (GMT -7) except for checking to see if the prop is resetting.· Good troubleshooting points, unfortunately none of those checks found the problem - but I added
    waitcnt(clkfreq+cnt)
    after the last line of PUB leftcal
    steermotor(steering, fright) - and after the steermotor(steering, fleft) in the PUB rightcal
    and it worked as desired.

    PUB leftcal
          if ina[noparse][[/noparse]leftstop] == 0                                                     'If Left LS is pressed (0)
            repeat while ina[noparse][[/noparse]leftstop] == 0                                         'while Left LS is pressed
              steermotor(steering, sright)                                          'keep turning slow right
                   
          steermotor(steering, steerstop)                                           'then stop motor
          waitcnt (clkfreq+cnt)                                                     'wait 1 second
          steermotor(steering, fright)                                              'go fast right
          waitcnt(clkfreq+cnt)                  
    


    I don't understand why this worked.· I didn't touch the repeat while.
    I just added a 1 sec pause after the return from the call to the PUB steermotor.
    The end of the PUB steermotor has a 6.5ms delay when only 5.25ms delay is required (for the HB-25).
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 20:48
    UNBELIEVABLE!!!!
    The addition of the waitcnt(clkfreq+cnt) did not fix the issue.
    I·thought the issue was fixed·...· and it was... Until I pulled the scope leads off of the LS input.· Then it did not work properly, again.
    So I·tried to mimic the load of the Oscope:

    Capacitive load?· I tried a few values of cap's - nogo

    Resistive load?· I tried a 2.2k ohm resistor from the input to gnd... and it worked.· Yes it did!

    Is a 2.2k pull down resistor on the switch input gonna be OK on the Prop Pro Development board?

    c
  • StefanL38StefanL38 Posts: 2,292
    edited 2010-06-15 21:42
    did you connect the switches without any pull-up or pull-down resistors?

    If you leave an input-pin free floating the detected state will flip around from 0 to 1 and back in an unpredictable way
    even if you only have connected a wire only one inch long.

    2.2k is Ok. Everything between 1k and 10k is OK

    maximum current: 3.3V / 1k = 3.3 mA 3.3V / 10k = 0.33mA

    best regards

    Stefan
  • cnelson700cnelson700 Posts: 31
    edited 2010-06-15 22:04
    Yep nope - I overlooked that aspect and spent 2 weeks trying to fix the 'software'.

    I didn't need to add a resistor for any of my other I/O devices (even the PB's on the prop pro development board have built in pull up resistors) so I completely overlooked that part of the design.

    Ouch!
Sign In or Register to comment.