Autor Tema: Conversión digital analoga [SOLUCIONADO]  (Leído 9811 veces)

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

Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Conversión digital analoga [SOLUCIONADO]
« en: 30 de Marzo de 2018, 22:22:28 »
Buenas a todos,

Acudo al foro con el fin de que me asesoren un poco con respecto al tema conversión digital análoga.
Sucede que la primer parte del código es realizar operaciones con dos entradas análogas variables, implementando interrupciones para un tiempo de muestreo de 10ms.

Pero la siguiente parte del código consiste en realizar la conversión digital (que es el resultado de la operación), a una salida análoga para apreciarla en el osciloscopio. Me dijeron que se podía con el módulo CCP del PIC, pero no sé como implementar este para realizar dicha conversión,

De antemano agradezco cualquier tipo de sugerencia, crítica o colaboración que puedan brindarme  :)

Gracias, aquí el codigo:

Código: C
  1. #include <16f877a.h>
  2. #device adc=10
  3. #fuses hs,nowdt,noprotect,noput
  4. #use delay (clock=4M)
  5. #int_timer1
  6.  
  7. void timer_1()
  8. {
  9.    set_timer1(64911);
  10. }
  11.  
  12. void main ()
  13. {
  14.  
  15.    setup_timer_1(t1_internal|t1_div_by_8);
  16.    set_timer1(64911);
  17.    enable_interrupts(int_timer1);
  18.    enable_interrupts(global);
  19.    int16 q;
  20.    int16 j;
  21.    float m;
  22.    float k=0.5;
  23.    setup_adc_ports(an0_an1_an3);
  24.    setup_adc(adc_clock_internal);
  25.  
  26.    while(true)
  27.    {
  28.      
  29.       set_adc_channel(0);
  30.       delay_us(20);
  31.       q=read_adc();
  32.       set_adc_channel(1);
  33.       delay_us(20);
  34.       j=read_adc();
  35.       if(input(pin_B0)==0)
  36.       {
  37.       m=(k*j*q);    
  38.       }
  39.       if(input(pin_B0)==1)
  40.       {        
  41.       m=(k*j)+q;
  42.       }
  43.      
  44.    }
  45. }
« Última modificación: 15 de Abril de 2018, 11:39:08 por weland98 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversión digital analoga
« Respuesta #1 en: 30 de Marzo de 2018, 22:32:12 »
Usas el CCP como PWM, y a la salida del PWM una resistencia + un capacitor, para "filtrarlo y asi obtener la componente de DC.

Lo que haces es variar el Duty de tu PWM y asi obtener una tension distinta del otro lado:



No va a ser tan recta la salida asi como la imagen, va a tener subidas y bajadas la tension debido a la carga cuando esta en alto y la descarga cuando esta en bajo. Pero al menos vas a tener una salida analogica (conversion Dig-Ana - DAC -) facilmente realizable.

El 100% de duty lo vas a definir vos, tal ves pases por una formula que te transforme el resultado de tus ADCs a tu duty.
« Última modificación: 30 de Marzo de 2018, 22:34:51 por KILLERJC »

Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Re:Conversión digital analoga
« Respuesta #2 en: 31 de Marzo de 2018, 01:19:38 »
Ok, leí un poco más y con tu ayuda llegue a este codigo:

Código: C
  1. #include <16f877a.h>
  2. #device adc=10
  3. #fuses hs,nowdt,noprotect,noput
  4. #use delay (clock=4M)
  5. #include <math.h>
  6. #int_timer1
  7.  
  8. void timer_1()
  9. {
  10.    set_timer1(64911);
  11. }
  12.  
  13. void main ()
  14. {
  15.    set_tris_c(0b000);
  16.    setup_timer_1(t1_internal|t1_div_by_8);
  17.    set_timer1(64911);
  18.    setup_ccp1(ccp_pwm);
  19.    enable_interrupts(int_timer1);
  20.    enable_interrupts(global);
  21.    int16 q;
  22.    int16 j;
  23.    int16 m;
  24.    float k=0.5;
  25.    setup_adc_ports(an0_an1_an3);
  26.    setup_adc(adc_clock_internal);
  27.  
  28.    while(true)
  29.    {
  30.      
  31.      
  32.       set_adc_channel(0);
  33.       delay_us(20);
  34.       q=read_adc();
  35.       set_adc_channel(1);
  36.       delay_us(20);
  37.       j=read_adc();
  38.       if(input(pin_B0)==0)
  39.       {
  40.       m=(k*j*q);    
  41.       set_pwm1_duty(m);
  42.       }
  43.       if(input(pin_B0)==1)
  44.       {        
  45.       m=(k*j)+q;
  46.       set_pwm1_duty(m);
  47.       }
  48.    }
  49. }

