[Aporte] Generador de Señales (DDS)

Cosme,


Aca puse un video del funcionamiento basico, mas que nada para mostrar como funciona el menu a traves del encoder de mouse.

A mi generador le falta un poco de desarrollo aun, mas que nada en el firmware para poder considerarse completo (por ej: aun no genero nada en la salida TTL, me faltan funciones de sweep, señal almacenada, transferencias, etc) Por suerte, todo eso es soft :)

En cuando a hard, este generador es a la vez frecuencimetro de su salida. Me falta poner un transistor para que siga detectando señales de baja amplitud. Tambien me falta ajustar algunos presets para que la senoidal sea perfecta (en este momento, el pico superior es apenas mas angosto que el inferior)

Por ultimo, una de las ideas, ya que tengo el encoder, es hacer una rutina de ajuste fino instantaneo. Es decir: Si yo le digo al generador que salgan 20khz y el frecuencimetro incorporado me dice que hay 19999hz a la salida, con la ruedita del mouse puedo ajustar dinamicamente el prescaler para dejar la salida en la exactitud deseada.

En cuanto a lo que se ve en el osciloscopio en este video, la señal por ahi esta un poco movediza pero es causado por defectos en el trigger (es mi osc. caserito) Lo probe con un osci comercial y la señal esta quietisima.

PD: El gabinete da asco :) jaja lo hice con un stereo viejo al cual le puse un frente de aluminio cortado a las apuradas.
 
Te quedó muy bueno la ruedita esa, además el sonido termina siendo la cereza del postre :aplauso: . Está buena la presentación del display, sobre la amplitud tal vez sea más piola usar Vp en vez de Vpp.

Por cierto, muy interesante el OCR, ¿si promedias las muestras no evitás ese corrimiento?
 
Gracias cosme. Quiero destacar que no hubiera podido hacer este DDS si no me hubieras explicado tu prescaler soft para poder hacerlo con TTLs :)

Por VPP entiendo en este caso los casi 5v cuando la señal esta al 100%. Lo que hago en soft es antes de mandar las muestras de ROM a la RAM, las multiplico por 0.6 (en el caso 60%). Sabiendo que la salida ideal 100% es 5vpp, si multiplique por 0.5 tendria que decir en el display 2.5vpp.

Uso vpp porque deja de importar el offset. Usando Vp importaria? No me doy cuenta la ventaja de uno a otro salvo que uno es la mitad (leyendo aca: http://mathforum.org/library/drmath/view/56347.html)

Sobre el OCR, es el que termine desarrollando donde el usuario del foro palurdo me ayudo enormemente con las matematicas. Promediar muestras es algo que hace en pantalla solamente, si se quiere, asi que el trigger no es afectado. Como el trigger es un operacional como comparador y no esta bien diseñado, los pequeños picos de la señal hacen un pequeño jitter. No le di mas bola porque estoy en proceso de hacerme el osciloscopio nuevo, con mas memoria, mas velocidad, trigger digital, etc. usando todo lo que aprendi haciendo este.

Si el tema del osci te interesa, me gustaria mucho armar un thread juntos al respecto para que debatamos ideas. Por el momento tengo un diseño de captura digital de 1 canal que anda muy bien (en los papeles) y justamente estaba viendo de expandirlo a 2 canales sin necesidad de meter otro ADC+memoria. Me vendrian muy bien tus conocimientos sobre llaves analogicas con mosfet para esto :) Vos decime y yo armo un thread posteando lo que tengo.

Por ultimo, y volviendo al tema, este generador DDS funcionado es exactamente el mismo esquematico que puse varios posts atras, solamente que le removi el teclado (reemplazo por encoder y 2 botones), cambie valores del filtro segun tus sugerencias, y por ultimo, meti la señal analogica en la entrada de timer del PIC para que este haga de frecuencimetro.

Por ahora, si otra persona quiere un DDS sugiero que haga el de cosme que es mas sencillo y efectivo. Con el mio se llega a mas frecuencia (hasta ahora ~1.5mhz los genera sin dramas) pero falta desarrollar un poco mas el soft y actualizar los esquematicos. Si alguien quiere, solo pidalo y armo un ZIP con el proyecto en proteus + firmware + PCB (desactualizada pero usable) para que hagan el suyo propio a partir de eso, con la aclaracion del caso de que no es "armar y enchufar"
 
