Control de velocidad del servomotor con PIC

Estoy controlando un servomotor usando el PIC12F675. El servo gira en direcciones opuestas.

Controlo el servo de la siguiente manera:

if(GPIO & (1<<3))
        {
                GPIO |=(1<<2);
            __delay_ms(1);
            GPIO &=~(1<<2);

            }
            else
        {
                GPIO |=(1<<2);
            __delay_ms(2);
            GPIO &=~(1<<2);


            }

            __delay_ms(18); 

Me gustaría controlar la velocidad a la que el servo llega a los extremos opuestos. Traté de buscar artículos relacionados con el control de velocidad, me pareció demasiado complicado controlar la velocidad de barrido. Estoy buscando sugerencias para el mismo

... y ¿qué son los bits GPIO 1 y 2?
@Jason, lo siento. GPIO 2 es la salida en la que se opera el servo. GPIO 3 tiene un interruptor de palanca. Estoy planeando usar un potenciómetro para controlar la velocidad.
(correcto, quise decir 2 y 3) -- Todavía no tenemos idea de lo que se supone que debe hacer GPIO2. Estás creando un pulso... ¿qué hace eso?
@JasonS Creo que se supone que GPIO2 simula una señal PWM para controlar el servo
@JasonS Sí, estoy creando un software PWM para el servomotor
¿Qué le hace qué al servomotor? Pulsos PWM = ??? ¿Velocidad? ¿Esfuerzo de torsión? ¿Actual? ¿Voltaje? ¿Posición?
Los pulsos @JasonS PWM son una señal para el servo. El servo se alimenta externamente.
De nuevo: ¿Cómo controla el servo el pulso PWM?
@JasonS Según tengo entendido, el tiempo de ENCENDIDO en el servo determina el ángulo al que debe girar el servo. El ciclo de tiempo total es de aproximadamente 20 ms y configurar el servo en 0,9 ms lo gira hacia un extremo, 1,5 ms de tiempo ON lo gira hacia el centro y 2,1 ms hacia el extremo opuesto
@JasonS Lo que Sai está tratando de hacer es: cada vez que el pin de entrada GPIO3 (¿botón?) Sube, el pin de salida GPIO2 sube durante 1 ms, posicionando el servo a -90 grados; por el contrario, cuando el pin de entrada pasa a nivel bajo (¿se suelta el botón?), el pin de salida GPIO2 pasa a nivel alto durante 2 ms, posicionando el servo a +90 grados. Luego espera otros 18 ms, porque un servo necesita actualizar su posición cada 20 ms
Aquí se utiliza una terminología muy confusa. ¿Es este (1) un "servomotor" o "servomotor" que es un motor giratorio de alto rendimiento con retroalimentación de velocidad O (2) un tipo de control de radio "servo" que es un motorreductor que está diseñado para proporcionar control de posición en un rango de 90 a 180 grados. || Por lo dicho entiendo que es lo segundo

Respuestas (2)

Los servos funcionan escuchando durante 20 ms y luego ajustando la posición en función de la duración del pulso alto.

El pulso alto ( Xabajo) puede tener una duración de entre 1 ms y 2 ms, con 1,5 ms como posición neutral o central.

|------------20ms-----------|
 |-X-|                
  ___ ___
_| |_______________________| |___ ...

Dependiendo de su servo, -90° (a la izquierda del centro) suele ser ~1ms, 90° (a la derecha del centro) es ~2ms.

Si está a 0° y le envías una señal de 1 ms, intentará girar a su posición de -90° lo más rápido que pueda. La velocidad máxima varía de servo a servo (las hojas de datos suelen especificar un tiempo de 0-60°), y también depende del voltaje que le des (Hitec HS-422 a 4,8 V tarda 0,21 segundos, a 6 V tarda 0,16 segundos).

Si desea variar la velocidad (no tan rápido como sea posible), debe indicarle que cambie su posición gradualmente.

Puede hacer esto enviando una serie de señales de posición (cada una de 20 ms de duración con un Xpulso alto de ms).

Si enviamos 50 pulsos, lentamente de 1.5ms a 1ms bajando 0.01ms cada vez, X será igual a:

1.50ms, 1.49ms, 1.48ms, ... , 1.02ms, 1.01ms, 1.00ms

luego, suponiendo que pueda girar tan rápido como queramos, tardará 50 (number of 20ms signals) x 20 ms (length of pulse) = 1sen pasar de 0° a -90°.


Envía un pulso de 20 ms con x ms alto: (psudocódigo)

function send_signal (x):
    set output high
    wait x ms
    set output low
    wait (20 - x) ms

Haz que un servo gire lentamente de izquierda (-90°) a derecha (90°)

Psudocódigo:

loop x from 1 to 2, step 0.01
    send_signal(x)

O si lo prefieres, en Do (99):

for (float x = 1; x <= 2; x += 0.01) {
    send_signal(x);
}
Muy buena respuesta!
¡Gracias! Pensé que podría ser útil cubrir los conceptos básicos ya que la respuesta de Jason fue bastante técnica.

Le sugiero que generalice su sistema a algo como lo siguiente:

int T = 200   // 200*100usec = 20msec period
while(1)
{
   u = compute_next_duty_cycle()
   servo_output_on();
   __delay_100us(u)       
   servo_output_off();
   __delay_100us(T-u)
}

donde servo_output_xxxx()enciende y apaga el GPIO. Es casi seguro que tendrá que mejorar la granularidad de sus retrasos, si elige usar un software PWM; Los pasos de retraso de 1 ms solo le brindan incrementos del 5% en el ciclo de trabajo PWM para un ciclo de 20 ms.

Tendrás que usubir y bajar rampas; una velocidad de giro fija debería ser suficiente (un control de trayectoria más complicado también limitaría la aceleración):

 pseudocode for ramping u given a position goal ufinal and max slewrate v:

 delta = ufinal - u;
 delta = min(v, max(-v, delta));   // limit delta to +/- v
 u += delta

Si necesita una rampa muy lenta, tendrá que usar internamente un estado de alta resolución para u y luego dividir/cambiar para obtener su comando de salida:

 delta = ufinal - u;
 delta = min(v, max(-v, delta));   // limit delta to +/- v
 u += delta
 uout = u >> 8;  // or >> 16 or whatever
 servo_output_on();
 __delay_100us(uout)       
 servo_output_off();
 __delay_100us(T-uout)