Shop OBEX P1 Docs P2 Docs Learn Events
Question about Loop in SimpleIDE — Parallax Forums

Question about Loop in SimpleIDE

NWCCTVNWCCTV Posts: 3,629
edited 2014-09-04 16:22 in Learn with BlocklyProp
Not sure what I did wrong with this code. It works the first time but after I press 2 to stop the Servo, pressing 1 will not start it again. I know it is something simple but just not sure what.
/*Test SIRC Remote.c


Connect 38 kHz IR receiver to Propeller P10
Decodes button presses on Sony-compatible IR remote
Run with Terminal


*/


#include "simpletools.h" // Libraries included
#include "sirc.h"
#include "servo.h"


int main() // main function
{
sirc_setTimeout(1000); // -1 if no remote code in 1 s


while(1) // Repeat indefinitely
{ 
// decoding signal from P10
print("%c remote button = %d%c", // Display button # decoded
HOME, sirc_button(10), CLREOL); // from signal on P10
int button = sirc_button(10);
if(button == 1)servo_speed(18,100); // P16 servo to 0 degrees
if(button == 2)servo_stop();
pause(100); // 1/10 s before loop repeat
} 
}

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2014-09-02 20:28
    Just thinking aloud here. Stopping the servo cog simply kills the servo handler, i.e. anywhere in the loop. Then the lock is returned. Unless there is extra code involved the lock is returned in its current state. It's also highly likely that you catch it in the locked state which means when servo_set restarts the handler it then sits forever on an (already locked) lock (provided the same lock is checked out).

    This needs a fix in the library, e.g. lockclr before lockret or graceful exit of the handler code. The latter may inflict some delay (stop would only set a flag) so may not be desirable.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-02 20:51
    So how do I fix it?
  • edited 2014-09-03 11:20
    Andy

    I'll try to get an updated library posted here before the end of the day. If you are interested in adjusting the library yourself, try these tutorials first: http://learn.parallax.com/propeller-c-library-studies Note: Some of the memory saving lessons are no longer as significant, but it's still a good look into creating and editing libraries. After that, the servo library project is ...Documents\SimpleIDE\Learn\Simple Libraries\Motor\libservo\libservo.side. From what I gather from post #2 (thank you Kuroneko!) the servo_stop function needs a lockclr before the lockret. it would probably also be useful to add functions to stop sending signals to one or more selected servos so that you can allow servos to relax without stopping the entire driver.

    Andy
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-03 11:48
    Great. I am back working on my Wild Thumper project and was just "testing the waters" with a couple servos before I decide if I am going to use SPIN or SimpleIDE. I already have the code for SPIN set up and going but not for SimpleIDE. I am also going to be adding a PING in to the mix so if there is any advice you can give I am all ears. Thanks.
  • kuronekokuroneko Posts: 3,623
    edited 2014-09-03 16:10
    the servo_stop function needs a lockclr before the lockret. it would probably also be useful to add functions to stop sending signals to one or more selected servos so that you can allow servos to relax without stopping the entire driver.
    I think it would be cleaner to clear the lock after checking it out.

    Also, I noticed that the servo_start function gets a lock (potentially destroying/leaking an existing one) then calls servo_stop which - if the handler is running - frees it again. NG. Maybe servo_start shouldn't necessarily be public?
  • edited 2014-09-03 16:19
    Andy North,

    I do not yet have a library for you to test, but in the meantime, here is an undocumented servo library feature for you to try.

    You can make the servo library selectively release control of a servo with servo_set(pin, 0). This function call just makes the library stop sending control signals to the servo, but the library itself keeps going, and it'll also continue to control other servos. Although I could document this, it seems like it would be better to have a function named servo_sleep(int pin) that calls servo_set(pin, 0). That way, folks can see in the library docs that servo_sleep allows the application to selectively release control of a servo connected to a particular I/O pin.

    At any rate, here some code for you to test. It uses servo_set(18, 0) approach to release control of the servo. If you call servo_speed later (by pressing 1 on your remote), it should resume sending the control signals to that servo, and it'll start turning again. I also changed the remote delay to 200 ms. You could try 100, but much less than that might lead to missed remote button presses and it's also possible to send data to SimpleIDE Terminal more quickly than it can display.
    /*
      Test SIRC Servo Control 1
    */
    
    #include "simpletools.h"                    // Libraries included
    #include "sirc.h"
    #include "servo.h"
    
    int main()                                  // main function
    {
      sirc_setTimeout(200);                     // -1 if no remote code in 0.2 s
      while(1)                                  // Repeat indefinitely
      { 
        print("%c remote button = %d%c",        // Display button # decoded
              HOME, sirc_button(10), CLREOL);   // from signal on P10
              
        int button = sirc_button(10);           // Check P10 for remote message
        
        if(button == 1)servo_speed(18,100);     // P18 servo full speed CCW
        if(button == 2)servo_set(18, 0);        // Release servo control of P18
      } 
    }
    


    Another approach would be to call servo_speed(pin, 0). Unlike servo_set(pin, 0), which just stops sending control signals to servo, servo_speed(pin, 0) would send the servo a "stay still" signal to a continuous rotation servo. Assuming you use that same command center the continuous rotation servo, it should stay still. This will cause a continuous rotation servo to exert a little more force to try to keep the servo in a given position than if the control signal disappeared altogether. It does take a little more current though, and if the servo falls out of calibration, you may notice it turning slowly.

    /*
      Test SIRC Servo Control 2
    */
    
    #include "simpletools.h"                    // Libraries included
    #include "sirc.h"
    #include "servo.h"
    
    int main()                                  // main function
    {
      sirc_setTimeout(200);                     // -1 if no remote code in 0.2 s
      while(1)                                  // Repeat indefinitely
      { 
        print("%c remote button = %d%c",        // Display button # decoded
              HOME, sirc_button(10), CLREOL);   // from signal on P10
              
        int button = sirc_button(10);           // Check P10 for remote message
        
        if(button == 1)servo_speed(18,100);     // P18 servo full speed CCW
        if(button == 2)servo_speed(18, 0);        // Set P18 speed to 0
      } 
    }
    

    Andy
  • edited 2014-09-03 16:28
    Kuroneko,

    Okay, clearing the lock after checking it out sounds good.

    Yes, excellent point. I'll make it private.

    Thanks again, Andy
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-03 19:58
    OK, The code works as expected. Now, how would I add a second servo to opposite commands on pin 19? Such as one on the left side of a bot and one on the right side.

    EDIT: The thing I do not get is why after about 20 seconds or so the program no longer functions and I have to resend it. This is after stopping and starting the servo. How is a bot suppose to roam if the program stops every 20 to 30 seconds?
  • edited 2014-09-03 21:09
    Hmmm, I don't know why it's doing that (stopping every 20/30 seconds). It might be a power related issue causing a reset, but it could also be some other surprise in the library. I'll try it in one of my bots tomorrow.

    Here is an example of code driving a second servo. The library can run up to 14 servos in a single cog, so every time you servo_speed, servo_angle or servo_set with a new pin, the library puts that info in another memory slot, and the code running in another cog that sends servo pulses notices it within 1/50 of a second, and starts sending pulses to the new servo along with all the others.
    /*
      Test SIRC Servo Control 3
    */
    
    #include "simpletools.h"                    // Libraries included
    #include "sirc.h"
    #include "servo.h"
    
    int main()                                  // main function
    {
      sirc_setTimeout(200);                     // -1 if no remote code in 0.2 s
      while(1)                                  // Repeat indefinitely
      { 
        print("%c remote button = %d%c",        // Display button # decoded
              HOME, sirc_button(10), CLREOL);   // from signal on P10
              
        int button = sirc_button(10);           // Check P10 for remote message
        
        if(button == 1)
        {
          servo_speed(18, 100);                 // P18 servo full speed CCW
          servo_speed(19, -100);                // P19 servo full speed CW
        }
        if(button == 3)
        {
          servo_speed(18, -100);                // P18 servo full speed CW.
          servo_speed(19, 100);                 // P19 servo full speed CCW.
        }
        if(button == 2)
        {
          servo_speed(18, 0);                   // Set P18 speed to 0
          servo_speed(19, 0);                   // Set P19 speed to 0
        }
      } 
    }
    
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-03 22:33
    Strange. I tried this earlier and it did not work but it does now!!!! I think you are correct about the power being the issue with the program only running for 20 seconds or so. I am using a 12V wall wart on the Prop BOE so I am pretty sure the servos are pulling too much juice from it. I will try the code on my Wild Thumper to see how well it does. Now I just need to implement the Ping in with this code and get the WT project rolling again after over a year.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-04 10:42
    So this code seems to work OK now. Next question. If I do not want the servos to move unless a button is pushed how would I do that? The number set for this is 255 but when I coded it, it did not work out the way I planned. When I use the else command, it works for 17 (reverse)) but not for 16 (forward) Do not pay attention to the comments. I wait until my code works to fix them.
    /*Test SIRC Servo Control 3
    */
    
    
    #include "simpletools.h" // Libraries included
    #include "sirc.h"
    #include "servo.h"
    
    
    int main() // main function
    {
    sirc_setTimeout(200); // -1 if no remote code in 0.2 s
    while(1) // Repeat indefinitely
    { 
    print("%c remote button = %d%c", // Display button # decoded
    HOME, sirc_button(2), CLREOL); // from signal on P10
    int button = sirc_button(2); // Check P10 for remote message
    if(button == 16)
    {
    servo_speed(14, 100); // P18 servo full speed CCW
    servo_speed(15, -100); // P19 servo full speed CW
    }
    if(button == 17)
    {
    servo_speed(14, -100); // P18 servo full speed CW.
    servo_speed(15, 100); // P19 servo full speed CCW.
    }
    
    
    else
    {
    servo_speed(14, 0); // Set P18 speed to 0
    servo_speed(15, 0); // Set P19 speed to 0
    }
    }
    }
    
  • edited 2014-09-04 13:31
    Yeah, there are a few different ways to do that. Here are two examples:

    1) Keep in mind that the sirc_button function returns -1 if no button is pressed before it times out. In that case, you could forget about the else, and go back to all if statements: if(button == 16)...if(button == 17)...if(button == -1)... You'd then put your stay still code in the if(button == -1) code block.

    2) Set it up with if(...)...else if(...)...else if(...)...else... In your case, it would be if(button == 16)...else if(button == 17)...else... Your else condition would have the stay still code. It looks like you were trying to do this, but maybe missed changing if(button == 17) to else if(button == 17).

    If you think about your code as it is, the problem occurs if you hold anything other than 17. If you hold 16, it briefly tells the robot to go forward, but then it gets immediately overridden by the if(button==17)...else... That else says, if it's anything other than 17, make it stay still. Well, if you are holding 16, that's not 17, so it stays still. So again, you can fix that by changing if(button == 17) to else if(button == 17). Then, your code will say if button is 16, go forward, else if button is 17, go backwards, else stay still.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-04 16:03
    You were exactly correct. All I was missing was the else in front of if for button 17. Thanks for the help. My next task is to add the PING sensor code to this. I really only want the IR code as an override while the PING is driving my WT. Thanks for the help.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-04 16:15
    I forgot, I have commands for left turn and right turn to add. Would that be the same?
    else if(button == 18)
    servo_speed(14, -100); 
    servo_speed(15, 25);
    
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-04 16:22
    Never mind. I got it.
Sign In or Register to comment.