Modulación de señal 38 Khz con PIC

#1
hola a todos,

he estado tratando de diseñar una señal de 38khz para PIC16F628A pero he tenido algunas dudas al respecto, agradeceria si alguien puede ayudarme a aclarar mis ideas.

el tema es el siguiente

ya pude hacer la señal de 38khz pero continua como una señal cuadrada y estoy buscando modularla de la siguiente manera




setup_ccp1(ccp_PWM);
setup_timer_2(t2_div_By_1,25,1);
set_pwm1_duty(13);


agradecería si alguien sabe como puedo modularla para poder conectar un ir emisor
 

Adjuntos

#2
Una forma sencilla de hacerlo con lo que tienes es utilizando una compuerta AND (adjunto imagen). Otra forma seria, dependiendo del dato a enviar, activar y desactivar el modulo CCP para interrumpir la señal PWM de 38KHz.
modulador.jpg
 
#3
Una forma sencilla de hacerlo con lo que tienes es utilizando una compuerta AND (adjunto imagen). Otra forma seria, dependiendo del dato a enviar, activar y desactivar el modulo CCP para interrumpir la señal PWM de 38KHz.
Ver el archivo adjunto 165335

gracias por responder juanma2468, no entiendo muy bien la imagen, datos que seria? , solo quiero modular la señal como la imagen para que el ir receptor tsop4038 recoja la señal como se ve en la siguiente imagen:

señal sensor.png
 

Adjuntos

#4
Bien, pues "Datos" seria la señal que dura 600useg. Usando la interrupción por timer, cada 600useg activas/desactivas el modulo CCP y vas a tener la señal de la imagen que pusiste de la derecha.
 
#5
Hola, añadiendo a lo que comenta juanma2468. Para lograr modular la señal, pues la señal "datos" tiene que activar el módulo CCP cuándo valga uno y viceversa.
"Datos" es la señal moduladora de 38kHz.
 
#6
Buenas noches. He estado revisando sus comentarios y he conseguido algo parecido pero a lo que coloco un tiempo de 600 us es como si se saturara el CCP1
No sé si estoy haciéndolo bien, realmente este tema del PWM se me ha complicado siempre.

Este es el código que tengo para prueba:
C:
#include <16f628a.h>

//#device adc=10

#INCLUDE <stdio.h>



#FUSES HS,NOWDT

#use delay(clock=4M)


//#USE standard_IO(B)

//#USE standard_IO(A)


INT i;


void main(){

   output_low(PIN_B3); //CCP1
   setup_ccp1(ccp_PWM);
   setup_timer_2(t2_div_By_1,25,1);

while(true){

  setup_ccp1(ccp_pwm);
  delay_us(600);

   for(i=0;i<19;i++){
   set_pwm1_duty(13);
   delay_us(100);
   }

  setup_ccp1(ccp_off);
  delay_us(600);
}
}
 
Última edición por un moderador:
#8
lo que tenia en mente era que hiciera 19 flancos de bajado y 19 de subida para que completara el el ancho de 38khz!! no se si estoy equivocado la verdad he estado especulando
------- Mensaje actualizado: -------

Gudino Roberto duberlin revise el codigo sin el for y tengo estos resultados, creo que nos estamos acercando a la meta tengo las siguientes dudas:


IMG_2611.JPG

esa caída por que puede pasar?

la idea del proyecto es hacer un sensor de deteccion por proximidad , tengo conectado como receptor un sensor tsop4038 el cual deberia tener esta señal:
IMG_2613.JPG

y cuando detecte el objeto tenga un flanco de bajada!! pero al conectar la señal de 38khz, la señal del receptor es la siguiente:

IMG_2612.JPG

porque sera que pasa esto? agradezco su interés en este tema..
 
Última edición:
#9
Agregale una compuerta NOT smith trigger (CD40106 por ejemplo) y fijate si asi mejora. La caida esa tipo rampa se debe a que hay presentes capacidades parasitas en la salida, proba poniendo una resistencia de carga de 1k a masa a ver si eso hace que mejore.
 