Pero cuando lo simulo en Proteus, no me genera siquiera el ciclo "negativo" que debería tener pues de la señal analoga

Esta es la simulacion, agradezco hacerme caer en cuenta de algo que esté obviando, gracias...




También coloco un generador de onda como entrada analoga porque ese fue un requerimiento del taller

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversión digital analoga
« Respuesta #3 en: 31 de Marzo de 2018, 08:34:29 »
Citar
Pero cuando lo simulo en Proteus, no me genera siquiera el ciclo "negativo" que debería tener pues de la señal analoga

El PIC se encuentra alimentado desde 2 pines GND y VCC, ( 0 a 5V/3v3) entonces no podes tener valores negativos, su salida va a ir desde 0V a 5V. Cualquier DAC en un micro te va a dar el mismo resultado, y lo que vos pedis es una señal alterna.

Si descompones esa señal de PWM en ondas senoidales, te vas a encontrar que tiene una componente de DC + varios senos armonicos de la frecuencia que le diste. Una forma de bloquear el DC, es tener un capacitor en serie.
Inverti los lugares de R3 y C1 (R3 hacela un poco mas grande, 1K por ejemplo) y observa la salida.


Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Re:Conversión digital analoga
« Respuesta #4 en: 31 de Marzo de 2018, 11:11:57 »
Hola gracias por responder,

Invertí los componentes como me dijiste



Creo que es algo un poco mejor, pero esos picos cómo los podría arreglar?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversión digital analoga
« Respuesta #5 en: 31 de Marzo de 2018, 13:30:37 »
¿Que queres alimentar para que sea tan perfecto y encima como un PWM?
Primero pedis un conversor DAC y luego me decis que lo que buscas es obtener una señal de alterna

Antes de continuar dando posibles soluciones, explicate bien que es lo que queres hacer. Y que pensas alimentar con eso.

Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Re:Conversión digital analoga
« Respuesta #6 en: 31 de Marzo de 2018, 23:58:08 »
No no, borra lo que te dije del voltaje negativo, lo que quiero básicamente es que me salga una señal seno escalonada, sin embargo me están saliendo unos picos muy grandes, por eso te pregunto cómo podría corregir los picos que ves en la señal...

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:Conversión digital analoga
« Respuesta #7 en: 01 de Abril de 2018, 01:10:50 »
No no, borra lo que te dije del voltaje negativo, lo que quiero básicamente es que me salga una señal seno escalonada, sin embargo me están saliendo unos picos muy grandes, por eso te pregunto cómo podría corregir los picos que ves en la señal...

Lo más parecido a eso que podés conseguir mediante la salida PWM filtrada es un seno de frecuencia mucho mas baja, donde vas cambiando el duty cycle acorde a la amplitud correspondiente

Para lo que supongo tenías en mente, con el 16F877 tenés que usar un DAC externo (o si son pocos bits de resolución una red R2R) e ir largando los valores del seno de una tabla.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversión digital analoga
« Respuesta #8 en: 01 de Abril de 2018, 11:22:50 »
Ahi te dio las 3 opciones Eduardo.

- Usar el PWM con una tabla de seno, calcular la resistencia+capacitor para la frecuecnia que estes usando. El escalon va a ser feo, pero podes llegar a hacer una senoide.
- Usar un R2R si es que no necesitas tantos escalones. Los escalones van a estar bien definidos.
- Usar un DAC externo, te comunicas por SPI/I2C y el envias los valores que queres.

Otra opcion
- Comprar un PIC con DAC

Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Re:Conversión digital analoga
« Respuesta #9 en: 01 de Abril de 2018, 11:58:15 »
Tengo una duda respecto a la opción del pwm. Lo que pasa es que lo que me piden es que el periodo de muestreo sea de 10ms, eso lo garantizo con las interrupciones del timer 1. Lo que no estoy seguro es para cuadrar la frecuencia del pwm es si setear otro timer para dejar esta frecuencia distinta? Y si el filtro lo calculo para esa frecuencia del pwm, o para la frecuencia del generador de onda?

Gracias a todos por su ayuda.

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:Conversión digital analoga
« Respuesta #10 en: 01 de Abril de 2018, 15:48:47 »
Tengo una duda respecto a la opción del pwm. Lo que pasa es que lo que me piden es que el periodo de muestreo sea de 10ms, eso lo garantizo con las interrupciones del timer 1. Lo que no estoy seguro es para cuadrar la frecuencia del pwm es si setear otro timer para dejar esta frecuencia distinta? Y si el filtro lo calculo para esa frecuencia del pwm, o para la frecuencia del generador de onda?
...

