Control del servomotor con microcontrolador ATmega328p

1

Durante un tiempo, he estado trabajando con Arduino, pero hace aproximadamente un mes, cambié a usar únicamente el microcontrolador ATmega328-PU. Yo uso el IDE Atmel Studio. Hasta ahora, he parpadeado con éxito un LED, he usado programas con botones / interruptores y he usado la función Fast PWM para atenuar un LED. Actualmente, estoy intentando conducir un servomotor utilizando Fast PWM, pero he tenido poco éxito. No he encontrado ningún código fuente que funcione para las necesidades específicas de mi microcontrolador, y realmente no tengo la capacidad de cambiar todos los parámetros, ya que todavía estoy aprendiendo.

El siguiente es el código que he desarrollado. No funciona, pero esperaba que alguien pudiera arreglarlo. El servo se mueve en una dirección, pero no se detiene, y simplemente termina moliendo el engranaje del eje del motor, lo que indica que esto podría ser un problema con la longitud de la onda. Una pregunta adicional: ¿existe una ecuación para convertir el grado en longitud de onda PWM? Gracias!

Especificaciones del microcontrolador:

  • Modelo - ATmega328-PU
  • 16,000,000 hz de cristal
  • 28 pines
  • Usando el temporizador de 8 bits

Servo:

  • Modelo de servo: Tower Pro SG90
  • Frecuencia de servo 50 hz (¿es este estándar?)

Código:

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

int main(void)
{

    DDRD |= (1 << DDD6);
    // PD6 is now an output - corresponds to OCR0A

    TCCR0A |= (1 << COM0A1);
    // set non-inverting mode

    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // set fast PWM Mode

    ICR1 = 39999;

    OCR0A = ICR1 - 2000;
    // gives servo motor position

    TCCR0B |= (1 << CS01);
    // set prescaler to 8 and starts PWM


    while(1)
    {
    }
}
    
pregunta Mischief City

1 respuesta

1

Hay varios problemas con tu código: -

  1. En el modo de no inversión, el pulso PWM comienza con un conteo de 0 y termina en la comparación de comparación, por lo que debe cargar el ancho del impulso directamente en el registro de comparación (no restarlo del período).

  2. ICR1 es parte de Timer1 de 16 bits, no de Timer0 de 8 bits.

  3. Un temporizador de 8 bits no aceptará valores de 16 bits.

Para producir PWM de 16 bits, debe usar el temporizador 1, entonces los números 2000 (para el ancho de pulso de 1 ms) y 3999 (para el período de 20 ms) funcionarán correctamente. Así que cambie todas las referencias de Timer0 a sus equivalentes de Timer1, es decir. TCCR0A - > TCCR1A, COM0A1 - > COM1A1, etc. y configure PB1 para emitir el pulso del servo.

    
respondido por el Bruce Abbott

Lea otras preguntas en las etiquetas