Autor Tema: Generando N pulsos Quadrature con dirección  (Leído 6932 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Generando N pulsos Quadrature con dirección
« en: 02 de Octubre de 2008, 02:35:34 »
Aprovechando el éxito que obtuve al preguntar Algoritmo para cargar un registro en serie "por la izquierda", hoy os planteo la optimización de otro algoritmo.
En esta ocasión se trata de una función que se alimenta de dos variables para generar pulsos Quadrature como estos:


Las variables son:
  • PulsosEncoder, número de pulsos a generar
  • Sentido, 0 hacia un lado, 1 hacia el otro

Aquí una propuesta de algoritmo, que ya funciona, y con el que soy capaz de generar una señal de 42,8KHz trabajando a 12MIPS. Estoy seguro que podemos acelerarla un huevo, a ver qué decis.

Código: Javascript
  1. void EnviaPulsosQuadrature() {
  2.    while (PulsosEncoder--) {
  3.    
  4.       switch (IndQuad%4) {                
  5.          case 0b00:                      
  6.             output_low (PIN_B6);
  7.             output_low (PIN_B5);
  8.             break;
  9.          case 0b01:
  10.             output_high (PIN_B6);
  11.             output_low (PIN_B5);
  12.             break;
  13.          case 0b10:
  14.             output_high (PIN_B6);
  15.             output_high (PIN_B5);
  16.             break;  
  17.          case 0b11:
  18.             output_low (PIN_B6);
  19.             output_high (PIN_B5);
  20.             break;
  21.       }
  22.       if (Sentido)              
  23.         IndQuad++;
  24.       else
  25.         IndQuad--;
  26.    }
  27. }

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5538
    • Picmania by Redraven
Re: Generando N pulsos Quadrature con dirección
« Respuesta #1 en: 02 de Octubre de 2008, 16:33:59 »
Prueba con esto con tu nuevo osciloscopio (pronunciado con retintín) y dime algo, payo.  :mrgreen:

Código: C#
  1. #bit ENCODER_A = 0xF81.6 // PIN_B6 si es un 18F4550
  2. #bit ENCODER_B = 0xF81.5 // PIN_B5 si es un 18F4550
  3.  
  4. void EnviaPulsosQuadrature(int16 PulsosEncoder, int1 Sentido){
  5.  
  6.    int8 IndQuad=0;
  7.  
  8.    while (PulsosEncoder--) {
  9.       ENCODER_A=(bit_test(IndQuad,1)+Sentido);
  10.       ENCODER_B=(bit_test(IndQuad,1)+bit_test(IndQuad+1,0));
  11.       IndQuad++;
  12.    }
  13. }
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #2 en: 03 de Octubre de 2008, 01:30:48 »
Tal y como está funciona a 66KHz  :-/ pero no cambia de sentido.
Voy revisando

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #3 en: 03 de Octubre de 2008, 02:37:33 »
Ná, olvídalo, que funcionó bien a la primera. Es que estoy acarajotao.





Muchas gracias, Don Diego.

P.D.: en la esquina superior derecha está la frecuencia



Desconectado Kid_Bengala

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 490
Re: Generando N pulsos Quadrature con dirección
« Respuesta #4 en: 03 de Octubre de 2008, 07:22:14 »
Todo ello hecho con tu NUEVO OSCILOSCOPIOOOO  :mrgreen:

saludos de antonio

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Generando N pulsos Quadrature con dirección
« Respuesta #5 en: 03 de Octubre de 2008, 10:39:49 »
Oye Nocturno ..... no me digas que el calibrador Bernier Digital que tienes lo usas para .... medir el ancho de los pulsos  :D :D :D

Muy buena compra ... felicitaciones

saludos
El papel lo aguanta todo

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Generando N pulsos Quadrature con dirección
« Respuesta #6 en: 03 de Octubre de 2008, 15:58:47 »
Bueno Manolo, estuve meditandoló...

Como yo soy un freaky y vos lo que buscás es velocidad, automáticamente lo razoné en assembler. Lo posteo y después lo intento pasar a C, pasa que hay que ir mirando el codigo assembler que genera. Si no me equivoco, esta rutina debería ser unas cuantas veces mas rapida que las anteriores...

Eso sí. Me tomé el lujo de agregar una variable auxiliar de 8 bits llamada "sequence", y hay que inicializarla al inicio del programa:


Código: ASM
  1. #DEFINE X       PORTB,6
  2. #DEFINE Y       PORTB,5
  3.  
  4.  
  5.         movlw   0xCC
  6.         movwf   sequence
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13. Girar   movf    PulsosEncoder,f
  14.         btfsc   STATUS,Z
  15.         return
  16.  
  17.         btfss   Sentido,0               //0=Izq,1=Der
  18.         goto    Der
  19.                
  20. Izq     rlf     sequence,w
  21.         rlf     sequence,f
  22.  
  23.         btfss   sequence,1
  24.         bcf     X
  25.         btfsc   sequence,1
  26.         bsf     X
  27.  
  28.         btfss   sequence,0
  29.         bcf     Y
  30.         btfsc   sequence,0
  31.         bsf     Y
  32.  
  33.         decfsz  PulsosEncoder,f
  34.         goto    Izq
  35.         return
  36.  
  37. Der     rrf     sequence,w
  38.         rrf     sequence,f
  39.  
  40.         btfss   sequence,1
  41.         bcf     X
  42.         btfsc   sequence,1
  43.         bsf     X
  44.  
  45.         btfss   sequence,0
  46.         bcf     Y
  47.         btfsc   sequence,0
  48.         bsf     Y
  49.  
  50.         decfsz  PulsosEncoder,f
  51.         goto    Der
  52.         return
« Última modificación: 03 de Octubre de 2008, 16:40:33 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Generando N pulsos Quadrature con dirección
« Respuesta #7 en: 03 de Octubre de 2008, 16:30:57 »
Inicializo sequence a 0xCC, o sea, en binario: 11001100. Si ahora lo ubico de manera circular:


                                         0     0
                                      1           1
                                      1           1
                                         0     0

Y ahora digo que X= PORTB.6 e Y= PROTB.5, entonces:

                                         X     Y
                                         0     0
                                      1           1
                                      1           1
                                         0     0

y asigno a X e Y el valor que figura inmediatamente debajo de ellos(en la figura anterior, X=0 e Y=0).

Ahora con las rotaciones hago girar la ruedita esta...(vamos en sentido antihorario)

(1era rotacion)

                                         X     Y
                                         0     1
                                      0           1
                                      1           0
                                         1     0

(2da rotacion)

                                         X     Y
                                         1     1
                                      0           0
                                      0           0
                                         1     1

(3era rotacion)

                                         X     Y
                                         1     0
                                      1           0
                                      0           1
                                         0     1


(4ta rotacion)

                                         X     Y
                                         0     0
                                      1           1
                                      1           1
                                         0     0


y en sentido horario sería similar...

Bueno, a la noche veo si lo programo para C(siempre y cuando interese)...

Saludos.
« Última modificación: 03 de Octubre de 2008, 16:38:53 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #8 en: 03 de Octubre de 2008, 17:24:48 »
Vamos, vamos, que va a salir algo bonito. Me ha encantado lo del circulito.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Generando N pulsos Quadrature con dirección
« Respuesta #9 en: 03 de Octubre de 2008, 22:23:48 »
Bueno, encontré otras opciones(usando un goto) que va más rápido y demás cosillas...pero ya se torna un poco pseudoassembler asi que para mantenerlo sencillo y bueno...a ver a cuánto furula(y si es que furula :))

