TIP-120 bi-direction motor control

Near the same time would be acceptable for this project but I can't get this to work:

So what happens?
Put some print statements in to see if you are getting into the correct case statement. The code as posted looks fine.

Yeah, I guess that wasn't very elaborate. What happens is; the first part of the operation will run but he 2nd part never does.

As in:

case 't':    
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);
      break;

The 2nd pin fires, but not the 3rd. :drooling_face:

Oh and after some assembly time, I finally got to drive this thing around Monday night, it works perfectly! Thank you all for all of the help,
I feel like I have learned a few things too. =D

So, its time to take this code a step farther. Everything in the following code works perfectly for me. I am currently controlling 2
motors with the option to add another 2 motors, hence the 2x (Res) entries. I would like to add 2 servos into the mix, one on
Pin 5 and one on Pin 6.

#include <AFMotor.h>

AF_DCMotor motor1(1, MOTOR12_64KHZ); // create motor #1, 64KHz pwm 
AF_DCMotor motor2(2, MOTOR12_64KHZ); // create motor #2, 64KHz pwm 
AF_DCMotor motor3(3, MOTOR12_1KHZ);  // create motor #3, 1KHz pwm (Res)
AF_DCMotor motor4(4, MOTOR12_1KHZ);  // create motor #4, 1KHz pwm (Res)

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
}

void loop() {
  // read the sensor:
  if (Serial.available() > 0) {
    int inByte = Serial.read();

    int speed; // Local variable

    //Motor 1 - Full Speed

      switch (inByte) {
    case 'w':   
      motor1.setSpeed(225);
      motor1.run(FORWARD);     // Motor Runs Forward
      break;

    case 'k':   
      motor1.run(RELEASE);     // Motor Stops
      break;

    case 's':   
      motor1.setSpeed(225);
      motor1.run(BACKWARD);    // Motor Runs Backwards
      break;

      //Motor 2 - Full Speed

    case 'e':   
      motor2.setSpeed(225);
      motor2.run(FORWARD);     // Motor Runs Forward
      break;

    case 'l':   
      motor2.run(RELEASE);     // Motor Stops
      break;

    case 'd':   
      motor2.setSpeed(225);
      motor2.run(BACKWARD);    // Motor Runs Backwards
      break;

    default:
      // turn all the connections off:
      for (int thisPin = 2; thisPin < 7; thisPin++) {
        digitalWrite(thisPin, LOW);
      }
    }
  }
}

I know I have to add:

#include <Servo.h>
 
Servo myservo1;  // create servo object to control servo1
Servo myservo2;  // create servo object to control servo2

But as to where and not interrupt the motor code I am not sure. Do you add it to this instance or add it to a following instance?
Btw I am calling everything between the "}" instances.

Can I add the
#include <Servo.h> after the #include <AFMotor.h>
and the

Servo myservo1;  // create servo object to control servo1
Servo myservo2;  // create servo object to control servo2

after the

AF_DCMotor motor1(1, MOTOR12_64KHZ); // create motor #1, 64KHz pwm 
AF_DCMotor motor2(2, MOTOR12_64KHZ); // create motor #2, 64KHz pwm 
AF_DCMotor motor3(3, MOTOR12_1KHZ);  // create motor #3, 1KHz pwm (Res)
AF_DCMotor motor4(4, MOTOR12_1KHZ);  // create motor #4, 1KHz pwm (Res)

and just add entries like

case 'T':   
      myservo1.run(FORWARD);    // Servo Runs Forward
      break;

after

switch (inByte) {
    case 'w':   
      motor1.setSpeed(225);
      motor1.run(FORWARD);     // Motor Runs Forward
      break;

Thank you for your help in Advance. :%
-Ec7

Mostly yes, but not this...

case 'T':   
      myservo1.run(FORWARD);    // Servo Runs Forward
      break;

Look up the servo library in the reference section.

Yes, but I am not looking for it to move from one position to another, I am wondering if you can move it similar to a motor

Press T and it will move in desired direction
maybe press Y and it will stop.

  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);

Above reference code not quite it.