La frecuencia del PWM debe ser la mas alta posible (otro timer).

Pero tené en cuenta que un filtro no hace magia con un solo período PWM, para suavizar decentemente una señal de ese tipo se necesitan MUCHOS períodos (20 o mas).
Eso obliga a que para "ver escalones"  deba elegir la frecuencia mas alta para el oscilador del PWM y una resolución tal que el período resulte unos 2kHz.

Además, la señal PWM es p*ta de filtrar ==> mejor usar un filtro de 2do orden, por ejemplo, con dos RC en cascada (R=3k3 , C=330n , para períodos de 500ms)

Desconectado weland98

  • PIC10
  • *
  • Mensajes: 16
Re:Conversión digital analoga
« Respuesta #11 en: 04 de Abril de 2018, 13:03:20 »
Hola buenas ya pude filtrarla un poco mejor para una frecuencia de PWM de 8kHz.
Pero ahora lo que me piden es utilizar la función seno, solo que en ecuaciones en diferencia. ¿ alguna idea de como pueda plasmar una ecuación en diferencia en lenguaje C?

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:Conversión digital analoga
« Respuesta #12 en: 05 de Abril de 2018, 00:59:30 »
Hola buenas ya pude filtrarla un poco mejor para una frecuencia de PWM de 8kHz.
Pero ahora lo que me piden es utilizar la función seno, solo que en ecuaciones en diferencia. ¿ alguna idea de como pueda plasmar una ecuación en diferencia en lenguaje C?

Al profesor le decís que buscaste en una tabla la transformada Z del seno (o coseno) y armaste la antitransformada por recurrencia.
Aunque si el párrafo anterior te suena a chino, decí que la encontraste en Internet.

La recurrencia para un seno es   Xn = k*Xn-1 - Xn-2   ,  n > 1

Siendo 
     k = 2*cos(ang)        ,  ang : El ángulo que avanza en cada paso.
     X0 = 0
     X1 = A*seno(ang)   ,  A : Amplitud. 



Ojo con las relaciones recursivas. 
- Si trabajás con punto flotante no hay problemas salvo claro , la velocidad.
- Pero cuando la velocidad importa hay que trabajar en enteros.  En ese caso hay que ser cuidadoso porque los truncamientos y la manera en que se hacen las operaciones pueden hacer desastres después de muchas iteraciones. 
Los "desastres" pueden ser  senos que se extinguen , que crecen y crecen (termina con overflows) , de amplitud variable , con un error en frecuencia o  uno poco de cada cosa.


Saludos.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conversión digital analoga
« Respuesta #13 en: 05 de Abril de 2018, 08:05:03 »
No entiendo/encuentro como llegaste a esa formula. Puedo pensar en matematica discreta pero sigo sin ver el aproximado de la misma. Y sino podrías dar un ejemplo de como serian las primeras 4 resultados de esa ecuación?, Segun mi entendimiento seria:

Xn = k*Xn-1 - Xn-2

n = 0
Xn = k*0 - 0
n = 1
Xn = 2*cos(ang)*A*sen(ang)  - 0
n = 2
Xn = ¿?¿??¿ - 2*cos(ang)*A*sen(ang)

Si me decís que tengo que variar el angulo de coseno y seno, significa que necesito implementar 2 tablas, una de seno y otra de coseno! para obtener el seno ¿?¿?. Si no varia el angulo, y elijo un angulo igual a 0 para simplificar, el resultado es siempre 0. Porque k es 0.


En todos lados veo que usan series de taylor, o se puede usar los polinomios de Chebyshev, pero la anti trasformada como la planteas no la vi nunca.

Por mi:
Si quiere un calculo con una ecuación en diferencia, que cargue una tabla con la diferencia entre un punto y otro, y no el valor total. Algo simple y sigue siendo una ecuación en diferencia, el concepto esta, es culpa de el docente por no ser especifico.
Y por supuesto, la suma de todos los valores que cargues en la tabla te debe dar 0 si o si. Y nunca sobrepasar los limites 0 y el limite superior que elijas ( ejemplo 4095 )
« Última modificación: 05 de Abril de 2018, 11:29:39 por KILLERJC »

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:Conversión digital analoga
« Respuesta #14 en: 05 de Abril de 2018, 13:13:17 »
No entiendo/encuentro como llegaste a esa formula.

