¿Cómo usar pines IO en el microcontrolador PIC como PWM?

2

Estoy tratando de usar un microcontrolador PIC18F4520 para impulsar 8 servomotores. Para esto necesito 8 señales PWM, pero la unidad PIC solo tiene dos PWM incorporadas. Entonces, decidí usar algunos pines de E / S normales como PWM y busqué cómo hacerlo. Encontré alguna solución basada en hardware como el uso de IC adicionales o una solución basada en software como el uso de PWM basado en interrupciones. Pero, ¿por qué no puedo usar este segmento de código?

while(1)
{
PORTA.RA0=1;
delay_ms(10);
PORTA.RA0=0;
delay_ms(10);
}

El pin es alto durante 10 ms y bajo durante 10 m. Por lo tanto, el período de ciclo es de 20 ms. ¿No debería esto crear una señal de 50Hz con un ciclo de trabajo del 50%? ¿O me estoy perdiendo algo?

    
pregunta Nafis

3 respuestas

11

La función delay() hace que el PIC se repita y evita cualquier otra actividad que no sea la interrupción de las rutinas activadas. En su ejemplo, activará RA0 durante 10 ms, pausará (impidiendo el mantenimiento de cualquier otra salida) y luego desactivará RA0 durante 10 ms con la misma acción de inhibición. La función de pausa () debería estar realmente oculta para los principiantes, ya que fomenta este tipo de mala práctica de programación.

En su lugar, debe ejecutar un temporizador base para sus salidas PWM y hacer algo como este pseudo código.

while(1) {
  timer += 1;                // increment the timer.
  if (timer > tmax) {
    timer = 0;               // reset
  }
  PORTA.RA0 = (timer < t0ontime);  // Output on until ontime exceeded.
  PORTA.RA1 = (timer < t1ontime);
  PORTA.RA2 = (timer < t2ontime);
  PORTA.RA3 = (timer < t3ontime);
  PORTA.RA4 = (timer < t4ontime);
  PORTA.RA5 = (timer < t5ontime);
  PORTA.RA6 = (timer < t6ontime);
  PORTA.RA7 = (timer < t7ontime);
}

Hace muchos años que no uso el compilador PIC, por lo que puede que no funcione como está escrito, pero entiendes la idea. Debería hacer que el cronómetro se incremente en una base de tiempo fija en lugar de en la forma en que lo he mostrado para que no varíe si cambia el chip oscilador, etc.

Otra mejora que podrías hacer en este código es evitar iniciar todos los pulsos al mismo tiempo. Esto suavizaría la demanda de la fuente de alimentación y podría ayudar a reducir un poco el ruido.

    
respondido por el Transistor
8

Tiene problemas más grandes que no hay suficientes salidas de PWM de hardware y su intento de software no funciona. Usted malinterpreta los pulsos que requieren los servomotores hobby para el control.

Estas unidades solo funcionan en la longitud del pulso. Por lo general, el rango de recorrido de 0-100% resulta de 1 a 2 ms de ancho de pulso. Cada pulso le indica al controlador en la unidad donde desea que esté la posición del motor. Este comando de posición generalmente se debe repetir cada 20 ms aproximadamente para que el funcionamiento sea suave si la posición ordenada está cambiando.

Hay varias formas de usar hardware PWM para hacer esto. La primera opción obvia es obtener un PIC con más salidas PWM. Otra es multiplexar la salida de un solo generador PWM. Utilice el módulo CCP en modo de disparo único. Primero, cambie el multiplexor de salida a una unidad de servo particular, genere el pulso para esa unidad, cambie el mutiplexor de salida a la siguiente unidad de servo, etc.

Dado que todo el rango de viaje está codificado en 1 ms de ancho de pulso, esto es realmente algo que quiere que el hardware haga para obtener el resultado sin jitter.

    
respondido por el Olin Lathrop
4
  

¿No debería esto crear una señal de 50Hz con un ciclo de trabajo del 50%? O soy yo   falta algo?

hace (aproximadamente). El problema es que los servos RC requieren un ancho de pulso de 1 a 2 ms, no 10 ms. Las señales que debe generar se ven así: -

Lospulsosdelcanalpuedenemitirseunotrasotro,utilizandounsimpletemporizadorderetardodesoftwaresinonecesitahacernadamásalmismotiempo.Sinembargo,dadoqueeltiempototalparacada"cuadro" puede variar de 8 a 16 ms, dependiendo de los anchos de pulso individuales, necesita alguna forma de llevarlo hasta 20 ms. Una forma es sumar todos los anchos de pulso y restar de 20 ms para obtener el retardo adicional requerido en la brecha.

Otra forma es configurar un temporizador de hardware que se dispara cada 20 ms. También puede tener todo esto en un ISR para que el tiempo de intervalo esté disponible para otro procesamiento de "fondo" que no sea sensible al tiempo.

NOTA: los anchos de pulso del canal deben producirse con precisión con baja fluctuación de fase (< = 2us), pero el tiempo de trama no lo hace. La mayoría de los servos RC están diseñados para manejar cualquier tiempo de cuadro entre 16 ms y 22 ms, y un tiempo aún mayor no se verá afectado (los servos solo se moverán más lentamente).

    
respondido por el Bruce Abbott

Lea otras preguntas en las etiquetas