muy buen aporte!, me podrias explicar de nuevo como variar la frecuencia de la señal de salida, fue algo que no entendi.

Arme un circuito sencillo para probar, use un pic 18f4550 a 20Mhz y el circuito r2r.
Use un bucle "for" para arrojar (a lo bruto) el vector por el puerto c para ver com funcionaba, se ve muy bien la señal. Genera una señal alrededor de 2kHz

Entiendo que esta parte debiera estar los mas optimizado posible para obtener la maxima velocidad. Lo que no entendi es como le haces para variar la señal de salida, de un minimo (1Hz) hasta el maximo posible.

Gracias!
 
Última edición:
Disculpa aún sigo sin entenderlo al 100.

Ya leí varias veces el mensaje #10 y hay una línea en un párrafo que no entiendo (el párrafo más importante), parece ser que falta una palabra, en la tercera línea:

Entonces de esos 24 bits, solo te quedás con los últimos 8 bits más significativos y los usás como índice para el vector de la señal. El truco está en que ese vector de datos que tendrá la señal almacenada sea de 256 elementos (muestras) para que de esta forma con 8 bits puedas fácilmente esos elementos y cuando haya desborde en el índice (es decir el acumulador de 24bits desborde), vuelva al primer elemento (o muestra) del vector de datos. Fijate que de esta forma armas una cola circular de datos que siempre se repite al paso de la frecuencia que vos elegistes.


Según lo que entiendo (hasta ahora) es que tienes que jugar con los delays y la frecuencia de muestreo de los datos almacenados; por favor corrigeme si estoy mal.

Gracias!
 
Seria así:

cosmefulanito04 dijo:
Entonces de esos 24 bits, solo te quedás con los últimos 8 bits más significativos y los usás como índice para el vector de la señal. El truco está en que ese vector de datos que tendrá la señal almacenada sea de 256 elementos (muestras) para que de esta forma con 8 bits puedas fácilmente indexar esos elementos (es decir, usar un índice para seleccionar un elemento) y cuando haya desborde en el índice (es decir el acumulador de 24bits desborde), vuelva al primer elemento (o muestra) del vector de datos. Fijate que de esta forma armas una cola circular de datos que siempre se repite al paso de la frecuencia que vos elegistes.

Agregando más casos del ejemplo del mensaje, si quisiera 100Hz con una resolución de 0,105...Hz, debo ir aumentando el acumulador en 943 cuentas por c/vuelta que dá el loop, esto quiere decir que antes de la vuelta 70 el acumulador será demasiado bajo para que los últimos 8 bits modifiquen el índice:

Vuelta 69= 943*69= 65067 = 0x00FE2B (Hexa)= 0000 0000 1111 1110 0010 1011 (binario) => El índice sigue siendo 0.

Vuelta 70= 943*70= 66010 = 0x0101DA (Hexa)= 0000 0001 0000 0001 1101 1010 (binario) => El índice ahora es 1 (salen de los 8 bits más significativos).

....

Vuelta 17791= 943*17791 = 16776913 = 0xFFFED1 (Hexa)= 1111 1111 1111 1110 1101 0001 => El índice ahora es 255.

Vuelta 17792= 943*17792 = 16777856 = 0x1000280 (Hexa)= 1 0000 0000 0000 0010 1000 0000 => Como ahora hay desborde (rojo), debido a que el acumulador es de solo 24 bits, se vuelve al índice 0 y volvemos al primer elemento de la señal.

Así, se repite indefinidamente.

Más información en el mensaje #32.
 
Última edición:
Te escribo de la forma que yo termine entendiendolo:

Para simplificar, voy a escribir con valores decimales 0-255 y solo a 2 bytes (16 bits en vez de 24).

En memoria, hay almacenada una senoidal de 256 samples. Accedes a cada sample a traves del indice del vector, digamos.

El acumulador hace la operacion: ACUM = ACUM + PASO

Supongamos un acumulador y un paso de 16 bits

1- Valor inicial del acumulador: cero por lo tanto:

Byte Alto = 0
Byte Bajo = 0

2- Valor de paso: 128 en mi ejemplo

3- Entonces: 0 + 128 = 128

Byte Alto = 0
Byte Bajo = 128

4- Luego: 128 + 128 = 256

Byte Alto = 1
Byte Bajo = 0

5- Mas: 256 + 128 = 384

