11/1/2006 update:
Things have slowed a bit. I decided that the best way to test the line following was to have a moving platform. Therefore I decided to rebuild my H-Bridge circuit. I decided to compare the circuit I built nearly a decade ago with the reference design. Wow, not sure what I was thinking but my component values for the RC blanking circuit were way not right, and my current sense resistor wasn’t even connected.
Locked anti-phase
Previously I was using PWM of the enable pin for speed control and the phase pin for direction. Recently I read about PWM of the phase call locked anti-phase control. At 50% the motor is locked and thus neither moves forward or backward. If the PWM is less than 50% then it moves backward, greater than 50% forward. How much greater or less than 50% controls the speed. So now you get speed and direction with one control line.
New circuit
I soldered up my new circuit with more correct values except the current sense resistor. RS doesn’t carry a .5ohm resistor and paying $5 for a resistor is nuts. Long story short 10ohms was too big and I ended up removing the current sensing and blanking components from the circuit to make it work. Also I need to get a smaller tip for my iron as I had a short (or two) that I had to trace down too. Once I’m sure on my circuits, drafting a PCB seems like a good idea.
Testing
To test my circuit I first tried it as a servo. I must have been high from solder fumes because I knew that PWM of a servo doesn’t use a duty cycle it uses pulse timing (1.5ms for center, 1ms for 0 degrees, 2ms for 180 degrees roughly). So as a quick and dirty I bit banged a 500ms 50% duty square wave. The motor was locked alright but it was singing too. So I tried smaller periods and settled on 50ms. I’m hoping that using the built in phase correct PWM of Timern that I can get a nice smooth 127 steps in both directions with little wasted power at “stop”. I am thinking that I’ll need to add a brake line for each motor to de-energize the motors at 0 speed (50% duty).
PWM
There are 4 timers on the ATMega128 Timer 0 and 2 are 8-bit and Timer 1 and 3 are 16 bit. All are capable of PWM using output compares. If I only need/want 127 steps then and 8 bit timer is enough, but I can see no penalty in using a 16 bit timer either. So here is the scenario. Using the phase-correct mode of operation the period of the waveform is set by the WGMn3:0 bits. Either 0x00FF, 0X01FF or 0x03FF. For 8-bit 0x00FF is what I’ll use. TCNTn will count up to 0x00FF and then count down to zero. If OCRnx == 0 then the output will be zero. Similarly if it is 0x00FF (or TOP) then output will be 1. So first step is to decide the actual period and set the prescaler to get close. The CPU clock is 16MHz. A prescaler of 64 will give us a 4us timer clock source. This means our period will be roughly 2ms (2 * 255 * 4us) or 500Hz. Now we need to configure the Output Compare bits in TCCRnA. We will configure them to 2 (10b) to clear the output bit on up counting match and set it on down counting match. Finally we need to set the DDRx bits for our output pins.
void timer1PWMInit (void)
{
// Set prescaler
TCCR1B = 0x03; // Timer clocked at F_CPU/64
// Init to 8bit phase correct mode 1
TCCR1A = _BV(WGMA0);
// Configure Output compares for A and B mode 2
// output bit will be cleared on match while up counting and set on match while down counting
TCCR1A = _BV(COMA1) _BV(COMB1); ;
// Set DDRB pins 5 and 6 for output
DDRB = _BV(OC1A) _BV(OC1B);
// set motors to 0 or 50% duty for locked anti-phase controller
OCR1A = 0x7F;
OCR1B = 0x7F;
// Enable timer1 overflows
TIMSK = _BV(TOIE1); // enable TCNT1 overflow
}
Onward,
Jay