Reemplace el bucle con los temporizadores en este código de ATtiny

1

¿Cómo puedo reescribir lo siguiente para usar los temporizadores? Tenga en cuenta que esta es una ATtiny que solo tiene Timer0 y Timer1

Esencialmente estoy tratando de software PWM en muchos pines de salida, más que los pines PWM incorporados. El código a continuación está ligeramente simplificado, pero el código real utiliza la manipulación directa del puerto y no hace casi nada más, por lo que el resultado debería ser casi tan bueno como el PWM incorporado.

La aplicación prevista está diseñada para funcionar con una batería pequeña, por lo que el ahorro de energía es un objetivo de diseño importante. También dado que esto es ATtiny, todos los bytes del espacio del programa son importantes.

O, convénceme que no vale la pena intentar usar temporizadores en este caso.

void loop() {
  static int8_t procession = 0;
  static uint32_t lastTime = millis();
  static int8_t pos = 0;

  if (lastTime > millis() + 200) {
    lastTime = millis();
    if (++procession == 9) {
      procession = 0;
    }
  }

  const uint32_t ON_CYCLE = 5;
  const uint32_t OFF_CYCLE = 5;

  digitalWrite(procession, HIGH);

  delayMicroseconds(ON_CYCLE);

  if (OFF_CYCLE > 0) {
    digitalWrite(procession, LOW);
    delayMicroseconds(OFF_CYCLE);
  }
}
    
pregunta J Halcres

2 respuestas

1

Por supuesto, puede reemplazar cualquier tipo de bucle y demoras con los temporizadores de hardware. Esto casi siempre resultará en una operación más eficiente y predecible. No ha especificado el número de canales PWM que desea utilizar, ni los ciclos de frecuencia / servicio que desea para ninguno de ellos. Para PWM de "bit banging", está limitado al número de líneas de E / S disponibles (aunque, siempre puede agregar registros de desplazamiento externos para aumentar considerablemente este límite).

También está limitado en la frecuencia de CPU en uso. Cuanto más rápido está el reloj, más cosas puede hacer en la misma cantidad de tiempo. Esto será más importante a medida que agregue canales PWM. La velocidad de reloj AVR predeterminada es 8MHz, reducida a 1MHz internamente. Arduino utiliza típicamente un cristal externo de 16MHz. ¡Este detalle es importante!

Cada temporizador tendrá varios registros de "comparación de coincidencia" para su uso en las solicitudes de servicio de interrupción generadas. Básicamente, el temporizador contará hasta que alcance el valor en un registro de comparación de coincidencias, luego podría desencadenar un ISR, restablecer el conteo, etc. Desde la parte superior de mi cabeza, hay muchas formas de crear múltiples PWM usando un solo temporizador:

PWM múltiples de la misma frecuencia y ciclo de trabajo

Este caso es bastante trivial, pero con un solo temporizador, puede establecer cualquier número de pines de salida en "Comparar partido A" (que también restablece el conteo), y borrar estos pines en "Comparar partido B". El valor para "B" sería algo desde 1 hasta el valor de "A", dependiendo del ciclo de trabajo deseado.

PWM múltiples de la misma frecuencia con diferentes ciclos de trabajo

Esto es un poco más complicado, pero definitivamente es factible. Al igual que en el primer caso, usaremos "A" para configurar todos los pines de PWM y restablecer el conteo. El ISR "B" es un poco más complejo, pero aquí está lo esencial:

  1. cree una matriz global de valores de tiempo, que representa el "tiempo de inactividad" de cada pin PWM.
  2. Establezca el registro de comparación de coincidencia B en el más pequeño de estos "tiempos de inactividad"
  3. En el ISR "B", verifique si el valor del registro es igual al "tiempo de apagado" de cada línea PWM en la matriz de tiempo (siempre debería ser igual a uno de ellos cuando active el ISR) y luego apagar ese pin (s).
  4. Recorra la matriz de tiempo para el siguiente tiempo de apagado, y configure el registro "B" en ese valor, que se utilizará para activar el próximo ISR.

Este proceso le dará la cantidad de pines PWM que desee con diferentes ciclos de trabajo (variables) (veces) pero todos deben tener la misma frecuencia.

PWM múltiples con diferentes frecuencias y diferentes ciclos de trabajo

Este último caso que presentaré se basa en las ideas de los anteriores, pero agregará una variable de conteo que se incrementa cuando se dispara el temporizador ISR. Cada vez que este ISR se activa, ha transcurrido una cantidad exacta y conocida de tiempo, por lo que es libre de usar variables de contador para decidir cuándo ocurre un evento. Por ejemplo, podría usar una variable para contar hasta 100 antes de establecer un pin, luego contar hasta 100 antes de borrarlo, mientras que otra variable cuenta hasta 200 para hacer las mismas cosas. Eso es 2 variables para 2 canales PWM independientes.

Por supuesto, este método es el más desordenado en términos de código, pero debería parecer familiar: es esencialmente lo que estaba haciendo su código en el bucle del programa principal, simplemente ha trasladado esta funcionalidad a los temporizadores de hardware y ha generado ISR sin el duros retrasos, liberando su bucle principal y CPU para hacer cosas más importantes que mirar a los "NOP" de ASM durante miles de ciclos de reloj.

Notas adicionales

No he usado ningún código aquí, pero puedo agregar algunos si eres más específico con tus requisitos, o dar una pista sobre lo que ya sabes cómo hacer.

También, asumo que estás usando un AVR de 8 bits aquí. Si es así, le recomiendo que preste atención a los tipos de variables requeridos. Usar un número entero de 32 bits para un valor constante de 5 es tonto ... use uint8_t para cualquier cosa menos de 256.

Si está realmente preocupado por el poder y el tamaño del código, elimine las cosas de Arduino y las capas innecesarias de abstracción.

    
respondido por el Kurt E. Clothier
0
  

¿Cómo puedo reescribir lo siguiente para usar los temporizadores?

Escribí esto hace un tiempo para conducir los servos, pero el concepto básico es el mismo: producir ciclos de trabajo independientemente variables en cualquier número de pines.

enlace

tiene enlaces a otros enfoques que utilizan diferentes periféricos en PIC y AVR, pero el concepto básico es el mismo.

puede modificar los parámetros para que se ajusten a sus necesidades.

el código se ejecuta en su totalidad en el isr para que su bucle principal pueda hacer lo que sea necesario, como alterar los ciclos de trabajo ...

    
respondido por el dannyf

Lea otras preguntas en las etiquetas