Autor Tema: como duplico un tren de pulsos de 30 milisegundos?  (Leído 1083 veces)

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

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
como duplico un tren de pulsos de 30 milisegundos?
« en: 14 de Abril de 2021, 11:51:58 »
Cordial saludo, tan amables...requiero una idea para implementar lo siguiente..
tengo un tren de 50 pulsos a 30 milisegundos, requiero coger esos 50 pulsos y sacarlos por 2 salidas, los mismos 50 pulsos pero uno a 21 mili-segundos y otro a 19 milisegundos (simultaneaos).
si la entada fuera menor le colocaría retardos para obtener las salidas pero como es mayor lo veo mas difícil.
(en algún momento lo único que puede cambiar es el numero de pulsos, lo demás se mantiene.)
Pensaba en tomar los pulsos por el "tocki y guardarlos en una variable o tal vez por interrupción ensaye con un for para las temporizaciones pero al sumar las interrupciones se corre la frecuencia.
que me recomiendan por favor para empezar a implementar, gracias de antemano.
« Última modificación: 14 de Abril de 2021, 12:22:45 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 950
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #1 en: 14 de Abril de 2021, 12:22:52 »
¿Pero cómo son esos pulsos?
Si son 50 todos iguales basta con leer la aparición del primero para largar los otros, sin necesidad de andar contando.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #2 en: 14 de Abril de 2021, 12:34:46 »
Citar
Eduardo2 ¿Pero cómo son esos pulsos?
Si son 50 todos iguales basta con leer la aparición del primero para largar los otros, sin necesidad de andar contando.
,
cordial saludo, gracias por tu respuesta, si todos los pulsos son iguales.
lo que se evalúan son unos sensores en unas puertas, entonces  si una puerta abierta envía 30 pulsos en 30 milisegundos, si hay 2 puertas abiertas envía 100 pulsos en los mismos 30 milisegundos.
Si algo parece complicado... es por que esta mal explicado.

Desconectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 950
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #3 en: 14 de Abril de 2021, 12:59:49 »
La verdad no entiendo, tu 1er mensaje es confuso.   ¿Podés dibujar un timing?

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #4 en: 14 de Abril de 2021, 14:47:50 »
Código: [Seleccionar]
[b]Eduardo2[/b]La verdad no entiendo, tu 1er mensaje es confuso.   ¿Podés dibujar un timing?,
claro que si, espero se entienda..
estoy tratando pero no me deja,,

https://drive.google.com/file/d/1oRdhxdRZru26yu0FLnEizz37qkiwvXD8/view?usp=sharing
« Última modificación: 16 de Abril de 2021, 09:42:03 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #5 en: 14 de Abril de 2021, 16:06:59 »
no me fue posible subir la imagen directamente.
« Última modificación: 16 de Abril de 2021, 09:43:59 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 950
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #6 en: 14 de Abril de 2021, 16:32:40 »
Ok, eso es lo mismo que tu 1er mensaje y nada que ver con el 2do,  donde los pulsos podían ser 30 (o 100) en 30ms,  no espaciados 30ms.

Citar
entonces  si una puerta abierta envía 30 pulsos en 30 milisegundos, si hay 2 puertas abiertas envía 100 pulsos en los mismos 30 milisegundos.


Imaginemos que es un número de pulsos  variable espaciados cada 30ms y querés  dos trenes espaciados 21 y 19ms  -->  No se puede adivinar cuantos pulsos van a llegar, vas a tener que primero contarlos (que llevaría 3s si son 100)  y después largar las salidas.
Como mucho, conociendo el máximo número de pulsos, largarlas un intervalo antes del tiempo máximo.


Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #7 en: 14 de Abril de 2021, 16:40:18 »
graciasEduardo2...
tengo claro guardar los pulsos  pero como los transmito? ahí tengo la duda si por tmr0 hago un conteo ademas, los pulsos de 19ms terminaran primero que los de 21ms.
Si algo parece complicado... es por que esta mal explicado.

Desconectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 950
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #8 en: 15 de Abril de 2021, 00:36:54 »
Hay muchas maneras, dependerá de los timers libres, la frecuencia y los gustos personales.

