En ves de usar una logica de ...
IMP=read_ADC();
PWM=(IMP/8)+20;
set_pwm1_duty(pwm);
En el que el valor del PWM depende exclusivamente del ADC.
Podrias utilizar otra "logica" o forma de pensamiento.
Sabiendo que tenes el centro y tiene un valor, supongamos 0x01FF.
Definis una guarda alrededor de ese punto supongamos +-0x30 en el que no se mueve para nada el valor del PWM. De ahora en adelante voy a suponer que va para un lado nomas el potenciometro para que sea mas simple
Divido el rango de mi potenciometro en varias partes y que van a tener una caracteristica, segun el valor del ADC va a incrementarse una cierta cantidad el duty del PWM ( esto es un solo lado, si es para el otro lado es decrementarse )
0x1FF ---------- 0x22F ------------ 0x2CF ---------- 0x36F ------------- 0x3FF
+0 +1 +2 +3
Entonces uso un timer que por ejemplo cada 250ms actualize el valor del duty del PWM,entonces cada 250ms, se fija que valor tiene el ADC, si por ejemplo esta en 0X2FF, al duty que tengo lo aumento en 2. Siempre limitandolo al maximo ( creo que acepta hasta 1024 el set_pwm_duty() )
Esto daria una sensacion de variacion de velocidad segun vas moviendo el joystick para un lado o para el otro. y cuando lo soltas no se mueve para ningun lado. Por otra parte esa "guarda" te proteje de que si el potenciometro no quedo muy centrado no aumente o decremente.
Como dije usas un timer, asi que esto lo podes hacer de 2 formas:
- Cada seccion incrementa en una cantidad distinta como hice el ejemplo, y se incrementa en un tiempo "fijo" 250ms segun mi ejemplo.
- O podes incrementar siempre 1, pero cada seccion modifica el tiempo de ese incremento (resumiendo le cambias el valor que le cargas al timer), ejemplo:
0x1FF ---------- 0x22F ------------ 0x2CF ---------- 0x36F ------------- 0x3FF
+0 +1 +1 +1
300ms 150ms 100ms
- O pones un tiempo fijo mas chico y contas la cantidad de veces a entrar.. Si esta en la zona de 0x22F a 0x2CF que entre 3 veces , la siguiente 2 y la otra 1 antes de incrementar el duty
Es lo unico que se me ocurre.
Otra cosa aunque todo parezca muy lindo pueden haber problemas.
El principal es que si tu PIC aumenta demasiado rapido el duty y tu servo no puede seguirlo, cuando vuelva a la posicion de 0 el servo va a seguir moviendose, asi que la velocidad con que aumentes el duty tiene que ser tal que tu servo pueda seguirlo.
Seguro que se puede solucionar con mas elementos en el circuito pero eso significa complicarla mucho mas. Y si no queres complicarla mucho podes hacer directamente:
0x1FF ---------- 0x22F ------------ 0x3FF
+0 +1
Y solo tenes una velocidad, la fijas vos cuanto aumenta y listo

Y ahi si podes reemplazar el codigo que puse arriba por un:
int IMP,X;
IMP=128; //Comienza centrado
#define VELOCIDAD 1
while(1)
{
X = read_ADC() //Leo el ADC (8bits)
if(X>140) // Valor Centro(128) + guarda(12), asi para la derecha
{
if( IMP > (255-VELOCIDAD) ) { IMP=255; } // Me asguro que si sumo no supere los limites, sino lo pongo al limite
else { IMP+= VELOCIDAD; }
}
else if ( X<116 ) // Lado izquierdo, Centro - guarda(12)
{
if( IMP < VELOCIDAD ) { IMP=0; } // Cambio la posicion, siempre y cuando pueda ir restando
else { IMP-= VELOCIDAD; }
}
PWM=(IMP/8)+20; // Calculo la posicion en base a IMP que es de 0 a 255 y no incrementando de a 1, es una conversion mas simple ( por la formula podria haber hecho IMP de 0 a 32 )
set_pwm1_duty(pwm); // Seteo duty, si fuera estuvierae en el centro el joystick, el PWM no cambiaria ya que no se modificaria IMP
}
(En ese codigo use un ADC de 8 bits como lo planteaste)
------------------------
Con respecto a la programacion, evita el uso de GOTO, por que es una instruccion en ASM mas que para C, el compilador se maneja de una forma y que me parece que no tenes clara logrando hasta un stack overflow.
Si queres salir de un while() usa break;