Shop OBEX P1 Docs P2 Docs Learn Events
Controlling a servo — Parallax Forums

Controlling a servo

dcgartindcgartin Posts: 6
edited 2013-04-10 23:19 in Learn with BlocklyProp
Hello,

I have modified a servo for 360 degrees of continuous rotation, and I have written some code to make the servo rotate 1 degree every time I press a button on the keyboard and press enter. The problem is I have to hit enter each time and repeatedly hit the key to keep it going. Is there a way to program it so I can just hold the key down and it continue to move till I take my finger off?


Thanks,

Chadd

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-03-13 08:55
    Not really. The problem has to do with how the PC and the Stamp (I assume that's what you're using) communicate. When you hit the Enter key, the PC sends the character as a group of pulses to the Stamp. If the Stamp is listening with a SERIN or DEBUGIN statement, it will recognize the group of pulses as a character and the SERIN or DEBUGIN statement will finish and your program will continue and move the servo a little bit. The PC keyboard likely has a repeat function so it will send the same character repeatedly (a couple of times a second) to the PC if you hold the key down. The PC will send the repeated characters to the Stamp and the servo will move a little as long as you hold the key down. That's probably not quite what you're asking. You want the Stamp to be able to detect whether the key is held down and the PC / Stamp configuration you're using can't do that.

    You could use a pushbutton (either bought or homemade with a paperclip and a few screws on a block of wood. The "What's a Microcontroller?" tutorial shows how to use a pushbutton in a program. The BoeBot uses something similar (whiskers they call them) for detecting obstacles.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-03-13 09:05
    Chadd,

    Are you using a Basic Stamp to do this?

    What code are you using?

    Here's a link to a tutorial about posting code in the forum.

    attachment.php?attachmentid=78421&d=1297987572

    A Basic Stamp can only do one thing at a time but I'd think if should be able to do what you want but it would be a lot easier to show how to modify your code to do so than to write a program from scratch.

    My guess is you'd want to include a check for serial input between commands to pulse the servo.

    I'm not sure, but I think there should be time for this within the servo's refresh period.
    Let's see the code you have so far.

    Edit: Mike bet me to it and with a better answer. I almost suggested using a button.
  • W9GFOW9GFO Posts: 4,010
    edited 2013-03-13 11:05
    On page 408 of the BASIC Stamp Syntax and Reference Manual (accessed from the help menu of the editor) it explains how to use the timeout feature. You can have SERIN wait a specified number of milliseconds for the character, if it does not appear then the program will jump to another subroutine - such as a stop routine.

    Another tip, if you are using the keyboard to control something in real time you will want to go into control panel and change the repeat rate of your keyboard to it's lowest setting.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-03-13 11:48
    About the timeout for SERIN ...

    The only time the Stamp will accept an incoming character from the PC is when the SERIN is actually executing. You can use a timeout, but the Stamp will ignore any incoming characters when it's executing other statements like the PULSOUT you're using for servo control. While the Stamp is waiting for a character to be received, it won't be able to produce pulses for the servo and the servo will eventually shut off until the next pulse comes in.
  • dcgartindcgartin Posts: 6
    edited 2013-03-13 11:52
    Here's the code I have so far.
    #include <Servo.h>
    
    Servo servo_base;
    Servo servo_r_tread;
    Servo servo_l_tread;
    Servo servo_shoulder;
    Servo servo_elbow;
    Servo servo_claw;
    
    byte commandByte;
    
    int servoangle_base = servo_base.read();
    int servoangle_r_tread = servo_r_tread.read();
    int servoangle_l_tread = servo_l_tread.read();
    int servoangle_shoulder = servo_shoulder.read();
    int servoangle_elbow = servo_elbow.read();
    int servoangle_claw = servo_claw.read();
    
    void setup()
    {
      Serial.begin(9600);
      
      servo_base.attach(8);
      servo_base.write(servoangle_base);
      servo_r_tread.attach(9);
      servo_r_tread.write(servoangle_r_tread);
      servo_l_tread.attach(10);
      servo_l_tread.write(servoangle_l_tread);
      servo_shoulder.attach(11);
      servo_shoulder.write(servoangle_shoulder);
      servo_elbow.attach(12);
      servo_elbow.write(servoangle_elbow);
      servo_claw.attach(13);
      servo_claw.write(servoangle_claw);
    }
    
    void loop()
    {   
      if(Serial.available() > 0)
        {
          commandByte = Serial.read();
          if(commandByte == 'Q')
          {
            servoangle_l_tread = servoangle_l_tread+10;  
            servo_l_tread.write(servoangle_l_tread);
          }
          if(commandByte == 'A')
          {
            servoangle_l_tread = servoangle_l_tread-10;
            servo_l_tread.write(servoangle_l_tread);
          }
          if(commandByte == 'W')
          {
            servoangle_r_tread = servoangle_r_tread + 10;
            servo_r_tread.write(servoangle_r_tread);
          }
          if(commandByte == 'S')
          {
            servoangle_r_tread = servoangle_r_tread - 10;
            servo_r_tread.write(servoangle_r_tread);
          }
          if(commandByte == '>')
          {
            servoangle_base++;
            servo_base.write(servoangle_base);
          }
          if(commandByte == '<')
          {
            servoangle_base--;
            servo_base.write(servoangle_base);
          }
          if(commandByte == 'T')
          {
            servoangle_shoulder++;
            servo_shoulder.write(servoangle_shoulder);
          }
          if(commandByte == 'Y')
          {
            servoangle_shoulder--;
            servo_shoulder.write(servoangle_shoulder);
          }
          if(commandByte == 'U')
          {
            servoangle_elbow++;
            servo_elbow.write(servoangle_elbow);
          }
          if(commandByte == 'I')
          {
            servoangle_elbow--;
            servo_elbow.write(servoangle_elbow);
          }
          if(commandByte == 'O')
          {
            servoangle_claw++;
            servo_claw.write(servoangle_claw);
          }
          if(commandByte == 'P')
          {
            servoangle_claw--;
            servo_claw.write(servoangle_claw);
          }
       }
    }
    
    
  • Mike GreenMike Green Posts: 23,101
    edited 2013-03-13 12:05
    Ah, you're using an Arduino. We can't help you with the specifics of Arduino programming, but I can give you a general outline of what's needed. Basically, you've got what's called a "state machine" with two "states" and your program has to remember which state it's in to figure out what it should do. Let's say you're using the period key to start and stop the servo. You might have:
    // ---------- Initialization code (for Arduino, this goes in setup)
    state = 0;   // Initially in state 0.  state is a byte variable
    
    // ---------- Repeated execution (for Arduino, this goes in loop)
    if (commandByte == '.')  {
       if (state == 0) {   // In state 0
          // Start the servo moving
          state = 1;   // Go to next state
       }
       else {   // In state 1
          // Stop the servo moving
          state = 0;   // Go to initial state
       }
    
  • AndroidAndroid Posts: 82
    edited 2013-04-08 17:42
    I am no Arduino user(Wish I had one) but it would be much much easier to just use a pushbutton. What is the point of your project?
  • NWCCTVNWCCTV Posts: 3,629
    edited 2013-04-10 23:19
    Is switching to a stepper motor an option? If so, you could write the program to move x amount of steps and would probably be more accurate than a servo.
Sign In or Register to comment.