Arduino Uno PWM - Resultados extraños

0

He estado experimentando con los modos de generación de forma de onda PWM en el ATMega328P. He estado obteniendo algunos resultados extraños y no puedo entender si es un problema con la forma en que escribo el firmware o cómo interpreto el hoja de datos .

Aquí está el primer fragmento de código que escribí para emular la función analogWrite ():

// Waveform Generation Mode 0
// Table 15-4 of the datasheet

void setup()
{
  DDRB = (1<<PB1); // set pin 9 as output

  TCCR1A |= (1<<COM1A1);
  OCR1A = 125;
}

void loop()
{
}

El código anterior produce una salida de voltaje promedio de alrededor de 2.5V (ciclo de trabajo del 49%) fuera del pin 9. Lo extraño (para mí) es que, según la hoja de datos, TIMER1 es un temporizador de 16 bits, por lo que debe desbordarse a 65536 garrapatas. Por lo que entiendo, configurar OCR1A entre 0 y 65535 cambiará el ciclo de trabajo del pulso. Entonces, habiendo establecido el OCR1A en 125, ¿no debería estar obteniendo una salida de alrededor de 0.01 V en lugar de 2.5V? Los resultados parecen implicar que el reloj se está desbordando en 255.

Para mi segunda incursión en tierra PWM, quise intentar crear una señal de 2.5V usando el modo rápido PWM de ATMega. Esto es lo que obtuve:

// Waveform Generation Mode 14
// Table 15-4 of the datasheet

void setup()
{
  DDRB = (1<<PB1);

  TCCR1A |= (1<<COM1A1) | (1<<WGM11);
  TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10);

  ICR1 = 19999;
  OCR1A = 10000;
}

void loop()
{
}

Establecí ICR1 (el valor de desbordamiento) arbitrariamente en 20000 tics, luego establecí OCR1A (el valor de comparación) en aproximadamente la mitad. Establecí el canal A en modo no inversor, pero (creo) no habría hecho una diferencia si lo configurara en modo inversor. Cuando envié esto al Arduino, obtuve un promedio de voltaje constante de 5V (100% de ciclo de trabajo) del pin 9, y no puedo por la vida de mí averiguar por qué.

Apreciaría cualquier información que pueda ofrecer.

    
pregunta

2 respuestas

0

Respondido por joeymorin en AVRfreaks:

Tenga en cuenta que en el Uno, el código de inicio de Arduino que se ejecuta antes de su configuración () configura muchas cosas, incluidos los tres temporizadores en el 328P.

Desde wiring.c :

   sbi(TCCR0A, WGM01); 
   sbi(TCCR0A, WGM00); 
   sbi(TCCR0B, CS01); 
   sbi(TCCR0B, CS00); 
   sbi(TIMSK0, TOIE0); 

   sbi(TCCR1B, CS11); 
   sbi(TCCR1B, CS10); 
   sbi(TCCR1A, WGM10); 

   sbi(TCCR2B, CS22); 
   sbi(TCCR2A, WGM20);

Esto inicia los tres temporizadores con un preescalador de 64.

TIMER0 se coloca en el modo 3 (PWM rápido) con la interrupción de desbordamiento habilitada para admitir las funciones de temporización (milis (), micros () y retraso ()).

TIMER1 se coloca en el modo 1 (PWM fijo de fase de 8 bits).

TIMER2 se coloca en el modo 1 (PWM de fase correcta).

void setup() 
{ 
  DDRB = (1<<PB1); // set pin 9 as output 

  TCCR1A |= (1<<COM1A1); 
  OCR1A = 125; 
} 

void loop() 
{ 
} 

Ya que WGM10 en TCCR1A ya está configurado, el ajuste COM1A1 habilitará la salida PWM en modo no inversor, tal como lo haría analogWrite ().

  

TIMER1 es un temporizador de 16 bits, por lo que debe desbordarse en 65536 tics. Desde   Lo que entiendo al configurar OCR1A entre 0 y 65535 cambiará el   Ciclo de trabajo del pulso. Entonces, habiendo puesto el OCR1A en 125, no debería   ¿Se está obteniendo una salida de alrededor de 0.01 V en lugar de 2.5V? Los resultados   parece implicar que el reloj se está desbordando en 255.

En el modo 1, se comporta como un temporizador de 8 bits.

void setup() 
{ 
  DDRB = (1<<PB1); 

  TCCR1A |= (1<<COM1A1) | (1<<WGM11); 
  TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10); 

  ICR1 = 19999; 
  OCR1A = 10000; 
} 

void loop() 
{ 
}

Dado que WGM10 en TCCR1A ya está configurado, la configuración de WGM11, WGM13 y WGM12 seleccionará el modo 15, no el modo 14. El modo 15 es PWM rápido con TOP = OCR1A (no ICR1). Ya que también está utilizando la configuración de salida OC1A para PWM con COM1A1, esto resultará en un OC1A restante alto.

Como ya se mencionó, si desea configurar los temporizadores en el entorno Arduino, debe hacerlo desde cero con = en lugar de | =.

theusch escribió:

  

Y, por lo que sé, se podría ejecutar más después de la instalación ()

Desde main.cpp de Arduino: Código:

#include <Arduino.h> 

int main(void) 
{ 
   init(); 

#if defined(USBCON) 
   USB.attach(); 
#endif 

   setup(); 

   for (;;) { 
      loop(); 
      if (serialEventRun) serialEventRun(); 
   } 

   return 0; 
}

JJ

    
respondido por el user36193
0

Hay un hardware y hay un aspecto del software de esto.

1º - el hardware: Como sabe, el medidor de CC promedia el PWM para indicar un valor entre 0 y 5 V, que se relaciona con su ciclo de trabajo. Donde esto dependerá en gran medida de su carga. p.ej. Sin carga solo se acumulará la carga a 5 V y permanecerá allí. Demasiado y se disipará antes de que pueda medirse. El lugar donde se carga puede estimarse con f = 1 / 2PiRC

Segundo - el software - echa un vistazo a Secretos de Arduino PWM tiene varios ejemplos de varios modos en los que puedes ejercitarte. , en el que deberías obtener los resultados indicados y desde allí puedes ajustarlos a tus necesidades.

En tercer lugar hay calculadoras PWM en línea. calculadora en línea y otro

    
respondido por el mpflaga

Lea otras preguntas en las etiquetas