Sequence es un int8 que debe ser inicializado con el valor 0xCC(o el que corresponda a la 1era posicion del cuadrante)
Como sé que sos de usar variables globales, PulsosEnconder y Sentido son globales aquí.

Código: C#
  1. void EnviaPulsosQuadrature3(){
  2.    while(PulsosEncoder--){
  3.       if(Sentido) rotate_right(&Sequence,1); else rotate_left(&Sequence,1);
  4.       ENCODER_A = bit_test(Sequence,1);
  5.       ENCODER_B = bit_test(Sequence,0);      
  6.    }
  7. }

Saludos
« Última modificación: 03 de Octubre de 2008, 22:27:37 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #10 en: 04 de Octubre de 2008, 01:06:32 »
¡Espectacular, Don Bruno!
¡Hemos subido a 91KHz!, más del doble de cuando empezamos.

¿Quién da más?

P.D.: soy partidario de variables globales porque el código sale más pequeño y se ejecuta más rápido, aunque sé que no es lo más apropiado dentro de una etiqueta de programación correcta.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Generando N pulsos Quadrature con dirección
« Respuesta #11 en: 04 de Octubre de 2008, 21:53:09 »
Uff Manolo!
Va a estar difícil superar eso.
La puedo acelerar un poco, pero queda un poco menos elegante...
A ver si las armo...

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #12 en: 05 de Octubre de 2008, 01:47:44 »
Hay una forma de acelerarlo aún más, que me obligaría a cambiar el esquema del circuito, pero lo mismo me animo: si pongo las salidas en un puerto que no esté utilizando, con rotar el puerto tengo suficiente, no será necesario luego asignar ningún valor a los pines de salida.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Generando N pulsos Quadrature con dirección
« Respuesta #13 en: 05 de Octubre de 2008, 07:33:45 »
Es una idea muy buena! No pense que podías modificarlo hasta ese punto...