#10
gracias por sus comentarios, tengo una duda al dejar este código dentro del while me pasa que no puedo colocar ningún delay para encender y apagar un led porque se pierde la señal de 38khz no se porque pasa esto.

setup_ccp1(ccp_PWM);
delay_us(600);
set_pwm1_duty(13);
setup_ccp1(ccp_off);
delay_us(600);
 
#11
Pasa que no tenes que usar delays para hacer la modulación, si te fijas en el post #4 te puse que tenias que usar el modulo del timer (por ejemplo el timer0) para que actue por interrupción y asi te desentendes de los delays y podes implementar apagados/encendidos de leds sin que se vea alterada la modulación. Si no sabes como hacer lo del timer, mira en el foro que hay muchos temas sobre esto, sino otra opción son los video tutoriales.
 
#12
juanma2468 gracias por la ayuda, he podido modular la señal con el timer0 y todo anda bien hasta el momento.

Ahora tengo la siguiente duda.

la idea del proyecto es reconocer obstaculos y poner en alto algunos pines del pic mientras el sensor esta detectando y cuando deje de detectar el obstaculo apague los pines.

lo estoy tratando de hacer con una interrupción externa y hasta ahí bien, interrumpe y activa los pines necesarios, el tema es que como la señal que le esta entrando del receptor infrarrojo son varios pulsos bajos, no se como limitar que reconozca un solo pulso y mientras lo este reconociendo mantenga en alto los bits y en bajo cuando ya no detecte nada.

agradezco sus comentarios que han sido de gran ayuda.
 
#13
Si únicamente quieres detectar pulsos negativos, eso es muy sencillo.
De hecho, si la interrupción externa está configurada para actuar por flanco de bajada, únicamente actuará cuando se detecten pulsos negativos.
Así que cuando ocurra la interrupción puedes actuar.
Pero si si se desea actuar ante un ancho de pulso determinado, entonces habrá que medir su periodo.
C:
    if(!flag_pulso)                     // Si se espera el pulso negativo...
    {
        tiempo_pulso = get_timer0();    // Obtener el tiempo del pulso.
        ext_int_edge(0, L_TO_H);        // Cambiar el flanco de interrupción de bajo a alto.
        flag_pulso = 1;                 // Indicar que se procesó el pulso negativo.
    }
    else    // Caso contrario. (Pulso positivo)
    {
        set_timer0(0x00);               // Restablecer el Timer 0.
        ext_int_edge(0, H_TO_L);        // Cambiar el flanco de interrupción de alto a bajo.
        flag_pulso = 0;                 // Restablecer flag_pulso.
    }

    // Comparar si el pulso es válido:
    if(tiempo_pulso > x && tiempo_pulso < x)    // Establecer el margen de actuación.
        output_high(PIN_XX);
    else
       output_low(PIN_XX);
 
#14
gracias por contestar D@rkbytes he estado revisando tu código y no se tengo dudas al respecto no se si estoy haciendo algo mal, ya logro que encienda el led por flanco de bajada, algo que no entiendo es !flag_pulso ya que no se cuando se carga cuando para entrar al if, lo que hice fue ponerlo en 1 cuando entra a la interrupción pero al tener el símbolo ¨!¨ no entra al if y lo otro que quería saber es si ese rango del timer0 es el que yo diseñe a 500us el cual es de 131, pero no tengo claro cual usaría para que apagara el led, estoy un poco confundido.


y otra pregunta que es mas curiosidad, por que al conectar el ir emisor a la señal de 38khz se baja el voltaje casi a 1V, lo que estoy haciendo es colocar el ccp1 para hacer un pwm de 38khz y lo coloco en la base de un transistor para poder sacar mas corriente, el tema es que no se porque se cae tanto el voltaje de 5v a 1v al colocar el ir emisor?
 
