H bridge dc motor help needed

Hi, I'm using an arduino and an h bridge to control a power window motor (basically a dc motor with a strong metal gearbox with an arm attached) and I'm trying to figure out how to program it to only move within a narrow range of motion- like a servo. I can figure out speed and direction but the unfortunate thing is that because it moves at different speeds for each direction a simple back and forth loop eventually leaves the arm all the way extended.

Thanks in advance

Does it draw different current in either direction? If so, and if you're using an L298, you should be able to measure this current via the 'current sense' pin and therefore have a better estimate as to how far it's traveled.

You would still be applying guesswork when it comes to how many milliseconds to apply power for the motor in either direction.

As for exact measurements, you'd really need to hook it up to a potentiometer/rotary-encoder to know exactly how far round the motor has turned? But this would involve finding gears to match, etc...

What h-bridge are you using? Those kinds of motors draw a LOT of current, so your h-bridge needs to be sized for this; you could be overstressing your h-bridge and this might be the cause of your speed troubles.

As far as making it act like a servo; that's a topic unto itself. You have a couple of options:

  1. You can take apart a real servo, and disconnect the motor from the control PCB. Where the motor pins were wired, you wire them up to your h-bridge inputs. You will also need to disconnect the gear train of the servo from the potentiometer in the servo. Then, you re-assemble the servo, and lead the two wires to your h-bridge outside of the servo. The servo's shaft is usually connected directly to the potentiometer, so you can then hook a control horn to the servo output, and link that to the output shaft of the larger motor; typically, you can do this with a small wire linkage, or a gear/belt/chain drive system. Now, when the motor turns, it turns the shaft of the servo, which does its thing like its motor was driving it.

  2. Hook up your own potentiometer with the output feeding an analog input on the Arduino; connect the h-bridge to the Arduino (like you have now). Hook the potentiometer's shaft to the output shaft of the motor. Then, right software to check the angle of the potentiometer, and compare it to a set angle (actually, compare it to a window), and if it is at the same angle (within the window), stop the motor. Actually, to do this "right" takes a lot more explanation; what you really want to do is check the potentiometer, and if the value goes outside the window, drive the motor in the opposite direction of the window's boundary that the cross-over occurred - this is closer to an actual servo mechanism. Finally, for the really advanced system, you can use a PID control (such a PID library exists for the Arduino).

Setup #1 is simple (in concept) to implement, but provides no feedback (unless you hack the potentiometer too to bring out its output; there are tutorials out there that show how to do this); you are also limited to whatever resolution and window the servo is designed for. You may find it difficult to implement, depending on the type, size, and setup of the donor servo. Still, it is something worth trying; you can find further info on this kind of hack by searching for "homemade high power servo" on google; I know I have also posted things here in the forums about such hacks with links, so look them up.

The second option has the advantage of it being as complex and accurate as you like; with a PID control system, it can run the motor at its highest speed until it gets close to the angle needed, then it will slow the motor down until it reaches the destination angle. You can also play with the programming (if your motor is slow - or the output is slow - you may find PID to be overkill; a window comparator algorithm or something else might be all you need - you have the option), you can modify it to suit your needs and accuracy level. The Arduino has enough power to perform this kind of processing and do other things, but you may want to dedicate the Arduino to this task, or to fewer tasks - it will depend on your application and how you set it up. A state machine is key; also you may find that using an interrupt routine on the analog input pin (so when the pin changes value, the interrupt is triggered), and putting your control code there may be the best option (rather than using polling).

Hope this helps - good luck!

:slight_smile:

I'm using an L293- with 12v on a separate power supply to the motor, and it works fine thus far. Those are interesting suggestions, but I just get the sense there is an easier way to get a motorized arm to run through a specific arc. Plus I'm already over my budget. I'm going to try a momentary pushbutton physically attached to either side of the lever that reverses the motor direction, and let you know if it works.

Just use a momentary switch at each end of the arms path to detect when the window is either full open or full closed. Attach the outputs of the switches to pins on the Arduino to tell it to stop the motor. They are called limit switches on CNC machines.
If switch a is closed, the motor will not go in the up direction but will go down.
If switch b is closed, the motor will not go in the down direction but will go up.
Use a third switch to stop the motor if you want the window only part way down.

if you can put up with a small amount of overrun - you could detect the current increase observed when the motor reaches the end of the travel.

Hook the potentiometer's shaft to the output shaft of the motor...

I have done something similar, but ended up connecting the potentiometer to the lever joint. Doing it this way you can measure the angle at all times. If you connect it to the motor shaft (like a rotary encoder) you will have issues if there is a power outage.

So, I've placed a momentary pushbutton at the end of the arc I'd like the arm to run on, and uploaded this code, a really simple modification of the ITP arduino h bridge code-

const int switchPin = 2; // switch input
const int motor1Pin = 3; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 4; // H-bridge leg 2 (pin 7, 2A)
const int enablePin = 9; // H-bridge enable pin
const int ledPin = 13; // LED

void setup() {
// set the switch as an input:
pinMode(switchPin, INPUT);

// set all the other pins you're using as outputs:
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(ledPin, OUTPUT);

// set enablePin high so that motor can turn on:
digitalWrite(enablePin, HIGH);

// blink the LED 3 times. This should happen only once.
// if you see the LED blink three times, it means that the module
// reset itself,. probably because the motor caused a brownout
// or a short.
blink(ledPin, 3, 100);
}

void loop() {
// if the switch is high, motor will turn on one direction:
if (digitalRead(switchPin) == HIGH) {
digitalWrite(motor1Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, HIGH); // set leg 2 of the H-bridge high
delay(2000);
}
// if the switch is low, motor will turn in the other direction:
else {
digitalWrite(motor1Pin, HIGH); // set leg 1 of the H-bridge high
digitalWrite(motor2Pin, LOW); // set leg 2 of the H-bridge low
}
}

/*
blinks an LED
*/
void blink(int whatPin, int howManyTimes, int milliSecs) {
int i = 0;
for ( i = 0; i < howManyTimes; i++) {
digitalWrite(whatPin, HIGH);
delay(milliSecs/2);
digitalWrite(whatPin, LOW);
delay(milliSecs/2);
}
}

And it works well- for the first and second swing of the arm- then the motion begins to get stuttery, and I'm having a hard time figuring out why.

When you say 'stuttery' what do you mean?
Is it start stop, or back and forth?
How fast is the stutter?
Is the stutter near one end of travel, or right across the range of travel?

I notice the code is a bit asymetric, and in one leg there is a delay(), but not in the other:

void loop() {
 if (digitalRead(switchPin) == HIGH) {
     ...
     delay(2000);
   } 
   // if the switch is low, motor will turn in the other direction:
   else {
     ...
   }
 }

Is the travel such that you are pushing against an end stop at one end?

Could it be the H-Bridge chip shutting off to protect itself, then coming back on? When you touch it, is it hot?

(I'm impressed than L293 can cope with the current through a window motor, so I wouldn't be surprised if it is getting a bit stressed. The power to start the motor will be the largest current draw, so if the L293 is near to it's cut-off, maybe once it gets into the stuttering it gets locked in?)

Looking at the code, it looks like only one side of the L293 is controlling the current through the motor. It is okay to use both sides in parallel (according to the data sheet, and my chums who have done it). If the chip is hot, maybe you could use both sides of the L293 to control the motor current, and hence reduce heating.

Can you put a voltmeter, or a couple of LEDs (maybe protected with diodes for reverse voltage protection) on the motor connections to see what is happening to the motor power? Is the voltage varying a lot during the stutter?

Just some thoughts.
GB-)