El algoritmo que publiqué antes tiene 13 instrucciones asm que son las que generan las ondas. Esta que posteo ahora tiene 11(y podrían ser 10, pero no logro que el CCS utilice la instrucción decfsz para agilizar el decremento de PulsosEncoder) siempre y cuando a PulsosEnconder la declares como un int8.
Destaco que este algoritmo solo funciona para los pines RB5 y RB6.

Código: C#
  1. void EnviaPulsosQuadrature(){
  2.    if(Sentido){
  3.       Otra_Der:
  4.       rotate_right(&Sequence,1);
  5.       PORTB= (Sequence & 0b01100000) | (PORTB & 0b10011111);
  6.       if(--PulsosEncoder!=0) goto Otra_Der;
  7.    }else{
  8.       Otra_Izq:
  9.       rotate_left(&Sequence,1);
  10.       PORTB= (Sequence & 0b01100000) | (PORTB & 0b10011111);
  11.       if(--PulsosEncoder!=0) goto Otra_Izq;
  12.    }
  13. }

Y debo admitir, que fuera de la posibilidad que mencionaste, no exíste(por lo que estudié) manera de bajar el algoritmo de 10 instrucciones en assembler.

Adjunto el código assembler que genera de salida..(CCS Versión 4.058)

Código: ASM
  1. .................... void EnviaPulsosQuadrature(){
  2. ....................    if(Sentido){
  3. 0004:  BTFSS  06.0
  4. 0006:  BRA    0022
  5. ....................       Otra_Der:
  6. ....................       rotate_right(&Sequence,1);
  7. 0008:  RRNCF  07,F
  8. ....................       Aux= PORTB;
  9. 000A:  MOVFF  F81,08
  10. ....................       Aux&=0b10011111;
  11. 000E:  MOVLW  9F
  12. 0010:  ANDWF  08,F
  13. ....................       PORTB= (Sequence & 0b01100000) | Aux;
  14. 0012:  MOVF   07,W
  15. 0014:  ANDLW  60
  16. 0016:  IORWF  08,W
  17. 0018:  MOVWF  F81
  18. ....................       if(--PulsosEncoder!=0) goto Otra_Der;
  19. 001A:  DECF   05,F
  20. 001C:  BZ    0020
  21. 001E:  BRA    0008
  22. ....................    }else{
  23. 0020:  BRA    003A
  24. ....................       Otra_Izq:
  25. ....................       rotate_right(&Sequence,1);
  26. 0022:  RRNCF  07,F
  27. ....................       Aux= PORTB;
  28. 0024:  MOVFF  F81,08
  29. ....................       Aux&=0b10011111;
  30. 0028:  MOVLW  9F
  31. 002A:  ANDWF  08,F
  32. ....................       PORTB= (Sequence & 0b01100000) | Aux;
  33. 002C:  MOVF   07,W
  34. 002E:  ANDLW  60
  35. 0030:  IORWF  08,W
  36. 0032:  MOVWF  F81
  37. ....................       if(--PulsosEncoder!=0) goto Otra_Izq;
  38. 0034:  DECF   05,F
  39. 0036:  BZ    003A
  40. 0038:  BRA    0022
  41. ....................    }
  42. .................... }
  43. 003A:  GOTO   011E (RETURN)

P.D: O acaso estas usando C18?  :?

Saludos.
« Última modificación: 05 de Octubre de 2008, 07:44:56 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re: Generando N pulsos Quadrature con dirección
« Respuesta #14 en: 06 de Octubre de 2008, 02:44:32 »
¡Bravo, Bruno, has vuelto a conseguirlo!

Ahora volamos a 187,5KHz



He probado a rotar directamente sobre el puerto B pero no he conseguido que funcione. De todas formas, ya me doy por satisfecho y no seguiré intentándolo. Gracias a todos los que me habéis ayudado.



 

anything