Byte Alto = 1
Byte Bajo = 128

Si te fijas, entre el paso 3 y el paso 5, el byte alto ha aumentado en 1 su valor (y se ha repetido en el paso 4 y 5)

Como usamos el byte alto como indice del vector de la señal en memoria, va a usar:

- Paso numero 3: sample numero 0
- Paso numero 4: sample numero 1
- Paso numero 5: sample numero 1

En el paso numero 6 seguiria acumulando por lo que usaria el sample numero 2 y asi sucesivamente.

De lo dicho, se concluye que el valor de PASO representa el prescaler que se utiliza para variar la frecuencia de salida de la señal.

Probalo vos con otros numeros y lo vas a ver claramente. Recordar que en este generador el acumulador no es de 16 bits sino de 24, proveyendo mucha mas resolucion.
 
saludos he revisado paso a paso este exelente post y e logrado hacer las simulaciones gracias al programa que realizo seaarg tomado de cosmefulanito04 muy interesante, en las siguientes imagenes muesto la señal a una frecuencia de 200khz, ahora no se si esta correcto solo faltaria pasarlo por un filtro, pretendo realizar uno pero solo hasta esta frecuencia y con sweep, observando el programa no veo la forma de salir de la rutina buclesenal, mi pregunta es el se queda colgado en este ciclo a se puede salir de el para generar otra señal, no entiendo eso jajaja
seaarg puedes colgar el firmware y la simulacion proteus para comparar gracias
thump_9529513gensenal.png

fotos-gensenal-9529513.html
 
Última edición:
cornel,

podrias indicarme con un link el mensaje o simulacion al que haces referencia? Te lo pregunto porque el generador mio no es basado en micro sino en compuertas logicas.

Si hice algunas pruebas en CCS C con el micro 18F2550 pero eran pruebas basicas, sin ningun tipo de control ni salidas de bucle ni nada de eso.

A proposito: no se si soy yo, pero no logro ampliar la imagen que pusiste

@cosmefulanito:

En este momento estoy abocado al desarrollo de mi OCR basado en fpga (200+200msps) pero cuando lo termine, el proximo proyecto es un DDS basado en CPLD o FPGA. Te imaginas lo que se podria lograr con el acumulador funcionando a 200mhz o mas? La fpga que estoy usando tiene PLLs para generar un clock (que probe) de hasta 400mhz (quiza mas) con un oscilador de 50mhz :)
 
Última edición:
@cosmefulanito:

En este momento estoy abocado al desarrollo de mi OCR basado en fpga (200+200msps) pero cuando lo termine, el proximo proyecto es un DDS basado en CPLD o FPGA. Te imaginas lo que se podria lograr con el acumulador funcionando a 200mhz o mas? La fpga que estoy usando tiene PLLs para generar un clock (que probe) de hasta 400mhz (quiza mas) con un oscilador de 50mhz :)

Es el camino, con una CPLD tenés quepoder hacer magia. Le colocás un uC simple para la interfaz con el usuario y para cambiar el acumulador y ya. De paso hacé una comunicación I2C o algo similar entre uC y CPLD/FPGA.
 
hola seaarg, haa ok bueno he estado haciendo pruebas con el pic18f2550 realmente lo ando buscando es hacer barridos de frecuencia solo hasta 200khz pero no logro salirme del bucle donde se realiza el calculo de frecuencia. gracias
 
cornel,

podrias indicarme con un link el mensaje o simulacion al que haces referencia? Te lo pregunto porque el generador mio no es basado en micro sino en compuertas logicas.

Si hice algunas pruebas en CCS C con el micro 18F2550 pero eran pruebas basicas, sin ningun tipo de control ni salidas de bucle ni nada de eso.

A proposito: no se si soy yo, pero no logro ampliar la imagen que pusiste

@cosmefulanito:

En este momento estoy abocado al desarrollo de mi OCR basado en fpga (200+200msps) pero cuando lo termine, el proximo proyecto es un DDS basado en CPLD o FPGA. Te imaginas lo que se podria lograr con el acumulador funcionando a 200mhz o mas? La fpga que estoy usando tiene PLLs para generar un clock (que probe) de hasta 400mhz (quiza mas) con un oscilador de 50mhz :)

No es por pincharte el globo pero lograr que toda la lógica te funcione a 200MHz (ni hablar de 400) es bastante peliagudo. No alcanza con que el reloj alcance esa frecuencia, la lógica y el timing tienen que alcanzarla también :)

