# 7. Using the Trimmer Pot for Motor Control

The following sample program uses the motor control functions defined in Section 5 to drive the motors in response to the trimmer potentiometer position. Motors 1 and 2 transition linearly from full forward to stationary to full reverse as the potentiometer voltage varies from 0 to 5 V. This program uses the ATmega48/168/328’s analog-to-digital converter to determine the position of the potentiometer.

#include <avr/io.h>

int main()
{
motors_init();

// On the Orangutan and 3pi, the user trimpot can be optionally jumpered
// to ADC7 using a blue shorting block; the Orangutan and 3pi ship
// with this shorting block in place (this shorting block is required
// by this program).  On the Baby Orangutan, the trimpot is permanently

// bit 6 clear: don't start conversion
// bit 5 clear: disable autotrigger
// bit 4: ADC interrupt flag
// bit 3 clear: disable ADC interrupt
// bits 0-2 set: ADC clock prescaler is 128

ADMUX = 0x07;		// bit 7 and 6 clear: voltage ref is Vref pin
// bit 4 not implemented
// bits 0-3: ADC channel (channel 7)

while (1)			// loop forever
{
long sum = 0;
unsigned int avg, i;

// Here we accumulate 500 conversion results to get an average ADC.
// According to the ATmegaxx8 datasheet, it takes approximately 13
// ADC clock cycles to perform a conversion.  We have configured
// the ADC run at IO clock / 128 = 20 MHz / 128 = 156 kHz, which
// means it has a conversion rate of around 10 kHz.  As a result,
// it should take around 50 ms to accumulate 500 ADC samples.
for (i = 0; i < 500; i++)
{
while ( ADCSRA & ( 1 << ADSC ))    // wait while converting
;
}
avg = sum / 500;    // compute the average ADC result

// set motors based on trimpot position (middle value = motor speed 0)
//  avg is a 10-bit value and hence ranges from 0 to 1023
if (avg <= 511)
{
M1_forward((511 - avg) / 2);
M2_forward((511 - avg) / 2);
}
else
{
M1_reverse((avg - 512) / 2);
M2_reverse((avg - 512) / 2);
}
}

return 0;
}