Aprovecho que las antitransformadas Z  salen con relaciones de recurrencia. 
Conociendo la transformada del seno , la recurrencia queda:
Xn - 2*cos(a)*Xn-1 + Xn-2 = sin(a)*En-1
Usando de la excitación un impulso, simplificando y ordenando llegás a la expresión que puse.


Citar
Puedo pensar en matematica discreta pero sigo sin ver el aproximado de la misma. Y sino podrías dar un ejemplo de como serian las primeras 4 resultados de esa ecuación?, Segun mi entendimiento seria:

Xn = k*Xn-1 - Xn-2

n = 0
Xn = k*0 - 0
n = 1
Xn = 2*cos(ang)*A*sen(ang)  - 0
n = 2
Xn = ¿?¿??¿ - 2*cos(ang)*A*sen(ang)

Si me decís que tengo que variar el angulo de coseno y seno, significa que necesito implementar 2 tablas, una de seno y otra de coseno! para obtener el seno ¿?¿?

O sigue entrando un A*sen(ang) ?

No, como k es una constante se evalúa al inicio de acuerdo al ángulo de avance deseado.
Lo mismo con X1 = A*sen(ang) ,  es un valor inicial.

Un ejemplo en C  (para PC)  largando una lista de valores puede ser:

Código: [Seleccionar]
#include <stdio.h>
#include <math.h>

void main(void){

// Declaracion de variables

    int n ;
    double k , ang , A  ;
    double xn1 , xn ;

// Inicializacion

    ang = 4*M_PI/180  ; // Angulo de avance de 4°
    A   = 1000        ; // Amplitud  1000
    k   = 2*cos(ang)  ;
   
    xn1 = 0 ; xn  = A*sin(ang) ;     // Valores iniciales

// Salida de 200 valores , para no hacer
// un bucle infinito

    printf("%.3lf\n%.3lf\n",xn1,xn); // Muestro los dos
                                     // primeros
    for(n=2;n<200;n++){
        xn = -xn1 + k*(xn1=xn)  ;  // Esto es la única operación que se repite
        printf("%.3lf\n",xn)    ;
    }
}


Yo soy un amante de C porque los operadores permite bonitas fórmulas compactas (aunque díficil de interpretar)  :)

Por ejemplo, si a la recursión anterior la trabajamos un poco algebraicamente llegamos a la siguiente: 
   dn = dn-1 - k*xn
   xn = xn-1 + dn

Esas dos líneas , en C  equivalen a:     xn += dn -= k*xn ;

Este ejemplo genera exactamente la misma secuencia que el anterior (ojo que la definicion de k es diferente)

Código: [Seleccionar]
#include <stdio.h>
#include <math.h>

void main(void){

// Declaracion de variables

    int n ;
    double k , ang , A  ;
    double xn , dn ;

// Inicializacion

    ang = 4*M_PI/180  ; // Angulo de avance de 4°
    A   = 1000        ; // Amplitud  1000
    k   = 2*sin(ang/2);
    k  *= k           ;
    xn = 0 ; dn = A*sin(ang) ; // Valores iniciales

// Salida de 200 valores , para no hacer
// un bucle infinito

    printf("%.3lf\n",xn); // Muestro el valor inicial

    for(n=1;n<200;n++){
        xn += dn -= k*xn  ;
        printf("%.3lf\n",xn) ;
    }
}

Incluso puede implementarse sin ni siquiera calcular al inicio senos y cosenos sino manejarse con aproximaciones, ya que el avance angular siempre es un valor bajo.


Citar
En todos lados veo que usan series de taylor, o se puede usar los polinomios de Chebyshev, pero la anti trasformada como la planteas no la vi nunca.

Eso lo usás para calcular la función en un punto y lo lógico es usarlo para tablas de lookup o interpolar una tabla.

Acá la antitransformada es para hallar la ley de recurrencia y  meterla en un bucle infinito.

Citar
Por mi:
Si quiere un calculo con una ecuación en diferencia, que cargue una tabla con la diferencia entre un punto y otro, y no el valor total. Algo simple y sigue siendo una ecuación en diferencia, el concepto esta, es culpa de el docente por no ser especifico.
Y por supuesto, la suma de todos los valores que cargues en la tabla te debe dar 0 si o si. Y nunca sobrepasar los limites 0 y el limite superior que elijas ( ejemplo 4095 )

Ojo,  "ecuación en diferencias" se refiere a ecuaciones de este tipo ,  no al incremento respecto del valor anterior.   Salvo claro, que el docente haya abusado del lenguaje.


Saludos.


 

anything