Autor Tema: mi servo no se queda quieto (NUEVO RETO)  (Leído 34458 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #45 en: 22 de Junio de 2007, 20:22:14 »
Seguro que serviran Giovanny, en el hilo quedan para todo aquel que esta interesado y para los que vendran despues.
Te lo puedo asegurar por propia experiencia.... que ya son unos añitos... :mrgreen:
Saludos desde Granada, España.

Desconectado softjad

  • PIC10
  • *
  • Mensajes: 41
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #46 en: 16 de Julio de 2007, 12:47:18 »
y una solucion como la que nos ofrece redpic en sus ejemplitos?
es decir, el timer a 20ms, y en el bucle principal miras en que posicion se encuentra el timer. cuando le corresponda a cada servo se baja el pulso.
vamos, es el primer codigo con el que probe... y vibraba, pero supongo que era por las conversiones adc...
pero si las conversiones adc las hiciera SOLO una vez que el pulso haya bajado tendria como minimo 17.5ms para esta tarea, con lo que EN PRINCIPIO no deberia hacer vibrar al servo ya que el pulso se esta bajando correctamente cada vez.
nocturno, voy a probar de esta manera primero que asi tengo que hacer menos modificaciones al codigo, y si no da resultado mirare como tu dices.
y sino siempre podemos subir la velocidad del micro  :mrgreen:
salu2


Como lo puedo adaptar para 2 servos?

salu2

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #47 en: 16 de Julio de 2007, 13:45:20 »
Como lo puedo adaptar para 2 servos?

salu2

eso es lo que estamos queriendo saber...
ahora estoy terminando otro proyecto, y cuando tenga tiempo libre me pondre a hacer pruebas para ver como conseguirlo con 2 servos...
mientras tanto puedes adelantar algo de trabajo tu  :wink:
tienes la base de como hacerlo con un servo... y tambien las ideas que se comentan en este hilo
salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #48 en: 18 de Julio de 2007, 14:50:42 »
bueno, ya me he puesto nuevamente a molestar con los servos  :-/
primero hice pruebas con el codigo de redpic (el PWM se realiza desde un bucle en el main) pero leyendo el adc una vez que el pulso este bajo, para que no interfiera con el tiempo de la señal, pero no funciona... vibra...
asi que empece a hacer pruebas con la idea de manolo, poniendo el timer para que se desborde cada 100uS y mirando en cada interrupcion si hay que bajar o no el pulso de alguno de los servos...
las pruebas las empece directamente a 8mhz, ya que para esto seguramente iba a necesitar algo mas de velocidad de proceso.
las pruebas fueron genial! logre controlar 2 servos independientemente con su respectivo POT....
lo malo: al desbordarse el timer cada 100uS solo tenia 20 posiciones para el servo (2.5mS - 0.5mS = 2mS / 100uS = 20 Posiciones)
asi que baje el tiempo de desborde a 50uS. el codigo siguio funcionando correctamente, los servos se posicionaban correctamente y no vibraban, pero el POT se notaba un poco capado al tacto, ya que seguia teniendo solo 40 posiciones para el servo (2.5mS - 0.5mS = 2mS / 50uS = 40 Posiciones)
volvi a bajar el tiempo de desborde del timer, a 10uS.... la cosa fue FATAL!
los servos ya ni siquiera respondian al POT... con lo cual fui corriendo a CETRONIC (mi tienda amiga de electronica en coruña  :mrgreen: ) y compre un cristal de 20mhz...
asi que ahora me pondre a hacer las pruebas a altas velocidades  :-)
supongo que la cosa ira mejor... ya os contare
os dejo el codigo para dos servos funcionando perfectamente (con 40 posiciones), con un 12f683 a 8mhz
salu2

