Me gustaría aumentar la resolución de bits PWM del Arduino Uno. En este momento es de 8 bits, lo que considero demasiado bajo. ¿Es esto posible sin perder la capacidad de interrupciones y retrasos?
Koen
EDITAR Esta configuración ofrece un resultado de 16 bits
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS11); /* prescaler: clock / 8 */
ICR1 = 0xffff; /* TOP counter value (freeing OCR1A*/
}
/* Comments about the setup
Changing ICR1 will effect the amount of bits of resolution.
ICR1 = 0xffff; (65535) 16-bit resolution
ICR1 = 0x7FFF; (32767) 15-bit resolution
ICR1 = 0x3FFF; (16383) 14-bit resolution etc....
Changing the prescaler will effect the frequency of the PWM signal.
Frequency[Hz}=CPU/(ICR1+1) where in this case CPU=16 MHz
16-bit PWM will be>>> (16000000/8)/(65535+1)=30.5175Hz
*/
/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
fuente
ICR1
para0x1fff
, a continuación, su frecuencia será 1953 Hz (F_CPU / (TOP + 1)) con un pre-escalador en 1.ICR1 = 0x03FF
y en 0 veo un pequeño pulso en el visor lo suficiente como para encender el led. ¿Algunas ideas?analogWrite16(pin, val)
da un ciclo de trabajo de (val + 1) / ICR1. Como solución alternativa, Arduino loanalogWrite()
haceif (val == 0) digitalWrite(pin, LOW); else if (val == 255) digitalWrite(pin, HIGH);
. Pero entonces no puede obtener un ciclo de trabajo de 1 / ICR1 ...Con alguna calibración, podría sumar las salidas de dos canales PWM con diferentes resistencias de ponderación. En el extremo, podría usar una salida para proporcionar 8 bits de resolución y escalar la otra a 1/256 del nivel y agregarlos para que el segundo canal cubra un bit de rango y usted (nuevamente nocionalmente) obtenga 16 bits de resolución. Sin un cuidado y ajuste inmenso, todo lo que obtendrías sería un desastre.
Sin embargo, al dividir el segundo canal por 16 o 32, puede agregar varios bits adicionales de resolución PWM. Simplemente agregando 2 canales PWM con salidas analógicas filtradas, agrega un bit adicional (ya que el rango potencial se duplica para mV / bit sin cambios).
Nocionalmente (de nuevo) por cada división adicional entre 2 obtienes un bit adicional de resolución, pero esto solo puede llevarse a cabo para quizás 4 o 5 o 6 bits adicionales, con requisitos de precisión cada vez mayores de resistencias de escala y calibración más difícil y propensión a errores .
Breve ejemplo
Si un PWM se reduce para dar 0 - 255 mV en un paso de 1 mV, entonces sumar dos PWM con igual amplitud daría un rango de 0 - 510 mV en pasos de 1 mV.
Si un PWM se reduce por un factor de 32, en lugar de agregar 255 mV al rango inicial de PWM, agregaría solo 8 mV al extremo superior (0.256.32 = 8 mV, pero la resolución estaría en 0.03125 (1/32) ) mV pasos.
Si bien esto podría lograrse simplemente con la suma de resistencias y el filtrado RC, el uso de un amplificador operacional de verano mejoraría enormemente los resultados.
Además, la ondulación PWM podría filtrarse con un filtro RC simple, pero el uso de un opamp como amortiguador (o incluso un solo transistor como seguidor de emisor) le daría 3 o 5 polos de filtrado de paso bajo y muchas más posibilidades de lograr PWM adicional resolución. No he inspeccionado la "coherencia de fase" de las salidas PWM, pero espero que se muevan en un bloqueo relativo para que no tenga la ventaja de suavizar la adición de dos formas de onda no correlacionadas.
Se pueden hacer más comentarios si es necesario. Pregunte si está interesado.
fuente