¿Cómo puedo generar señales de frecuencia / pulso?

19

Estoy buscando formas de usar Raspberry Pi como generador de señal. Actualmente estoy trabajando en conectar un módulo AD9850 económico de eBay. Esto generará frecuencias bastante precisas de hasta 40MHz (70MHz con el AD9851).

ingrese la descripción de la imagen aquí

Supongo que la salida de audio también podría usarse para formas de onda arbitrarias hasta una frecuencia muy limitada.

existen algunas otras posibilidades?

John La Rooy
fuente

Respuestas:

13

Así es como conecté el módulo AD9850 y un simple programa Python para mostrar cómo configurar la frecuencia a 1000Hz.

El AD9850 necesita funcionar a 5V para funcionar correctamente con el cristal de 125MHz. Sería probablemente será aceptable para cablear 4 pines GPIO directamente al módulo ya que son sólo entradas, pero la conexión a través de un MCP23017 convierte efectivamente el módulo en otro I²C periférica y se asegura de las entradas RPI son seguros.

Nota importante sobre + 5V
El pin + 5V en el GPIO realmente no puede suministrar suficiente corriente para alimentar el AD9850. Debe usar un suministro externo de 5V.

RPi conectado al módulo AD9850 a través de MCP23017

from functools import partial

import smbus

def main():
    addr = 0x20
    bus = smbus.SMBus(0) # or SMBus(1) on newer pis

    # Helper functions    
    wr_dir = partial(bus.write_byte_data, addr, 0x01)
    wr = partial(bus.write_byte_data, addr, 0x13)

    # Set Pins B0-B4 of the MCP23017 to output
    wr_dir(0xF0)

    # Names of the Pins
    RST = 1 << 0
    DATA = 1 << 1
    FQ = 1 << 2
    CLK = 1 << 3

    def send_bit(bit):
        # send a single bit
        wr(DATA * bit)
        wr(CLK | DATA * bit)

    def fq():
        wr(FQ)
        wr(0)

    def init():
        wr(RST)
        wr(0)
        wr(CLK)
        wr(0)
        wr(FQ)
        wr(0) 

    freq = 1000  
    init()
    dphase = int(0.5 + (freq << 32) / 125000000.0)
    for x in range(32):
        send_bit((dphase >> x) & 1)

    # Phase bits can all be 0
for x in range(8):
    send_bit(0)

    fq()

if __name__ == "__main__":
    main()
John La Rooy
fuente
¿Es ese tu propio símbolo RPi GPIO?
Alex Chamberlain el
1
@AlexChamberlain, sí lo es. Por lo que puedo decir, el RPF no ha lanzado nada muy útil aparte del RPi en sí :)
John La Rooy
Hmm, supongo que esta podría ser una pregunta tonta, pero ¿qué es un símbolo GPIO?
Steven Lu
@StevenLu, el rectángulo grande a la derecha del esquema. Los viejos RPi tenían 26 pines, los más nuevos tienen 40 pines. ver elinux.org/…
John La Rooy
Ah, vale. Simplemente parece muy natural. Creo que no dibujó la versión de 40 pines porque de todos modos solo necesitaba 3 de esos pines para el diagrama.
Steven Lu
11

En teoría, podría conectar algunos convertidores D / A a pines GPIO, pero esto no es adecuado para la generación de señal porque no podrá conducirlo con una sincronización precisa, principalmente porque Linux no es un sistema operativo en tiempo real.

Además, no hay forma de que esto pueda funcionar a frecuencias tan altas.

Si 44 kHz más o menos es suficiente, creo que el conector de audio puede ser la forma más sencilla de hacerlo.


fuente
4

John La Rooy tiene una buena solución, pero el circuito puede ser más complicado de lo que algunos preferirían. Esto describe una solución similar diseñada por Tom Herbison usando solo el AD9850, aunque usa 4 pines de señal GPIO en lugar de 2 como la solución de John.

Tom se conecta a GPIO así: diagrama de conexión

Observe que ejecuta el AD9850 en 3.3V en lugar de 5V. Según esta discusión , el AD9850 está calificado para funcionar a 3.3V o 5V, pero algunas placas pueden usar componentes que no pueden manejar 5V por mucho tiempo, por lo que ejecutar a 3.3V puede ser una mejor solución, dependiendo de su sabor de placa AD9850 .

Mi placa AD9850 en particular tenía la mayoría de las etiquetas de clavijas solo debajo de la placa, así que tomé una foto de la parte inferior antes de presionarla en una placa de prototipos. Las ubicaciones de los pin terminaron siendo idénticas a las del tablero de Tom de todos modos. En mi pizarra, FQestá etiquetado FU_UQ, CLKes W_CLKy RSTes RESET.

Tom proporciona este script Python 3 para controlar el generador de funciones. Aquí hay una copia de v1.0 en caso de que el enlace de descarga se rompa:

