Controlling a servo with a potentiometer

 avatar
subratasarkar20
c_cpp
5 months ago
2.0 kB
6
Indexable
/*
 * ADC_Servo.cpp
 * Author: subrs
 */

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

void ADC_Init() 
{ 
    ADMUX = (1 << REFS0);										// AVCC as reference, ADC0 selected						
    
    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);			// Enable ADC, set prescaler to 64 (for 1MHz clock)			
}

uint16_t ADC_Read(uint8_t channel) 
{  
    ADMUX = (ADMUX & 0xF8) | (channel & 0x07);					// Select the ADC channel (in this case, channel 0 for the potentiometer)	
  
    ADCSRA |= (1 << ADSC);										// Start conversion							

    while (ADCSRA & (1 << ADSC));								// Wait for conversion to complete
    
    return ADC;													// Return the ADC result (10-bit value)
}

void setupPWM() 
{
    // Set Fast PWM mode with ICR1 as TOP (Mode 14: WGM13:WGM10 = 14)
    TCCR1A = (1 << WGM11);
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10);  // Prescaler = 64

    // Set non-inverting mode on OC1A (Clear OC1A on compare match, set at BOTTOM)
    TCCR1A |= (1 << COM1A1);

    // Set TOP value for 50Hz (ICR1 = 311)
    ICR1 = 311;

    // Set PD5 (OC1A) as output for PWM signal
    DDRD |= (1 << PD5);
}

void setServoPosition(int pulseWidth) 
{
    // Set the OCR1A register for the specified pulse width
    OCR1A = pulseWidth;
}

int main(void) 
{
    // Initialize ADC and PWM for controlling the servo
    ADC_Init();
    setupPWM();

    uint16_t adc_value;
    int pulseWidth;

    while (1) 
    {
        // Read the ADC value from the potentiometer (channel 0)
        adc_value = ADC_Read(0);								

        // Map the ADC value (0 - 1023) to pulse width for the servo (1ms to 2ms)
        pulseWidth = (adc_value / 57) + 16;							// (1024 / 180) + 16 => Pulse width between 16 and 31
        setServoPosition(pulseWidth);								// Set the servo position

        _delay_ms(50);  // Small delay for stability
    }
}
Editor is loading...
Leave a Comment