--- Edito ---
Al parecer el directorio para subir archivos esta lleno.... asi que no podre dejar el codigo colgado
lo pongo en un post....
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #49 en: 18 de Julio de 2007, 14:55:15 »
Código: C
  1. #include <12F683.h>
  2. #device adc=8
  3.  
  4. #FUSES NOWDT,NOMCLR,PUT,INTRC_IO
  5. #use delay(clock=8000000)
  6.  
  7. #include <math.h>
  8.  
  9. #define ADC1   0
  10. #define ADC2   3
  11. #define SERVO1 PIN_A1
  12. #define SERVO2 PIN_A5
  13.  
  14. int1 flagLeerADC = FALSE;     //flag para que sepa cuando leer el adc
  15. int16 PosicionServo1 = 15;    //posicion del servo1
  16. int16 PosicionServo2 = 15;    //posicion del servo1
  17. int16 ContInt = 0;            //Contador de interrupciones
  18.  
  19. void rLeerADC(void);
  20.  
  21. #int_TIMER0
  22. TIMER0_isr() {
  23. //Timer 8 bits -> 255 = Desborde
  24. //Prescaler de 1:2
  25. //1 Tick cada 1uS
  26. //1 desbordamiento cada 50uS (255 - 205 ticks)
  27.  
  28.    set_timer0(205);
  29.    
  30.    ContInt = ContInt + 1;
  31.    
  32.    if(ContInt < 51){
  33.       if(ContInt > PosicionServo1){
  34.          output_low(SERVO1);
  35.       }
  36.      
  37.       if(ContInt > PosicionServo2){
  38.          output_low(SERVO2);
  39.       }
  40.    }
  41.    
  42.    if(ContInt == 51){
  43.       flagLeerADC = TRUE;
  44.    }
  45.    
  46.    if(ContInt == 400){
  47.       ContInt = 0;
  48.       output_high(SERVO1);
  49.       output_high(SERVO2);
  50.    }
  51. }
  52.  
  53. void main() {
  54.  
  55.    setup_adc_ports(sAN0|sAN3|VSS_VDD);
  56.    setup_adc(ADC_CLOCK_INTERNAL);
  57.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
  58.    setup_timer_1(T1_DISABLED);
  59.    setup_timer_2(T2_DISABLED,0,1);
  60.    setup_comparator(NC_NC);
  61.    setup_vref(FALSE);
  62.    enable_interrupts(INT_TIMER0);
  63.    enable_interrupts(GLOBAL);
  64.    setup_oscillator(OSC_8MHZ);
  65.    set_adc_channel(ADC1);
  66.    
  67.    set_timer0(205);
  68.    
  69.    do{
  70.       if(flagLeerADC = TRUE)
  71.          rLeerADC();
  72.    }while(TRUE);
  73.    
  74. }
  75.  
  76.  
  77. void rLeerADC(void){
  78.    int16 ValorADC;
  79.    
  80.    ValorADC = read_adc();
  81.    PosicionServo1 = 10 + floor(ValorADC * 0.15686);
  82.    
  83.    set_adc_channel(ADC2);
  84.    delay_us(5);
  85.    
  86.    ValorADC = read_adc();
  87.    PosicionServo2 = 10 + floor(ValorADC * 0.15686);
  88.    
  89.    set_adc_channel(ADC1);
  90.    flagLeerADC = FALSE;
  91. }
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #50 en: 18 de Julio de 2007, 16:50:40 »
Creo que esa rutina de interrupción podría reducirse, ganando en velocidad de proceso y, por tanto, pudiendo meter más pasos de potenciómetro.
A ver si tengo un ratito y le echo un vistazo.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #51 en: 18 de Julio de 2007, 17:04:01 »
gracias nocturno!
yo ahora estoy con las pruebas a 20mhz...
cuentame cuando se te ocurra algo
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #52 en: 19 de Julio de 2007, 00:38:16 »
No es mucho, pero algún avance he conseguido.
En primer lugar y por si no lo sabías, te diré que para saber cuánto ocupa una función tenemos una opción en el menú que nos vendrá bastante bien. Se trata de la opción View->Statistics.
Al probarla con tu programa vemos lo siguiente:
Código: [Seleccionar]
Page ROM  %  RAM  Functions:
---- --- --- ---  ----------
0     63   4  10  @FLT
0     32   2   4  @SFTOI
0     30   2   2  @ITOF
0    203  13  14  @DIVFF
0    319  21  16  @ADDFF
0    118   8  13  @MULFF
0    408  26   4  floor
0     68   4   0  TIMER0_isr
0     86   6   0  main
0    172  11   6  rLeerADC
Observa que la interrupción del timer consume 68 instrucciones.

He hecho un par de cambios en la rutina de interrupción dejándola como sigue:
Código: C
  1. #int_TIMER0
  2. TIMER0_isr() {
  3.  
  4.    set_timer0(205);
  5.    
  6.    ContInt++;
  7.    
  8.    if(PuedenBajar){
  9.       if(ContInt == PosicionServo1){
  10.          output_low(SERVO1);
  11.       }
  12.  
  13.       if(ContInt == PosicionServo2){
  14.          output_low(SERVO2);
  15.       }
  16.    }      
  17.  
  18.    if(ContInt == 51){
  19.       flagLeerADC = TRUE;
  20.       PuedenBajar=FALSE;
  21.    }
  22.  
  23.  
  24.    if(ContInt == 400){
  25.       ContInt = 0;
  26.       PuedenBajar=TRUE;
  27.       output_high(SERVO1);
  28.       output_high(SERVO2);
  29.    }
  30. }