Te pongo un ejemplo para 4 trenes de pulsos, es mas corto escribirlo que explicarlo (y que se entienda ;) )

Cuando pulsás el boton de PIN_B7  te saca 4 trenes de pulsos cuadrados por PIN_B0..3
El argumento de secuencia() es la cantidad de pulsos a sacar y los W1...4  el intervalo entre pulsos.


Código: [Seleccionar]
#include<16F877A.h>

#use delay(crystal=4MHz)
#use fast_io(all)

#BIT Out1  = getenv("SFR:PORTB").0 ;
#BIT Out2  = getenv("SFR:PORTB").1 ;
#BIT Out3  = getenv("SFR:PORTB").2 ;
#BIT Out4  = getenv("SFR:PORTB").3 ;
#BIT boton = getenv("SFR:PORTB").7 ;

/* Ancho en ms de cada tren de pulsos */
#define W1  21
#define W2  19
#define W3  30
#define W4  55

/* Variables de estado de los contadores  */
int8 npuls1 = 0 ,
     npuls2 = 0 ,
     npuls3 = 0 ,
     npuls4 = 0 ;

int8 n1 = W1 ,
     n2 = W2 ,
     n3 = W3 ,
     n4 = W4 ;

/* Macro contador */
#define T_OUT(x)                                  \
    if(npuls##x !=0)                              \
        if(--n##x ==0){                           \
            n##x = W##x ;                         \
            if(Out##x ==1)           Out##x = 0 ; \
            else if(--npuls##x !=0)  Out##x = 1 ; \
        }

#INT_TIMER2
void  TIMER2_isr(void) {

    T_OUT(1)
    T_OUT(2)
    T_OUT(3)
    T_OUT(4)
}

/* Inicialización de lso trenes de pulsos */
void secuencia(int8 n){

    npuls1 = npuls2 = npuls3 = npuls4 = n ;
    Out1 = Out2 = Out3 = Out4 = 1 ;
}

void main(void) {

    output_b(0) ;
    set_tris_b(0x80) ;
    port_b_pullups(0xFF);

    setup_timer_2(T2_DIV_BY_4,125,1);  //.5ms overflow, .5ms interrupt

    enable_interrupts(INT_TIMER2);
    enable_interrupts(GLOBAL)    ;

    while(true){
        if(!boton){
            secuencia(100) ;   // Inicia la secuencia de pulsos
            while(!boton) ;
        }
    }
}

 

* Test877.jpg
(75.94 kB, 825x587 - visto 174 veces)

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #9 en: 15 de Abril de 2021, 03:55:19 »
Citar
Eduardo2 ¿Pero cómo son esos pulsos?
Si son 50 todos iguales basta con leer la aparición del primero para largar los otros, sin necesidad de andar contando.
,
cordial saludo, gracias por tu respuesta, si todos los pulsos son iguales.
lo que se evalúan son unos sensores en unas puertas, entonces  si una puerta abierta envía 30 pulsos en 30 milisegundos, si hay 2 puertas abiertas envía 100 pulsos en los mismos 30 milisegundos.

  Usa un timer , y una interrupción por cambio de estado y mide el periodo. 

  30 pulsos en 30 ms significa 1 pulso en 1 ms.
 100 pulsos en 30 ms significa 1 pulso en 300 uS.

  Una vez determinado el periodo de un solo pulso ya sabes cómo están las puertas y puedes decidir que hacer.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #10 en: 15 de Abril de 2021, 21:33:40 »
Citar
Eduardo2
Hay muchas maneras, dependerá de los timers libres, la frecuencia y los gustos personales.

Te pongo un ejemplo para 4 trenes de pulsos, es mas corto escribirlo que explicarlo (y que se entienda ;) )

Cuando pulsás el boton de PIN_B7  te saca 4 trenes de pulsos cuadrados por PIN_B0..3
El argumento de secuencia() es la cantidad de pulsos a sacar y los W1...4  el intervalo entre pulsos.
Gracias por tu respuesta, pues la verdad es que el código que me compartes es muy avanzado para mi y de hecho me has puesto a estudiar (lo cual me agrada) nunca he trabajado con macros ni con los registros"getenv("SFR:PORTB"" directamente, me estoy documentando para entender tu código y adaptarlo a mi proyecto. mi idea no es copiar y pegar sino aprender de ustedes así que si estas de acuerdo voy a ir segmentando tu código y agregarle los comentarios para saber si voy bien.
Citar
remi04
Usa un timer , y una interrupción por cambio de estado y mide el periodo.

  30 pulsos en 30 ms significa 1 pulso en 1 ms.
 100 pulsos en 30 ms significa 1 pulso en 300 uS.

  Una vez determinado el periodo de un solo pulso ya sabes cómo están las puertas y puedes decidir que hacer.
gracias, así sera tan pronto tenga el anterior codigo corriendo.
saludos.
« Última modificación: 16 de Abril de 2021, 00:27:56 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #11 en: 15 de Abril de 2021, 23:40:12 »
creo que seria así,
Código: ASM
  1. #BIT Out1  = getenv("SFR:PORTB").0 ;
  2. #BIT Out2  = getenv("SFR:PORTB").1 ;
  3. #BIT Out3  = getenv("SFR:PORTB").2 ;     //hace referencia a la posición de cada bit del puerto B en la memoria, ( tengo dudas del punto y coma (;))
  4. #BIT Out4  = getenv("SFR:PORTB").3 ;
  5. #BIT boton = getenv("SFR:PORTB").7 ;
Código: ASM
  1. /* Inicialización de lso trenes de pulsos */
  2. void secuencia(int8 n){                            //n toma el valor de 100
  3.  
  4. npuls1 = npuls2 = npuls3 = npuls4 = n ;  // las cuatro toman el valor de n
  5. Out1 = Out2 = Out3 = Out4 = 1 ;           // las 4 toman el valor de 1
  6. }


Código: ASM
  1. if(npuls##x !=0)      //no logro encontar info especifica del uso de ## dentro de las macros.

esto es lo que pude averiguar pero no lo comprendo.
Citar
Un solo '#' creará una cadena a partir del argumento dado, independientemente de lo que contenga ese argumento, mientras que el doble '##' creará un nuevo token al concatenar los argumentos.



« Última modificación: 16 de Abril de 2021, 00:25:40 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 252
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #12 en: 16 de Abril de 2021, 01:30:30 »
creo que le voy viendo el sentido,,
Código: QBasic/QuickBASIC
  1. #include<16F877A.h>
  2.  
  3. #use delay(crystal=4MHz)
  4. #use fast_io(all)
  5.  
  6. #BIT Out1  = getenv("SFR:PORTB").0 ;
  7. #BIT Out2  = getenv("SFR:PORTB").1 ;
  8. #BIT Out3  = getenv("SFR:PORTB").2 ;
  9. #BIT Out4  = getenv("SFR:PORTB").3 ;
  10. #BIT boton = getenv("SFR:PORTB").7 ;
  11.  
  12. /* Ancho en ms de cada tren de pulsos */
  13. #define W1  21
  14. #define W2  19
  15. #define W3  30
  16. #define W4  55
  17.  
  18. /* Variables de estado de los contadores  */
  19. int8 npuls1 = 0 ,
  20.      npuls2 = 0 ,
  21.      npuls3 = 0 ,
  22.      npuls4 = 0 ;
  23.  
  24. int8 n1 = W1 ,
  25.      n2 = W2 ,
  26.      n3 = W3 ,
  27.      n4 = W4 ;
  28.  
  29. /* Macro contador */
  30. #define T_OUT(x)                                  \       // 1,2,3 o 4
  31.     IF(npuls##x !=0)                              \        // si npuls,1 es diferente a 0 (esto en la primera pasada) ## une las 2 variables,,creo
  32.         IF(--n##x ==0){                           \       // aquí si me perdí :( ?
  33.             n##x = W##x ;                         \
  34.             IF(OUT##x ==1)           OUT##x = 0 ; \
  35.             ELSE IF(--npuls##x !=0)  OUT##x = 1 ; \
  36.         }
  37.  
  38. #INT_TIMER2
  39. void  TIMER2_isr(void) {
  40.  
  41.     T_OUT(1)  // cuando llega la primera interrupcion el  uno (1 carga T_OUT(x) , la x ya valdría 1 hasta que nueva interrupción y  ya seria 2
  42.     T_OUT(2)
  43.     T_OUT(3)
  44.     T_OUT(4)
  45. }
  46.  
  47. /* Inicialización de lso trenes de pulsos */
  48. void secuencia(int8 n){
  49.  
  50.     npuls1 = npuls2 = npuls3 = npuls4 = n ; // las 4 valen 100
  51.     Out1 = Out2 = Out3 = Out4 = 1 ;           // las 4 valen 1
  52. }
  53.  
  54. void main(void) {
  55.  
  56.     output_b(0) ;
  57.     set_tris_b(0x80) ;
  58.     port_b_pullups(0xFF);
  59.  
  60.     setup_timer_2(T2_DIV_BY_4,125,1);  //.5ms overflow, .5ms interrupt
  61.  
  62.     enable_interrupts(INT_TIMER2);
  63.     enable_interrupts(GLOBAL)    ;
  64.  
  65.     WHILE(true){
  66.         IF(!boton){
  67.             secuencia(100) ;   // Inicia la secuencia de pulsos   // se carga n con este 100
  68.             WHILE(!boton) ;
  69.         }
  70.     }
  71. }
« Última modificación: 16 de Abril de 2021, 01:32:31 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 950
Re:como duplico un tren de pulsos de 30 milisegundos?
« Respuesta #13 en: 16 de Abril de 2021, 10:44:28 »
Lo estás descifrando bien :)

GETENV  te devuelve valores asociados al entorno, como la version del compilador, pero la mayoria referidos al micro usado.

getenv("SFR:PORTB")  devuelve la dirección del PORTB, escribir:
#BIT Out1  = getenv("SFR:PORTB").0 ;   es lo mismo que #BIT Out1  = 0x6.0 ;
La utilidad es que si cambiás de micro te puede cambiar la dirección del puerto, de esta manera te olvidás donde está.

El macro T_OUT(1)  expandido resulta:      (le agregué comentarios, no forman parte de la expansión)
Código: [Seleccionar]
/* Expansion de T_OUT(1)*/
    if(npuls1 !=0)                    //  npuls1 es el número de pulsos pendientes de enviar.                 
        if(--n1 ==0){                 // Cuando n1 llegue a 0 hay que cambiar de estado la salida           
            n1 = W1     ;             // recarga n1                       
            if(Out1==1)            Out1 = 0 ;
            else if(--npuls1 !=0)  Out1 = 1 ;   //  Si Out1 estaba en 0 entonces toca mandar el siguiente, salvo que haya sido el úlltimo.
                                                // Esto ya no vuelve a arrancar hasta que se asigne a npuls1 un valor mayor que 0. De eso se encarga secuencia()
        }

El  n##x  significa que a la 'n' le agregas el argumento 'x' .   Si x es 1  te forma 'n1'
De esa manera genero en la expansion los nombres de las variables 'n1', 'n2', 'n3','n4' ,Out1,Out2...  etc.

Se puede usar mas de un argumento, por ejemplo hacer:
Código: [Seleccionar]
#define T_OUT(x,w)                                \
    static int8 n##x = w ;                        \
    if(npuls##x !=0)                              \
        if(--n##x ==0){                           \
            n##x = w    ;                         \
            if(Out##x ==1)           Out##x = 0 ; \
            else if(--npuls##x !=0)  Out##x = 1 ; \
        }

Entonces invoco el macro con el número del contador y el ancho del pulso.

    T_OUT(1,19)  se expande en:
Código: [Seleccionar]
   
    static int8 n1 = 19 ;         
    if(npuls1!=0)                     
        if(--n1==0){                         
            n1 = 19     ;             
            if(Out1==1)           Out1 = 0 ;     
            else if(--npuls1!=0)  Out1 = 1 ;
        }


Los parámetros y el estado de los contadores podrían estar dentro de una array y no andar repitiendo el código.  La elección dependerá de la memoria de programa y RAM disponible y el tiempo admisible dentro de la interrupción.