Can the code be edited like

case 'T':
myservo1.write(Forward);
break;

case 'Y'
myservo1.write(RELEASE)
break;

case 'U':
myservo1.write(Backwards);
break;

Possible?

Yes, but I am not looking for it to move from one position to another, I am wondering if you can move it similar to a motor

There are two kinds of servos. Real servos and continuous rotation "servos". Continuous rotation "servos" aren't really servos any more.

Servos can not be "run like motors". "Servos" can.

Servos are meant to control things like steering or throttle. Neither of these are possible scenarios for "just run like a motor".

Referring to the continuous rotation, or previously stated
"broken" servos. I can use these because they still fit into the
bracket and I have 2 laying around.

Can you somehow drive a pin high / low to control it?

Basically this is a pan / tilt assembly for a camera and i need
it to work similar to the previous motor code that I was working
on.

Ideas?

I have 2 "broken servos" and 2 180 degree servos. the nice idea
about the 180 degree servos is that it would only allow the cam to
turn 90 degrees in either direction and would avoid tangling cables.

Continuous rotation servos are still driven with the servo library. One 'position' (usually around 90) represents 'stop', then positions higher or lower than 'stop' give proportionally higher speed in one direction or the other.

Problem solved. I took the continuous servo apart and wired directly to the motor. Now I can just control it the same way I control my other motors.

Okay back to servos.

This should actually be possible:

Press a key to have the servo move to and stop on a pre-defined degree.

say press X and the servo will move to 0

Press Y and the servo will move to 90

Press Z and it will move to -90

Something like:

#include <Servo.h>
 
Servo myservo1;  // create servo object to control a servo

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps

void loop() {
  // read the sensor:
  if (Serial.available() > 0) {
    int inByte = Serial.read();

switch (inByte) {

case 'X':
myservo.write(0);              // tell servo to go to position 0
    delay(15);

case 'Y':
myservo.write(90);              // tell servo to go to position 90
    delay(15);

case 'Z':
myservo.write(-90);              // tell servo to go to position -90
    delay(15);

Servo.write() takes an argument from 0 to 180 (representing degrees) which are the extremes of the servo travel, 90 degrees is in the middle.

JFYI Servo.write will interpret any value that is out of band for degrees of movement as time in microseconds. So ensure adequate constraints on any value calculated and passed to the servo class.

Good Evening, It's been awhile.

I would like to revisit and continue the Servo idea.

Take a servo and control it (move to X degree) when you press a keyboard key, (Move to Y degree) when you press another. (Working Code Below)

I am also interested in learning how to make it move in X number of degrees until a stop button has been pressed.

The following code will move to 90 degrees when q is pressed and 170 when w is pressed. How could you add an interrupt that would stop the servo if a digital button was pressed say before it go to 170 degrees? (like its traveling and stop it at 136 degrees) [This is for a robotic claw that I want to pick objects up without crushing them / straining the servo]

#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
 
int pos = 0;    // variable to store the servo position

void setup() {
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
    for (int thisPin = 9; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);

switch (inByte) { 
    case 'q':    
    	myservo.attach(9);
	myservo.write(90);  // set servo to mid-point
	 break; 

    case 'w':    
    	myservo.attach(9);
	myservo.write(170);  // set servo to mid-point
	 break; 

 	  default: 
      // turn all the connections off (Except Motorshield): 
      for (int thisPin = 9; thisPin < 11; thisPin++) { 
        digitalWrite(thisPin, LOW); 
		
		}
		}
		}}}

Thanks =)

How could you add an interrupt that would stop the servo if a digital button was pressed say before it go to 170 degrees?

Easy. You write the code is a way that does NOT require interrupts. Move the servo a little. See if the servo should be moved some more (the switch is not pressed). If so. move it some more. If not, don't.

Hello again PaulS.

The thinking I had behind interrupts was that perhaps I could add a timing mechanism to the code so that if: Claw closes, the button is in the claw, claw closes on an object and presses the button, timer is allowing the servo to move a few more milliseconds, this allows the claw to "grip". To reverse this; hit the other key and claw opens to repeat the process all over again. - My thinking anyways.