Última edición:
#15
gracias por contestar D@rkbytes he estado revisando tu código y no se tengo dudas al respecto no se si estoy haciendo algo mal, ya logro que encienda el led por flanco de bajada, algo que no entiendo es !flag_pulso ya que no se cuando se carga cuando para entrar al if, lo que hice fue ponerlo en 1 cuando entra a la interrupción pero al tener el símbolo ¨!¨ no entra al if y lo otro que quería saber es si ese rango del timer0 es el que yo diseñe a 500us el cual es de 131, pero no tengo claro cual usaría para que apagara el led, estoy un poco confundido.


y otra pregunta que es mas curiosidad, por que al conectar el ir emisor a la señal de 38khz se baja el voltaje casi a 1V, lo que estoy haciendo es colocar el ccp1 para hacer un pwm de 38khz y lo coloco en la base de un transistor para poder sacar mas corriente, el tema es que no se porque se cae tanto el voltaje de 5v a 1v al colocar el ir emisor?
Colocá el esquemático de como lo conectaste así podemos ver donde está el error, supongo que debes haber usado resistencia de base y resistencia en el IR emisor verdad?
 
#16
Colocá el esquemático de como lo conectaste así podemos ver donde está el error, supongo que debes haber usado resistencia de base y resistencia en el IR emisor verdad?
1523490927142.png

Así es como lo tengo conectado, el osciloscopio está a 2 V y en físico prácticamente es la misma señal, cuando desconecto el led aumenta el voltaje.

Este es el código con el que estoy generando la señal:
C:
#int_timer0


void timer0(){

contador++;

contador1++;

if(contador1==500){

setup_ccp1(ccp_pwm);

contador1=0;

}

if(contador==1000){

setup_ccp1(ccp_OFF);

contador=0;

}


}



void main(){


   output_low(PIN_B3); //CCP1

   setup_ccp1(ccp_PWM);

   setup_timer_2(t2_div_By_1,25,1);

   set_pwm1_duty(13);


setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);

SET_TIMER0(131);   // valor es un entero de 8bits

enable_interrupts(INT_TIMER0); // Habilitamos la interrupción que deseamos

enable_interrupts(GLOBAL); //Habilita int. general
 
Última edición por un moderador:
#17
Hola...El led no debe ir en el emisor del transistor si no en el colector.

El por que te lo dejo para que lo investigues tu.

Saludos.

Ric.
------- Mensaje actualizado: -------

 

Adjuntos

Última edición:
#18
Hola a todos. Todavía estoy trabajando en el tema de la señal de 38 khz por pulsos.
Ahora tengo una duda que me gustaría compartir con ustedes.
¿Cómo podría hacer para enviar únicamente una cantidad determinada de pulsos?
Digamos, 10 pulsos. Ya que como lo tengo diseñado, me envía pulsos constantemente.

Esto lo he pensado para hacer un conteo de los pulsos que necesito para activar la salida que estoy buscando switchar!!
No sé de qué otra forma podría hacer un conteo de pulsos si recibo demasiados en corto tiempo.

Este es mi código hasta ahora:
C:
#int_timer0


void timer0(){

   pulso++;

 


   if(RA1==0){

   output_high(pin_a1);

   setup_ccp1(ccp_PWM);

   set_timer0(131);

   }

   else{

   output_low(pin_a1);

   setup_ccp1(ccp_off);

    }

   }




void main(){

         output_low(PIN_B3); //CCP1

         setup_ccp1(ccp_PWM);//activo pwm

         setup_timer_2(t2_div_By_1,25,1);//activar timer 2 para señal de 30khz

         set_pwm1_duty(13);//ciclo de trabajo 50%

    

      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);

      SET_TIMER0(131);   // valor es un entero de 8bits

      enable_interrupts(INT_TIMER0); // Habilitamos la interrupción que deseamos

      enable_interrupts(GLOBAL); //Habilita int. general


while(TRUE){



}



}
 
Última edición por un moderador:

Temas similares

Arriba