# RPi RF Signal Generator v1.0

# Copyright (C) 2013 Tom Herbison MI0IOU
# Email (hidden to discourage spammers - see original rpi_rfsiggen.py file)
# Web <http://www.asliceofraspberrypi.co.uk>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# import GUI module
from tkinter import *

# import GPIO module
import RPi.GPIO as GPIO

# setup GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

# Define GPIO pins
W_CLK = 15
FQ_UD = 16
DATA = 18
RESET = 22

# setup IO bits
GPIO.setup(W_CLK, GPIO.OUT)
GPIO.setup(FQ_UD, GPIO.OUT)
GPIO.setup(DATA, GPIO.OUT)
GPIO.setup(RESET, GPIO.OUT)

# initialize everything to zero
GPIO.output(W_CLK, False)
GPIO.output(FQ_UD, False)
GPIO.output(DATA, False)
GPIO.output(RESET, False)

# Function to send a pulse to GPIO pin
def pulseHigh(pin):
    GPIO.output(pin, True)
    GPIO.output(pin, True)
    GPIO.output(pin, False)
    return

# Function to send a byte to AD9850 module
def tfr_byte(data):
    for i in range (0,8):
        GPIO.output(DATA, data & 0x01)
        pulseHigh(W_CLK)
        data=data>>1
    return

# Function to send frequency (assumes 125MHz xtal) to AD9850 module
def sendFrequency(frequency):
    freq=int(frequency*4294967296/125000000)
    for b in range (0,4):
        tfr_byte(freq & 0xFF)
        freq=freq>>8
    tfr_byte(0x00)
    pulseHigh(FQ_UD)
    return


# Class definition for RPiRFSigGen application
class RPiRFSigGen:
        # Build Graphical User Interface
        def __init__(self, master):
                frame = Frame(master, bd=10)
                frame.pack(fill=BOTH,expand=1)
                # set output frequency
                frequencylabel = Label(frame, text='Frequency (Hz)', pady=10)
                frequencylabel.grid(row=0, column=0)
                self.frequency = StringVar()
                frequencyentry = Entry(frame, textvariable=self.frequency, width=10)
                frequencyentry.grid(row=0, column=1)
                # Start button
                startbutton = Button(frame, text='Start', command=self.start)
                startbutton.grid(row=1, column=0)
                # Stop button
                stopbutton = Button(frame, text='Stop', command=self.stop)
                stopbutton.grid(row=1, column=1)


        # start the DDS module
        def start(self):
                frequency = int(self.frequency.get())
                pulseHigh(RESET)
                pulseHigh(W_CLK)
                pulseHigh(FQ_UD)
                sendFrequency(frequency)

        # stop the DDS module
        def stop(self):
                pulseHigh(RESET)

# Assign TK to root
root = Tk()

# Set main window title
root.wm_title('RPi RFSigGen')

# Create instance of class RPiRFSigGen
app = RPiRFSigGen(root)

# Start main loop and wait for input from GUI
root.mainloop()

Dado que cualquier uso de los pines GPIO en el pi requiere ejecutarse como root, Tom describe dos métodos para lanzar su código python con privilegios de root. Su primer método es modificar el ícono de escritorio IDE de Python para que siempre se ejecute como root, pero eso me parece inseguro: no es necesario ejecutar todos los programas de la GUI de Python como root si no es necesario. El segundo método es ejecutar sudo idle3_desde un símbolo del sistema para iniciar el entorno de desarrollo integrado de Python 3 con privilegios de root siempre que necesite privilegios de root.

Tom no menciona la instalación de la biblioteca RPi.GPIO python 3, por lo que puede que ya esté disponible en algunas versiones de Pi OS, pero no estaba disponible en el Occidentalis v0.2 que estaba usando, así que corrí sudo apt-get install python3-rpi.gpio. Tenga en cuenta que Python 3 usa una ubicación diferente para RPi.GPIO, por sudo apt-get install python-rpi.gpiolo que solo hará que la biblioteca sea accesible para Python 2.

Una vez que el IDE de Python 3 esté abierto con privilegios de root, abra el archivo rpi_rfsiggen.py, luego elija Run -> Run Moduledel menú o presione F5.

Pude obtener una buena onda sinusoidal estable de 18kHZ a 1Vpp desde el pin de salida SinB (etiquetado ZOUT2en mi placa) en mi primer intento.

Chris Dragon
fuente
3

Si solo desea implementar un generador de funciones para audio y Lf rf, elija un módulo AD9833 barato de EBAY. Esto le dará ondas sinusoidales, cuadradas y triangulares, más fase variable. Aparentemente no es muy bueno después de 7 MHz ...

ingrese la descripción de la imagen aquí

Steve
fuente
Debe haber una razón por la que esos módulos son mucho más caros que los módulos AD9850. ¿Alguna idea de por qué?
John La Rooy el