Pero con las tecnologías actuales, trabajar a 100MHz como primer objetivo es algo fácilmente realizable. Yo comenzaría por allí. Luego de conseguido eso, iría subiendo de a poco.

Si necesitás ayuda chiflá :)
 
@chclau: estoy de acuerdo, no es nada sencillo. Para el osciloscopio que estoy haciendo con un cyclone III mande a hacer la placa doble faz a una fabrica directamente y en base a las pruebas que estoy haciendo, alcance los 200mhz (salida de clock a los ADC) y funciona. Aun no se si "bien". Eso si, recien al empezar a escribir el vhdl me di cuenta que tendria que haber usado pines de salida especificos de clock :( Igual funciona.

Aclaro que la logica interna, el nios, la memoria, etc todo funciona a 133mhz internamente. Solo hay 200mhz en la salida clock a los ADC y en la entrada de datos a los mismos (pistas de 1cm de largo max) Pude hacer un sistema con memorias fifo donde 2 conversores 8 bits a 200mhz graban en 2 sdram 16 bits a 133mhz (double buffering)

@cornel

Una idea que yo estaba manejando para ese PIC es asi: Suponte que tenes tu bucle infinito trabajando, para poder salir de el sin agregar ciclos de reloj en las instrucciones, pensaba en emplear una interrupcion (externa, cambio de estado de pin) en la cual, dentro de ella, en vez de retornar normalmente de la interrupcion, haces un salto incondicional a un NOP que este FUERA del bucle, previamente limpiando stack y cualquier otra cosa que puedas necesitar.
 
Última edición:
Subo los siguientes archivos:

  • Generador de Señal - Proyecto Altium: se encuentra el esquemático y el PCB del generador.
  • Filtro de línea - Proyecto Altium: se encuentra el esquemático y el PCB del filtro de línea.
  • Firmware: todos los archivos fuente del software para el uC (tanto C como Assembler), junto con el ejecutable ".hex".
  • Generador de Señal - Java: el ejecutable Jar para controlar el generador desde la Pc. También incluye la librería RxTx para 32/64 bits que deberán ser instalados en el directorio Java Jre de la Pc.
  • Señales: incluyo un par de señales y una función para Matlab que sirve para pasar un vector a un archivo ".txt".

Cualquier duda me avisan.

Hola! me encantó el proyecto y estoy pensando seriamente en realizar uno igual al tuyo. La duda que me surge es con que software realizaste el código y como hago para subirlo, nunca he trabajdo con este modelo de micro. Muchas gracias!
 
Para programar usé el Avr Studio 5, ahora creo que está disponible el 6. Lo podés bajar gratuitamente de la página de Atmel.

Para programar el uC (microcontrolador), usé el ponyprog con un programador muy sencillo que requiere un puerto serie. Acá podés encontrarlo:

http://electronics-diy.com/avr_programmer.php

El micro, para no meterse con SMD, podés conseguirlo en DIP, pero no sé si tenés exáctamente los mismo puertos.
 
Buenas cosme, te hago una consulta. Realicé nuevamente todo el proyecto de cero para construirlo con el micro que conseguí (Atmega32 PDIP) el hardware por suerte quedó bien pero me encuentro con un problema al generar la señal. Del puerto C utilizado al igual que vos para el conversor D/A solo obtengo salida de algunos bits, casualmente los dos bits menos significativos y los dos mas significativos funcionan pero los 4 del medio no. Quedando Bit 2 en 1 ;Bit 3 en 1 ;Bit 4 en cero y Bit 5 en 1. Alguna idea de lo que puede estar pasando?
 
Si no me equivoco, es porque al programar los fuses, no destildaste la opción de JTAG, entonces los puertos:

PC5 (TDI)
PC4 (TDO)
PC3 (TMS)
PC2 (TCK)

El control no lo tiene el soft, sino el JTAG. Desactivalo y deberían funcionar.
 
Ahh ahora me fijo, si debe ser eso. Gracias!

Solucionado eso, no tenia ni idea de dicha opcion. Ahora el tema es este la generacion sale deformada. El orden de los bits del puerto es el mismo que el de tu diseño y el R2R esta re contra revisado.

Alguna idea? Muchas gracias por tu ayuda!
 
Última edición:
Atrás
Arriba