Comment générer des signaux de fréquence / impulsion?
19
Je cherche des moyens d'utiliser le Raspberry Pi comme générateur de signaux. Actuellement, je travaille à brancher un module AD9850 bon marché sur ebay. Cela générera des fréquences assez précises jusqu'à 40 MHz (70 MHz avec l'AD9851).
Je suppose que la sortie audio pourrait également être utilisée pour des formes d'onde arbitraires jusqu'à une fréquence très limitée.
Voici comment j'ai connecté le module AD9850 et un simple programme Python pour montrer comment régler la fréquence à 1000 Hz.
L'AD9850 doit fonctionner à 5 V pour fonctionner correctement avec le cristal 125 MHz. Il serait probablement correct de câbler 4 broches GPIO directement au module car ce ne sont que des entrées, mais la connexion via un MCP23017 transforme efficacement le module en un autre périphérique I²C et garantit que les entrées RPi sont sûres.
Remarque importante à propos de + 5V
La broche + 5V du GPIO ne peut pas vraiment fournir suffisamment de courant pour alimenter l'AD9850. Vous devez utiliser une alimentation 5V externe.
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()
@AlexChamberlain, c'est vrai. Pour autant que je sache, le FPR n'a rien publié de très utile à part le RPi lui-même :)
John La Rooy
Hmm, je suppose que cela pourrait être une question idiote, mais qu'est-ce qu'un symbole GPIO?
Steven Lu
@StevenLu, le grand rectangle à droite du schéma. Les anciens RPi avaient 26 broches, les plus récents ont 40 broches. voir elinux.org/…
John La Rooy
Ah d'accord. Cela semble tout simplement très naturel. Je pense que vous n'avez pas dessiné la version à 40 broches car vous n'aviez besoin que de 3 de ces broches pour le diagramme.
Steven Lu
11
Vous pourriez en théorie brancher un convertisseur N / A sur des broches GPIO, mais cela ne convient pas à la génération de signal car vous ne pourrez pas le piloter avec un timing précis, principalement parce que Linux n'est pas un système d'exploitation en temps réel.
De plus, il n'y a aucun moyen que cela puisse fonctionner à des fréquences aussi élevées.
Si 44 kHz environ suffisent, je pense que la prise audio peut être le moyen le plus simple de le faire.
John La Rooy a une bonne solution mais le circuit peut être plus compliqué que certains ne le souhaiteraient. Cela décrit une solution similaire conçue par Tom Herbison en utilisant uniquement l'AD9850, bien qu'il utilise 4 broches de signal GPIO au lieu de 2 comme la solution de John.
Tom se connecte à GPIO comme ceci:
Notez qu'il exécute l'AD9850 sur 3,3 V au lieu de 5 V. Selon cette discussion , l'AD9850 est conçu pour fonctionner à 3,3 V ou 5 V, mais certaines cartes peuvent utiliser des composants incapables de gérer 5 V pendant longtemps, donc un fonctionnement à 3,3 V peut en fait être une meilleure solution, selon la saveur de la carte AD9850. .
Ma carte AD9850 particulière avait la plupart des étiquettes de broches uniquement sous la carte, j'ai donc pris une photo de la face inférieure avant de la presser dans une carte de prototypage. Les emplacements des broches ont finalement été identiques à ceux de la carte de Tom. Sur mon tableau, FQest étiqueté FU_UQ, CLKest W_CLKet RSTest RESET.
Tom fournit ce script Python 3 pour contrôler le générateur de fonctions. Voici une copie de la v1.0 en cas de rupture du lien de téléchargement:
# 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()
Étant donné que toute utilisation des broches GPIO sur le pi nécessite de s'exécuter en tant que root, Tom décrit deux méthodes de lancement de son code python avec des privilèges root. Sa première méthode consiste à modifier l'icône du bureau Python IDE pour qu'elle s'exécute toujours en tant que root, mais cela me semble dangereux - vous ne voulez pas exécuter tous les programmes GUI python en tant que root si vous n'êtes pas obligé. La deuxième méthode consiste à exécuter à sudo idle3_partir d'une invite de commandes pour lancer l'environnement de développement intégré Python 3 avec des privilèges root chaque fois qu'il a besoin de privilèges root.
Tom ne mentionne pas l'installation de la bibliothèque RPi.GPIO python 3 donc elle peut déjà être disponible sur certaines versions de Pi OS, mais elle n'était pas disponible sur l'Occidentalis v0.2 que j'utilisais alors j'ai couru sudo apt-get install python3-rpi.gpio. Notez que Python 3 utilise un emplacement différent pour RPi.GPIO donc sudo apt-get install python-rpi.gpione rendra la bibliothèque accessible qu'à Python 2.
Une fois l'IDE Python 3 ouvert avec les privilèges root, ouvrez le fichier rpi_rfsiggen.py, puis choisissez Run -> Run Moduledans le menu ou appuyez sur F5.
J'ai pu obtenir une belle onde sinusoïdale stable de 18 kHz à 1 Vpp à partir de la broche de sortie SinB (étiquetée ZOUT2sur ma carte) lors de mon premier essai.
Si vous souhaitez simplement implémenter un générateur de fonctions pour l'audio et le Lf rf, choisissez un module AD9833 bon marché d'EBAY. Cela vous donnera des ondes sinusoïdales, carrées et triangulaires ainsi qu'une phase variable. Apparemment, pas beaucoup de bien après 7 MHz ....
Vous pourriez en théorie brancher un convertisseur N / A sur des broches GPIO, mais cela ne convient pas à la génération de signal car vous ne pourrez pas le piloter avec un timing précis, principalement parce que Linux n'est pas un système d'exploitation en temps réel.
De plus, il n'y a aucun moyen que cela puisse fonctionner à des fréquences aussi élevées.
Si 44 kHz environ suffisent, je pense que la prise audio peut être le moyen le plus simple de le faire.
la source
John La Rooy a une bonne solution mais le circuit peut être plus compliqué que certains ne le souhaiteraient. Cela décrit une solution similaire conçue par Tom Herbison en utilisant uniquement l'AD9850, bien qu'il utilise 4 broches de signal GPIO au lieu de 2 comme la solution de John.
Tom se connecte à GPIO comme ceci:
Notez qu'il exécute l'AD9850 sur 3,3 V au lieu de 5 V. Selon cette discussion , l'AD9850 est conçu pour fonctionner à 3,3 V ou 5 V, mais certaines cartes peuvent utiliser des composants incapables de gérer 5 V pendant longtemps, donc un fonctionnement à 3,3 V peut en fait être une meilleure solution, selon la saveur de la carte AD9850. .
Ma carte AD9850 particulière avait la plupart des étiquettes de broches uniquement sous la carte, j'ai donc pris une photo de la face inférieure avant de la presser dans une carte de prototypage. Les emplacements des broches ont finalement été identiques à ceux de la carte de Tom. Sur mon tableau,
FQ
est étiquetéFU_UQ
,CLK
estW_CLK
etRST
estRESET
.Tom fournit ce script Python 3 pour contrôler le générateur de fonctions. Voici une copie de la v1.0 en cas de rupture du lien de téléchargement:
Étant donné que toute utilisation des broches GPIO sur le pi nécessite de s'exécuter en tant que root, Tom décrit deux méthodes de lancement de son code python avec des privilèges root. Sa première méthode consiste à modifier l'icône du bureau Python IDE pour qu'elle s'exécute toujours en tant que root, mais cela me semble dangereux - vous ne voulez pas exécuter tous les programmes GUI python en tant que root si vous n'êtes pas obligé. La deuxième méthode consiste à exécuter à
sudo idle3_
partir d'une invite de commandes pour lancer l'environnement de développement intégré Python 3 avec des privilèges root chaque fois qu'il a besoin de privilèges root.Tom ne mentionne pas l'installation de la bibliothèque RPi.GPIO python 3 donc elle peut déjà être disponible sur certaines versions de Pi OS, mais elle n'était pas disponible sur l'Occidentalis v0.2 que j'utilisais alors j'ai couru
sudo apt-get install python3-rpi.gpio
. Notez que Python 3 utilise un emplacement différent pour RPi.GPIO doncsudo apt-get install python-rpi.gpio
ne rendra la bibliothèque accessible qu'à Python 2.Une fois l'IDE Python 3 ouvert avec les privilèges root, ouvrez le fichier
rpi_rfsiggen.py
, puis choisissezRun -> Run Module
dans le menu ou appuyez sur F5.J'ai pu obtenir une belle onde sinusoïdale stable de 18 kHz à 1 Vpp à partir de la broche de sortie SinB (étiquetée
ZOUT2
sur ma carte) lors de mon premier essai.la source
Si vous souhaitez simplement implémenter un générateur de fonctions pour l'audio et le Lf rf, choisissez un module AD9833 bon marché d'EBAY. Cela vous donnera des ondes sinusoïdales, carrées et triangulaires ainsi qu'une phase variable. Apparemment, pas beaucoup de bien après 7 MHz ....
la source