Home |

Trigat

Attiny85 Servos with C

10-14-2017

I have been reading up on the Attiny85 AVR. I wanted to control servos without using Arduino so I wrote the code below.

Language or Platform: C

Image

Code:

//      Attiny85 AVR Microcontroller
// C program for controlling 2 servos using a potentiometer and button.
// Written by Josh M

// I'm new to Attiny85 registers so this code will not be perfect
// and may need some tweaking.

// Put potentiometer on a pin such as PB3
// Put push button on a pin such as PB4
// Put servo on PB0 for OCR0A
// Put servo on PB1 for OCR0B

#define F_CPU 1000000UL // for 1Mhz Attiny85
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>

// Predefined Servo position values for OCR0A
// You need to fine tune this for different servos.
// Servo 1
#define SERVO1_ONE 8  // servo position
#define SERVO1_TWO 12
#define SERVO1_THREE 16
#define SERVO1_FOUR 19  
#define SERVO1_FIVE 23
#define SERVO1_SIX 28
#define SERVO1_SEVEN 31

// Servo 2
#define SERVO2_ONE 15  // servo position
#define SERVO2_TWO 18
#define SERVO2_THREE 20
#define SERVO2_FOUR 22
#define SERVO2_FIVE 24
#define SERVO2_SIX 27
#define SERVO2_SEVEN 30

// used for button
uint8_t position = 1;

int main(void)
{
	// set potentiometer as input, other pins as output
	DDRB = 0b00111;  // Example: 0b10111 would be pin 3.  0b11011 would be pin 2.

	// Enable internal pull-up resistor on PB3(potentiometer) and PB4
    // and set others low
	PORTB = 0b11000;  // PB3 and PB4 set high
	
	// Mode 3 - Fast PWM
	TCCR0A |= (1<<WGM01) | (1<<WGM00);

	// Set OC0A/OC0B at BOTTOM (non-inverting mode)
	// Clear OC0A/OC0B on Compare Match
    // *** This may need to be adjusted ****
	TCCR0A |= (1<<COM0A1)|(1<<COM0B1); // (1<<COM0B1) controlls pin1
                                       // (1<<COM0A1) controlls pin0
	// Set prescaler to 64
	// 1 MHz / 64*256 = 61 Hz PWM frequency
	TCCR0B |= (1<<CS01) | (1<<CS00);

	// Start with the servo in center position
	OCR0A = SERVO1_THREE;
	OCR0B = SERVO2_FOUR;

    unsigned int adc_value; // Variable to hold ADC result

    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS0);
    // ADEN turns on ADC
    // ADPS2 and ADPS0 set to make division factor 32
    ADMUX = PINB3; // ADC input channel set to Pin3 (potentiometer pin)

    while (1)
    {
		// For potentiometer (servo 1)
        ADCSRA |= (1 << ADSC); // Start conversion
        while (ADCSRA & (1 << ADSC)); // Wait for conversion to complete
        adc_value = ADCW; // Store ADC value

        if (adc_value > 880 && adc_value < 1023)
        {
            OCR0A = SERVO1_ONE;
        }
        else if (adc_value > 680 && adc_value < 880)
        {
            OCR0A = SERVO1_TWO;
        }
        else if (adc_value > 570 && adc_value < 680)
        {
            OCR0A = SERVO1_THREE;
        }
        else if (adc_value > 450 && adc_value < 570)
        {
            OCR0A = SERVO1_FOUR;
        }
        else if (adc_value > 310 && adc_value < 450)
        {
            OCR0A = SERVO1_FIVE;
        }
        else if (adc_value > 200 && adc_value < 310)
        {
            OCR0A = SERVO1_SIX;
        }
        else if (adc_value < 100)
        {
			OCR0A = SERVO1_SEVEN;
        }
        
        // For button press (servo 2)
	    if (bit_is_clear(PINB, 4)) 
        {
	    	switch(position)
	    	{
                    // delay makes servo run smoother
	    		case 0:
	    			OCR0B = SERVO2_ONE;
	    			_delay_ms(600);
		    		break;
		    	case 1:
		    		OCR0B = SERVO2_TWO;
		    		_delay_ms(600);
		    		break;
		    	case 2:
		    		OCR0B = SERVO2_THREE;
		    		_delay_ms(600);
		    		break;
		    	case 3:
		    		OCR0B = SERVO2_FOUR;
		    		_delay_ms(600);
		    		break;
		    	case 4:
		    		OCR0B = SERVO2_FIVE;
		    		_delay_ms(600);
		    		break;
		    	case 5:
		    		OCR0B = SERVO2_SIX;
		    		_delay_ms(600);
		    		break;
		    	case 6:
		    		OCR0B = SERVO2_SEVEN;
		    		_delay_ms(600);
		    		break;
		    	default:
		    		break;
	        }
		}
		position++;
		if(position == 7)
			position = 0;          
    }
}

Back