Jak mogę generować sygnały częstotliwości / impulsów?

19

Patrzę na sposoby wykorzystania Raspberry Pi jako generatora sygnału. Obecnie pracuję nad podłączeniem niedrogiego modułu AD9850 z serwisu eBay. To wygeneruje dość dokładne częstotliwości do 40 MHz (70 MHz w AD9851).

wprowadź opis zdjęcia tutaj

Wydaje mi się, że wyjście audio może być również wykorzystane do arbitralnych przebiegów do bardzo ograniczonej częstotliwości.

Czy są jakieś inne możliwości?

John La Rooy
źródło

Odpowiedzi:

13

Oto jak podłączyłem moduł AD9850 i prosty program w języku Python, aby pokazać, jak ustawić częstotliwość na 1000 Hz.

AD9850 musi pracować przy napięciu 5 V, aby poprawnie działać z kryształem 125 MHz. To prawdopodobnie będzie ok do drutu 4 piny GPIO bezpośrednio do modułu, ponieważ są one tylko wejść, ale łączenie poprzez MCP23017 skutecznie odwraca modułu do innego I²C peryferyjnych i pilnuje wejścia RPI są bezpieczne.

Ważna uwaga na temat +
5 V Pin + 5 V w GPIO nie może tak naprawdę dostarczyć wystarczającej ilości prądu do zasilania AD9850. Należy użyć zewnętrznego źródła zasilania 5 V.

RPi podłączone do modułu AD9850 przez 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
źródło
Czy to twój własny symbol RPi GPIO?
Alex Chamberlain,
1
@AlexChamberlain, tak to jest. O ile mogę stwierdzić, RPF nie wydało nic bardzo przydatnego oprócz samego RPi :)
John La Rooy
Hmm, chyba to głupie pytanie, ale co to jest symbol GPIO?
Steven Lu
@StevenLu, duży prostokąt po prawej stronie schematu. Stare RPi miały 26 pinów, nowsze mają 40 pinów. patrz elinux.org/…
John La Rooy
W porządku To po prostu wydaje się bardzo naturalne. Myślę, że nie narysowałeś wersji 40-pinowej, ponieważ i tak potrzebowałeś tylko 3 z tych pinów do schematu.
Steven Lu
11

Teoretycznie możesz podłączyć konwerter D / A do styków GPIO, ale nie jest to odpowiednie do generowania sygnału, ponieważ nie będziesz w stanie sterować nim z precyzyjnym taktowaniem, głównie dlatego, że Linux nie jest systemem operacyjnym czasu rzeczywistego.

Nie ma też możliwości, aby działał on przy tak wysokich częstotliwościach.

Jeśli około 44 kHz wystarcza, uważam, że audio jack może być najprostszym sposobem na zrobienie tego.


źródło
4

John La Rooy ma dobre rozwiązanie, ale obwód może być bardziej skomplikowany niż niektórzy by woleli. To opisuje podobne rozwiązanie zaprojektowane przez Toma Herbison używając tylko AD9850, chociaż nie używa 4 styki sygnałowe GPIO zamiast 2 Podoba rozwiązania Jana.

Tom łączy się z GPIO w następujący sposób: diagram połączeń

Zauważ, że zasila AD9850 napięciem 3,3 V zamiast 5 V. Zgodnie z tą dyskusją , AD9850 może być zasilany napięciem 3,3 V lub 5 V, ale niektóre płyty mogą używać komponentów, które nie są w stanie wytrzymać 5 V przez długi czas, więc praca z napięciem 3,3 V może być lepszym rozwiązaniem, w zależności od upodobań płyty AD9850 .

Moja konkretna płyta AD9850 miała większość etykiet ze szpilkami tylko pod płytką, więc zrobiłem zdjęcie spodu, zanim wcisnąłem ją w płytkę prototypową. W każdym razie lokalizacje pinów były identyczne z tymi na tablicy Toma. Na mojej planszy FQjest oznaczony FU_UQ, CLKjest W_CLKi RSTjest RESET.

Tom udostępnia ten skrypt Python 3 do sterowania generatorem funkcji. Oto kopia wersji 1.0 na wypadek, gdyby link do pobrania kiedykolwiek się zepsuł:

# 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()

Ponieważ każde użycie pinów GPIO na pi wymaga uruchomienia jako root, Tom opisuje dwie metody uruchamiania swojego kodu python z uprawnieniami roota. Jego pierwszą metodą jest zmodyfikowanie ikony pulpitu Python IDE, aby zawsze działała jako root, ale wydaje mi się to niebezpieczne - nie chcesz uruchamiać wszystkich programów GUI Pythona jako root, jeśli nie musisz. Druga metoda polega na uruchomieniu sudo idle3_z wiersza polecenia w celu uruchomienia zintegrowanego środowiska programistycznego Python 3 z uprawnieniami roota, gdy tylko potrzebne są uprawnienia roota.

Tom nie wspomina o instalacji biblioteki python 3 RPi.GPIO, więc może być już dostępna w niektórych wersjach Pi OS, ale nie była dostępna w Occidentalis v0.2, którego używałem, więc uruchomiłem sudo apt-get install python3-rpi.gpio. Zauważ, że Python 3 używa innej lokalizacji dla RPi.GPIO, dzięki sudo apt-get install python-rpi.gpioczemu biblioteka będzie dostępna tylko dla Python 2.

Gdy Python 3 IDE zostanie otwarty z uprawnieniami administratora, otwórz plik rpi_rfsiggen.py, a następnie wybierz Run -> Run Modulez menu lub naciśnij F5.

Przy ZOUT2pierwszej próbie udało mi się uzyskać ładną, stabilną falę sinusoidalną 18kHz przy 1Vpp ze styku wyjściowego SinB (oznaczonego na mojej płycie).

Chris Dragon
źródło
3

Jeśli chcesz zaimplementować generator funkcji audio i Lf rf, wybierz tani moduł AD9833 z EBAY. To da ci sinusoidalne, kwadratowe i trójkątne fale plus zmienną fazę. Najwyraźniej niewiele powyżej 7 MHz ....

wprowadź opis zdjęcia tutaj

Steve
źródło
Musi istnieć powód, dla którego moduły te są o wiele droższe niż moduły AD9850. Masz pomysł, dlaczego?
John La Rooy,