Los cambios son principalmente dos:
- los if con condición ">" los he sustituido por "==". El micro tarda menos en comprobar esta condición y para el funcionamiento de tu programa es lo mismo.
- he añadido un flag (PuedenBajar) para sustituir la condición if (ContInt<51)

Ahora al compilar aparece lo siguiente:
Código: [Seleccionar]
Page ROM  %  RAM  Functions:
---- --- --- ---  ----------
0     63   4  10  @FLT
0     32   2   4  @SFTOI
0     30   2   2  @ITOF
0    203  13  14  @DIVFF
0    319  21  16  @ADDFF
0    118   8  13  @MULFF
0    408  26   4  floor
0     60   4   0  TIMER0_isr
0     86   6   0  main
0    172  11   6  rLeerADC

Como ves, hemos ahorrado 8 instrucciones, o lo que es igual, un 12% de tamaño que probablemente puedas incrementar en frecuencia de proceso.
Ni que decir tiene que si hicieras esta interrupción en assembler conseguirías reducirla bastante más, aunque en ese tema yo no puedo ayudarte.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #53 en: 19 de Julio de 2007, 02:49:26 »
Master por mas que miro veo las dos tablas iguales....  :shock:
donde esta la diferencia?...
Manolo al final que compilador usas?... con que entorno de trabajo?...
Saludos desde Granada, España.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #54 en: 19 de Julio de 2007, 10:43:19 »
dogflu, yo tambien estuve mirando un buen rato las tablas, y ahora me doy cuenta! en donde dice timer0_isr, la primera tabla dice que son 68 instrucciones, y en la segunda son 60
lo de ver las estadisticas lo acabo de probar (en PICC) y esta interesante! sobre todo para saber cuanto tarda el programa en cada cosa.
probare a ver si asi va mejor el tema.... pero aun asi no creo que la solucion este por este lado... si que es un paso importante para reducir el codigo, pero al hablar de 80 pasos al menos del POT creo que habra que buscar soluciones mas drasticas, tanto puede ser lo de incluir algo de ASM (que nunca es tarde para aprender  :mrgreen: ) o ir a mas Mhz.
yo ya habia adaptado el codigo a 20mhz y empece a hacer las pruebas... y no comprendia porque la cosa no funcionaba... hasta que me di cuenta que el micro se me queda pequeño... ya que el pin A3 es solo entrada (no analogica)... y como estoy usando 2 pines para el xtal me quede sin pines, ya que necesito dos salidas para el pwm y dos entradas analogicas para los pot.... asi que ahora me pongo a modificar el codigo para ver que tal va con un 16f88
salu2 y gracias manolo por aportarnos sabiduria! cada vez que dices algo yo aprendo una cosa nueva  :-)
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #55 en: 19 de Julio de 2007, 13:37:58 »
Ahora si lo vi...  :z)

Yo tengo un codigo para controlar un servo. Este codigo no usa contadores
para controlarlo, lo que hago es cargar directamente el registro del timer
con el valor... es una primera aproximacion... lo que ocurre es que no esta
en C.

PD. por el momento puedes asociar una entrada analogica a varios servos y
de esta manera aprovechas el hard operativo que tengas por el momento.
Saludos desde Granada, España.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #56 en: 19 de Julio de 2007, 14:12:24 »
Manolo al final que compilador usas?... con que entorno de trabajo?...
Utilizo un vetusto pero fiable CCS 3.242

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #57 en: 20 de Julio de 2007, 22:33:47 »
manolo, desde que dijiste lo de "statics" no dejo de mirar como optimizar el codigo!
es curioso, pero "a=a+1" ocupa las mismas instrucciones que "a += 1", pero ambas una instruccion mas que "++a" / "a++"... aunque en principio creo que tendrian el mismo efecto, no? (hablando del lenguaje C, claro)
esto lo quiero usar para incrementar el contador de interrupciones del timer
salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #58 en: 21 de Julio de 2007, 02:08:29 »
Efectivamente a=a+1 es igual a a += 1 y necesita tres posiciones de memoria, dos para los operandos (la variable "a" y "1") mas una posición para la operación con los operandos (+). Sin embargo ++a y a++ solo utilizan dos posiciones, una para la variable y otra para la operación (el 1 es implicito, mientras con la otra instrucción puedes incrementar lo que quieras, con esta solo puedes incrementar la unidad).

Un saludo.
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: mi servo no se queda quieto (NUEVO RETO)
« Respuesta #59 en: 21 de Julio de 2007, 03:06:56 »
Qué curioso, juraría que el compilador detectaba el a=a+1 y lo compilaba como a++

Si no es así, ya tienes otro ciclo que ahorrar ;-)