Possible?

Possible?

Anything's possible. But, let's discuss what is really needed. How soon after contact do you need to know that contact has occurred? With an interrupt, you'd know within nanoseconds. Is that necessary? How soon can you set a flag that loop() checks to determine that it needs to do something different? Is that less than the time needed to determine, using polling, that loop() needs to do something different?

I don't think it has to be extremely precise. It needs to not damage the servo by trying to close the claw on an object (and not shutting down), but allow enough time to "grip" said object. I am also hoping to have it be adjustable.

Teach me the:

How soon can you set a flag that loop() checks to determine that it needs to do something different? Is that less than the time needed to determine, using polling, that loop() needs to do something different?

and I will give it a shot.

Thank you.

Teach me the:

I don't understand what you are asking.

If you use an interrupt, you can do something when the interrupt happens. When the interrupt is over, the program resumes executing where it was before the interrupt occurred. You can not change that.

What you can do, in the interrupt service routine, is to set a flag.

In loop(), or other functions, you can periodically, check the status of the flag. If it is true, do one thing (maybe return). If it is false, do something else.

Of course, instead of checking a flag, you could check the pin state.

In your program, you could have the switch trigger an interrupt. In the interrupt handler, you can not make the claw stop closing. All you can do is set a flag that says that the claw should stop closing.

In the "close the claw" function, you might have a while loop that is moving the claw in small increments.

while(clawNotFullyClosed)
{
}

With the interrupt method, you'd change that to

while(clawNotFullyClosed && !clawIsToStop)
{
}

You's set clawIsToStop to false before this loop, and you'd set it to true in the ISR.

With polling, you'd use

while(clawNotFullyClosed && digitalRead(clawSwitch) != HIGH)
{
}

Or LOW, depending on how the switch is wired.

I think that you can see that, in this case, using interrupts buys you nothing. You won't know whether the switch was closed and interrupt has been triggered any sooner than you'd learn that the switch was closed.

Good morning,

In the interrupt handler, you can not make the claw stop closing. All you can do is set a flag that says that the claw should stop closing.

Oh that's not good. It kind of sounds like what happened out at Chernobyl. "We sent the command, the indicator light came on; Maybe the valve is open?"

You won't know whether the switch was closed and interrupt has been triggered any sooner than you'd learn that the switch was closed.

I am needing this so that the unit does not damage its self. I could program it in with the user in control; as long as you press X the claw closes, but this leave way to much room for error (user error, latency in sending the command over wireless, etc)

Originally I was going to use a motor and do the "as long as you press X the claw closes" trick. I was going to wire said motor so that both the + and the - had 2 leads. I would then wire a momentary button to one of the leads so that when the claw closed on something it would depress and the power would be cut to the motor. The other 2 leads could then be powered by another button press "Y"(that would be programmed to drive the pin of the first set of powered leads to Low) so that you could still be able to reopen the claw and release its grip on an object. X to close, Y to open.

Instead I figured I would be able to do this in software and learn a more sophisticated way of doing things. There has to be a way of accomplishing such a simple task =)

There has to be a way of accomplishing such a simple task =)

There is. As an example, suppose that you are using a servo to close the claw. Suppose that the servo starts at 180 with the claw open and will be at 35 when the claw closes without grasping anything. Suppose, too, that there is a switch that is pressed when the claw makes contact with an object. You could write a function like this to grab an object:

void closeTheClaw()
{
   int pos = 180;
   while(pos > 35 && digitalRead(clawContactSwitchPin) != LOW)
   {
      claw.write(pos--);
   }
}

Now, if the switch were connected to interrupt pin, you could have an interrupt handler:

volatile bool stopClaw = false;

void screamStop()
{
   stopClaw = true;
}

Then, the closeTheClaw() function would look like:

void closeTheClaw()
{
   int pos = 180;
   while(pos > 35 && !stopClaw)
   {
      claw.write(pos--);
   }
}

As you can see, though, the complexity of interrupts, and the need to develop and test an interrupt handler would not result in the slaw stopping any sooner.