PlutoSDR en Pythonï
Dans ce chapitre, nous apprenons Ă utiliser lâAPI Python pour le PlutoSDR, qui est une radio SDR Ă faible coĂ»t dâAnalog Devices. Nous couvrirons les Ă©tapes dâinstallation du PlutoSDR afin de faire fonctionner les pilotes et le logiciel, puis nous discuterons de la transmission et de la rĂ©ception avec le PlutoSDR en Python.
Installation de logiciels/pilotesï
Configuration de la VMï
Bien que le code Python fourni dans ce manuel devrait fonctionner sous Windows, Mac et Linux, les instructions dâinstallation ci-dessous sont spĂ©cifiques Ă Ubuntu 18. Si vous avez des difficultĂ©s Ă installer le logiciel sur votre OS en suivant les instructions fournies par Analog Devices, je vous recommande dâinstaller une VM Ubuntu 18 et dâessayer les instructions ci-dessous.
Installez et ouvrez VirtualBox.
CrĂ©ez une nouvelle VM. Pour la taille de la mĂ©moire, je recommande dâutiliser 50% de la RAM de votre ordinateur.
CrĂ©ez le disque dur virtuel, choisissez VDI, et allouez dynamiquement la taille. 15 Go devraient suffire. Si vous voulez ĂȘtre vraiment sĂ»r, vous pouvez utiliser plus.
Téléchargez Ubuntu 18 Desktop .iso- http://releases.ubuntu.com/18.04/
DĂ©marrez la VM. Il vous demandera le support dâinstallation. Choisissez le fichier .iso du bureau Ubuntu 18. Choisissez « installer ubuntu », utilisez les options par dĂ©faut, et une fenĂȘtre pop-up vous avertira des changements que vous ĂȘtes sur le point dâeffectuer. Cliquez sur continuer. Choisissez le nom/mot de passe et attendez que la VM finisse de sâinitialiser. AprĂšs avoir terminĂ©, la VM va redĂ©marrer, mais vous devez Ă©teindre la VM aprĂšs le redĂ©marrage.
Allez dans les paramĂštres de la VM (lâicĂŽne de lâengrenage).
Sous systÚme > processeur > choisissez au moins 3 processeurs. Si vous avez une carte vidéo réelle, alors dans affichage > mémoire vidéo > choisissez quelque chose de beaucoup plus élevé.
Démarrez votre VM.
Je recommande dâinstaller des addons dâinvitĂ©s VM. Dans la VM, allez dans Devices > Insert Guest Additions CD > cliquez sur run quand une boĂźte apparaĂźt. Suivez les instructions. RedĂ©marrez la VM. Le presse-papiers partagĂ© peut ĂȘtre activĂ© via Dispositifs > Presse-papiers partagĂ© > Bidirectionnel.
Connecter la PlutoSDRï
Si vous utilisez OSX, dans OSX, et non dans la VM, dans les prĂ©fĂ©rences systĂšme, activez « kernel extensions ». Puis installez HoRNDIS (vous devrez peut-ĂȘtre redĂ©marrer aprĂšs).
Si vous utilisez Windows, installez ce pilote : https://github.com/analogdevicesinc/plutosdr-m2k-drivers-win/releases/download/v0.7/PlutoSDR-M2k-USB-Drivers.exe
Si vous utilisez Linux, vous ne devriez pas avoir à faire quoi que ce soit de spécial.
Branchez Pluto sur la machine hĂŽte via le port USB. Veillez Ă utiliser le port USB central de Pluto, car lâautre ne sert quâĂ lâalimentation. Le branchement de Pluto devrait crĂ©er une carte rĂ©seau virtuelle, câest-Ă -dire que Pluto apparaĂźt comme un adaptateur Ethernet USB.
Sur la machine hĂŽte (pas la VM), ouvrez un terminal ou votre outil ping prĂ©fĂ©rĂ© et effectuez un ping sur 192.168.2.1. Si cela ne fonctionne pas, arrĂȘtez et dĂ©boguez lâinterface rĂ©seau.
Dans la VM, ouvrez un nouveau terminal
Effectuez un Ping sur 192.168.2.1. Si cela ne fonctionne pas, arrĂȘtez ici et dĂ©boguez. Si cela continue, câest que quelque chose dâautre Ă cette adresse IP est sur le rĂ©seau, et vous devrez changer lâIP du Pluto (ou de lâautre appareil) avant de continuer.
Notez lâadresse IP du Pluto car vous en aurez besoin lorsque nous commencerons Ă utiliser la Pluto en Python.
Installation du pilote PlutoSDRï
Les commandes de terminal ci-dessous devraient construire et installer la derniĂšre version de :
libiio, la bibliothĂšque « multiplateforme » dâAnalog Device pour lâinterfaçage du matĂ©riel.
libad9361-iio, AD9361 est la puce RF spécifique du PlutoSDR.
pyadi-iio, lâAPI Python du Pluto, câest notre objectif final, mais il dĂ©pend des deux bibliothĂšques prĂ©cĂ©dentes.
sudo apt-get install build-essential git libxml2-dev bison flex libcdk5-dev cmake python3-pip libusb-1.0-0-dev libavahi-client-dev libavahi-common-dev libaio-dev
cd ~
git clone --branch v0.23 https://github.com/analogdevicesinc/libiio.git
cd libiio
mkdir build
cd build
cmake -DPYTHON_BINDINGS=ON ..
make -j$(nproc)
sudo make install
sudo ldconfig
cd ~
git clone https://github.com/analogdevicesinc/libad9361-iio.git
cd libad9361-iio
mkdir build
cd build
cmake ..
make -j$(nproc)
sudo make install
cd ~
git clone https://github.com/analogdevicesinc/pyadi-iio.git
cd pyadi-iio
pip3 install --upgrade pip
pip3 install -r requirements.txt
sudo python3 setup.py install
Test des pilotes PlutoSDRï
Ouvrez un nouveau terminal (dans votre VM) et tapez les commandes suivantes :
python3
import adi
sdr = adi.Pluto('ip:192.168.2.1') # ou quel que soit l'IP de votre Pluton
sdr.sample_rate = int(2.5e6)
sdr.rx()
Si vous parvenez à ce stade sans erreur, passez aux étapes suivantes.
Changer lâadresse IP de Plutonï
Si, pour une raison quelconque, lâIP par dĂ©faut de 192.168.2.1 ne fonctionne pas parce que vous avez dĂ©jĂ un sous-rĂ©seau 192.168.2.0, ou parce que vous voulez que plusieurs Pluto soient connectĂ©s en mĂȘme temps, vous pouvez changer lâIP en suivant les Ă©tapes suivantes :
Modifiez le fichier config.txt sur le pĂ©riphĂ©rique de stockage de masse PlutoSDR (câest-Ă -dire le dispositif ressemblant Ă une clĂ© USB qui apparaĂźt aprĂšs avoir branchĂ© la Pluto). Entrez la nouvelle IP que vous voulez.
Ejectez le pĂ©riphĂ©rique de stockage de masse (ne dĂ©branchez pas la Pluto !). Dans Ubuntu 18, il y a un symbole dâĂ©jection Ă cĂŽtĂ© du pĂ©riphĂ©rique PlutoSDR, lorsque vous regardez lâexplorateur de fichiers.
Attendez quelques secondes, puis faites un cycle dâalimentation en dĂ©branchant le Pluto et en le rebranchant. Retournez dans le config.txt pour dĂ©terminer si votre ou vos modifications ont Ă©tĂ© enregistrĂ©es.
Notez que cette procédure est également utilisée pour flasher une image de firmware différente sur la Pluto. Pour plus de détails, voir https://wiki.analog.com/university/tools/pluto/users/firmware.
« Hacker » PlutoSDR pour augmenter la plage RFï
Les PlutoSDR sont livrĂ©s avec une gamme de frĂ©quences centrales et un taux dâĂ©chantillonnage limitĂ©s, mais la puce sous-jacente est capable de frĂ©quences beaucoup plus Ă©levĂ©es. Suivez ces Ă©tapes pour dĂ©bloquer la gamme de frĂ©quences complĂšte de la puce. Sâil vous plaĂźt garder Ă lâesprit que ce processus est fourni par Analog Devices, il est donc aussi faible risque que vous pouvez obtenir. La limitation de frĂ©quence du PlutoSDR est due au fait quâAnalog Devices utilisant lâAD9364 sur la base dâexigences strictes de performance Ă des frĂ©quences plus Ă©levĂ©es. âŠ. En tant que passionnĂ©s de SDR et expĂ©rimentateurs, nous ne sommes pas trop concernĂ©s par ces exigences de performance.
Il est temps de pirater ! Ouvrez un terminal (hĂŽte ou VM, peu importe) :
ssh root@192.168.2.1
Le mot de passe par défaut est analogique.
Vous devriez voir lâĂ©cran de bienvenue de PlutoSDR. Vous avez maintenant SSH dans le CPU ARM sur la Pluto elle-mĂȘme ! Si vous avez une Pluto avec la version 0.31 ou infĂ©rieure du firmware, tapez les commandes suivantes :
fw_setenv attr_name compatible
fw_setenv attr_val ad9364
reboot
Et pour lâutilisation de 0.32 et plus :
fw_setenv compatible ad9364
reboot
Vous devriez maintenant ĂȘtre en mesure de tuner jusquâĂ 6 GHz et de descendre jusquâĂ 70 MHz, sans oublier dâutiliser une frĂ©quence dâĂ©chantillonnage jusquâĂ 56 MHz ! Bravo !
RĂ©ceptionï
LâĂ©chantillonnage en utilisant lâAPI Python du PlutoSDR est simple. Avec nâimporte quelle application SDR, nous savons que nous devons lui indiquer la frĂ©quence centrale, la frĂ©quence dâĂ©chantillonnage et le gain (ou si nous voulons utiliser le contrĂŽle automatique du gain). Il peut y avoir dâautres dĂ©tails, mais ces trois paramĂštres sont nĂ©cessaires pour que le SDR ait suffisamment dâinformations pour recevoir des Ă©chantillons. Certains SDR ont une commande pour leur indiquer de commencer Ă Ă©chantillonner, tandis que dâautres, comme la Pluto, commencent Ă Ă©chantillonner dĂšs que vous lâinitialisez. Une fois que le tampon interne du SDR se remplit, les Ă©chantillons les plus anciens sont abandonnĂ©s. Toutes les API SDR ont une sorte de fonction « recevoir des Ă©chantillons », et pour la Pluto câest rx(), qui renvoie un lot dâĂ©chantillons. Le nombre spĂ©cifique dâĂ©chantillons par lot est dĂ©fini par la taille du tampon dĂ©finie au prĂ©alable.
Le code ci-dessous suppose que vous avez installĂ© lâAPI Python du Pluto. Ce code initialise le Pluto, fixe la frĂ©quence dâĂ©chantillonnage Ă 1 MHz, fixe la frĂ©quence centrale Ă 100 MHz et fixe le gain Ă 70 dB avec le contrĂŽle automatique du gain dĂ©sactivĂ©. Notez que lâordre dans lequel vous dĂ©finissez la frĂ©quence centrale, le gain et la frĂ©quence dâĂ©chantillonnage nâa gĂ©nĂ©ralement pas dâimportance. Dans lâextrait de code ci-dessous, nous indiquons Ă la Pluto que nous voulons quâelle nous donne 10 000 Ă©chantillons par appel Ă rx(). Nous affichons les 10 premiers Ă©chantillons.
import numpy as np
import adi
sample_rate = 1e6 # Hz
center_freq = 100e6 # Hz
num_samps = 10000 # nombre d'échantillons retournés par appel à rx()
sdr = adi.Pluto()
sdr.gain_control_mode_chan0 = 'manual'
sdr.rx_hardwaregain_chan0 = 70.0 # dB
sdr.rx_lo = int(center_freq)
sdr.sample_rate = int(sample_rate)
sdr.rx_rf_bandwidth = int(sample_rate) # largeur du filtre, il suffit de le mettre au mĂȘme niveau que la frĂ©quence d'Ă©chantillonnage pour l'instant.
sdr.rx_buffer_size = num_samps
samples = sdr.rx() # recevoir des échantillons de la Pluton
print(samples[0:10])
Pour lâinstant, nous nâallons rien faire dâintĂ©ressant avec ces Ă©chantillons, mais le reste de ce manuel est rempli de code Python qui fonctionne sur des Ă©chantillons de QI comme ceux que nous avons reçus ci-dessus.
Gain de rĂ©ceptionï
La Pluto peut ĂȘtre configurĂ© pour avoir un gain de rĂ©ception fixe ou automatique. Un contrĂŽle automatique de gain (CAG) ajustera automatiquement le gain de rĂ©ception pour maintenir un niveau de signal fort (-12dBFS pour ceux qui sont curieux). LâAGC ne doit pas ĂȘtre confondu avec le convertisseur analogique-numĂ©rique (CAN) qui numĂ©rise le signal. Techniquement parlant, lâAGC est un circuit de rĂ©troaction en boucle fermĂ©e qui contrĂŽle le gain de lâamplificateur en rĂ©ponse au signal reçu. Son objectif est de maintenir un niveau de puissance de sortie constant malgrĂ© un niveau de puissance dâentrĂ©e variable. En gĂ©nĂ©ral, le CAG ajuste le gain pour Ă©viter de saturer le rĂ©cepteur (câest-Ă -dire dâatteindre la limite supĂ©rieure de la plage du CAN) tout en permettant au signal de « remplir » autant de bits CAN que possible.
Le circuit intĂ©grĂ© de radiofrĂ©quence, ou RFIC, Ă lâintĂ©rieur de la PlutoSDR possĂšde un module CAG avec quelques rĂ©glages diffĂ©rents. (Un RFIC est une puce qui fonctionne comme un Ă©metteur-rĂ©cepteur : il Ă©met et reçoit des ondes radio). Tout dâabord, notez que le gain de rĂ©ception sur la Pluto a une gamme de 0 Ă 74.5 dB. En mode CAG « manuel », le CAG est dĂ©sactivĂ©, et vous devez indiquer au Pluto le gain de rĂ©ception Ă utiliser, par exemple :
sdr.gain_control_mode_chan0 = "manual" # désactiver l'AGC
gain = 50.0 # allowable range is 0 to 74.5 dB
sdr.rx_hardwaregain_chan0 = gain # la gamme permise est de 0 Ă 74.5 dB
Si vous voulez activer le CAG, vous devez choisir lâun des deux modes suivants :
sdr.gain_control_mode_chan0 = "slow_attack"sdr.gain_control_mode_chan0 = "fast_attack"
Et avec le CAG activĂ©, vous ne devez pas fournir une valeur Ă rx_hardwaregain_chan0. Elle sera ignorĂ©e car le Pluto ajuste lui-mĂȘme le gain du signal. La Pluto a deux modes pour le CAG : attaque rapide et attaque lente, comme indiquĂ© dans le code ci-dessus. La diffĂ©rence entre les deux est intuitive, si vous y pensez. Le mode dâattaque rapide rĂ©agit plus rapidement aux signaux. En dâautres termes, la valeur du gain change plus rapidement lorsque le signal reçu change de niveau. Lâajustement aux niveaux de puissance des signaux peut ĂȘtre important, notamment pour les systĂšmes avec mutliplexage temporelle (TDD) qui utilisent la mĂȘme frĂ©quence pour Ă©mettre et recevoir. Le rĂ©glage de la commande de gain en mode dâattaque rapide pour ce scĂ©nario limite lâattĂ©nuation du signal. Dans lâun ou lâautre de ces modes, si aucun signal nâest prĂ©sent et quâil nây a que du bruit, la commande automatique de gain maximisera le rĂ©glage du gain ; lorsquâun signal apparaĂźt, il saturera briĂšvement le rĂ©cepteur, jusquâĂ ce que la commande automatique de gain puisse rĂ©agir et rĂ©duire le gain. Vous pouvez toujours vĂ©rifier le niveau de gain actuel en temps rĂ©el avec :
sdr._get_iio_attr('voltage0','hardwaregain', False)
Pour plus de détails sur la commande automatique de gain (CAG) de la Pluto, notamment sur la maniÚre de modifier les paramÚtres CAG avancés, reportez-vous à la rubrique the « RX Gain Control » section of this page.
Transmettreï
Avant de transmettre un signal avec votre Pluto, assurez-vous de connecter un cĂąble SMA entre le port TX de la Pluto et lâappareil qui servira de rĂ©cepteur. Il est important de toujours commencer par transmettre sur un cĂąble, en particulier lorsque vous apprenez comment transmettre, pour vous assurer que la SDR se comporte comme vous le souhaitez. Maintenez toujours une puissance dâĂ©mission extrĂȘmement faible, afin de ne pas surcharger le rĂ©cepteur, car le cĂąble nâattĂ©nue pas le signal comme le fait le canal sans fil. Si vous possĂ©dez un attĂ©nuateur (par exemple 30 dB), câest le bon moment pour lâutiliser. Si vous ne disposez pas dâun autre SDR ou dâun analyseur de spectre pour faire office de rĂ©cepteur, vous pouvez en thĂ©orie utiliser le port RX sur la mĂȘme Pluto, mais cela peut devenir compliquĂ©. Je vous recommanderais de vous procurer un RTL-SDR Ă 10$ pour faire office de SDR de rĂ©ception.
Transmettre est trĂšs similaire Ă recevoir, sauf quâau lieu de dire au SDR de recevoir un certain nombre dâĂ©chantillons, nous lui donnerons un certain nombre dâĂ©chantillons Ă transmettre. Au lieu de rx_lo, nous allons dĂ©finir tx_lo, pour spĂ©cifier sur quelle frĂ©quence porteuse Ă©mettre. Le taux dâĂ©chantillonnage est partagĂ© entre le RX et le TX, donc nous allons le rĂ©gler comme dâhabitude. Un exemple complet de transmission est montrĂ© ci-dessous, oĂč nous gĂ©nĂ©rons une sinusoĂŻde Ă +100 kHz, puis transmettons le signal complexe Ă une frĂ©quence porteuse de 915 MHz, ce qui fait que le rĂ©cepteur voit une porteuse Ă 915,1 MHz. Il nây a pas vraiment de raison pratique de faire cela, nous aurions pu simplement rĂ©gler la center_freq sur 915.1e6 et transmettre un tableau de 1, mais nous voulions gĂ©nĂ©rer des Ă©chantillons complexes Ă des fins de dĂ©monstration.
import numpy as np
import adi
sample_rate = 1e6 # Hz
center_freq = 915e6 # Hz
sdr = adi.Pluto("ip:192.168.2.1")
sdr.sample_rate = int(sample_rate)
sdr.tx_rf_bandwidth = int(sample_rate) # la coupure du filtre, il suffit de la rĂ©gler sur la mĂȘme frĂ©quence d'Ă©chantillonnage.
sdr.tx_lo = int(center_freq)
sdr.tx_hardwaregain_chan0 = -50 # Augmenter pour augmenter la puissance tx, la plage valide est de -90 Ă 0 dB
N = 10000 # nombre d'échantillons à transmettre en une seule fois
t = np.arange(N)/sample_rate
samples = 0.5*np.exp(2.0j*np.pi*100e3*t) # Simulez une sinusoïde de 100 kHz, qui devrait apparaßtre à 915,1 MHz au niveau du récepteur.
samples *= 2**14 # Le PlutoSDR s'attend à ce que les échantillons soient compris entre -2^14 et +2^14, et non -1 et +1 comme certaines SDRs.
# Transmettez notre lot d'échantillons 100 fois, ce qui devrait représenter 1 seconde d'échantillons au total, si l'USB peut suivre.
for i in range(100):
sdr.tx(samples) # transmettre le lot d'échantillons une fois
Voici quelques notes sur ce code. Tout dâabord, vous voulez simuler vos Ă©chantillons IQ pour quâils soient entre -1 et 1, mais avant de les transmettre, nous devons les mettre Ă lâĂ©chelle par 2^14 Ă cause de la façon dont Analog Devices a implĂ©mentĂ© la fonction tx(). Si vous nâĂȘtes pas sĂ»r des valeurs min/max, imprimez-les simplement avec print(np.min(samples), np.max(samples)) ou Ă©crivez une instruction if pour vous assurer quâelles ne sont jamais supĂ©rieures Ă 1 ou infĂ©rieures Ă -1 (en supposant que ce code vienne avant la mise Ă lâĂ©chelle de 2^14). En ce qui concerne le gain dâĂ©mission, la gamme est de -90 Ă 0 dB, donc 0 dB est la puissance dâĂ©mission la plus Ă©levĂ©e. Nous voulons toujours commencer Ă une faible puissance dâĂ©mission, puis augmenter si nĂ©cessaire, donc nous avons rĂ©glĂ© le gain Ă -50 dB par dĂ©faut, ce qui est vers le bas. Ne vous contentez pas de le rĂ©gler sur 0 dB simplement parce que votre signal nâapparaĂźt pas; il y a peut-ĂȘtre un autre problĂšme et vous ne voulez pas griller votre rĂ©cepteur.
Transmettre des Ă©chantillons en rĂ©pĂ©titionï
Si vous voulez transmettre continuellement le mĂȘme ensemble dâĂ©chantillons de maniĂšre rĂ©pĂ©tĂ©e, au lieu dâutiliser une boucle for/while dans Python comme nous lâavons fait ci-dessus, vous pouvez dire au Pluto de le faire en utilisant une seule ligne :
sdr.tx_cyclic_buffer = True # Activer les tampons cycliques
Vous transmettez alors vos Ă©chantillons comme dâhabitude : sdr.tx(samples) une seule fois, et la Pluto continuera Ă transmettre le signal indĂ©finiment, jusquâĂ ce que le destructeur de lâobjet sdr soit appelĂ©. Pour changer les Ă©chantillons qui sont transmis en continu, vous ne pouvez pas simplement appeler sdr.tx(samples) Ă nouveau avec un nouveau jeu dâĂ©chantillons, vous devez dâabord appeler sdr.tx_destroy_buffer(), puis appeler sdr.tx(samples).
Transmettre par voie hertzienne en toute lĂ©galitĂ©ï
Dâinnombrables fois, des Ă©tudiants mâont demandĂ© sur quelles frĂ©quences ils Ă©taient autorisĂ©s Ă Ă©mettre avec une antenne (aux Ătats-Unis). La rĂ©ponse courte est aucune, pour autant que je sache. GĂ©nĂ©ralement, lorsque les gens font rĂ©fĂ©rence Ă des rĂ©glementations spĂ©cifiques qui parlent de limites de puissance dâĂ©mission, ils se rĂ©fĂšrent aux frĂ©quences suivantes the FCCâs « Title 47, Part 15 » (47 CFR 15) regulations. Mais il sâagit de rĂ©glementations pour les fabricants qui construisent et vendent des appareils fonctionnant dans les bandes ISM, et ces rĂ©glementations traitent de la maniĂšre dont ils doivent ĂȘtre testĂ©s. Un appareil de la partie 15 est un appareil pour lequel une personne nâa pas besoin de licence pour le faire fonctionner dans le spectre quâil utilise, mais lâappareil lui-mĂȘme doit ĂȘtre autorisĂ©/certifiĂ© pour montrer quâil fonctionne conformĂ©ment aux rĂ©glementations de la FCC avant dâĂȘtre commercialisĂ© et vendu. Les rĂ©glementations de la partie 15 spĂ©cifient les niveaux de puissance maximum dâĂ©mission et de rĂ©ception pour les diffĂ©rents Ă©lĂ©ments du spectre, mais rien de tout cela ne sâapplique rĂ©ellement Ă une personne transmettant un signal avec une radio SDR ou une radio de fabrication artisanale. Les seules rĂ©glementations que jâai pu trouver concernant les radios qui ne sont pas rĂ©ellement des produits vendus Ă©taient spĂ©cifiques Ă lâexploitation dâune station radio AM ou FM de faible puissance dans les bandes AM/FM. Il y a Ă©galement une section sur les « appareils de fabrication artisanale », mais il est spĂ©cifiquement dit quâelle ne sâapplique pas Ă tout ce qui est construit Ă partir dâun kit, et il serait exagĂ©rĂ© de dire quâune plate-forme dâĂ©mission utilisant une radio logicielle est un appareil de fabrication artisanale. En rĂ©sumĂ©, les rĂ©glementations de la FCC ne sont pas aussi simples que « vous pouvez transmettre Ă ces frĂ©quences uniquement sous ces niveaux de puissance », mais il sâagit plutĂŽt dâun Ă©norme ensemble de rĂšgles destinĂ©es aux tests et Ă la conformitĂ©.
Une autre façon de voir les choses serait de dire « bien, ce ne sont pas des appareils de la Partie 15, mais suivons les rĂšgles de la Partie 15 comme sâils lâĂ©taient ». Pour la bande ISM de 915 MHz, les rĂšgles sont les suivantes : « LâintensitĂ© de champ de toute Ă©mission rayonnĂ©e dans la bande de frĂ©quence spĂ©cifiĂ©e ne doit pas dĂ©passer 500 microvolts/mĂštre Ă 30 mĂštres. La limite dâĂ©mission dans ce paragraphe est basĂ©e sur un instrument de mesure employant un dĂ©tecteur moyen. » Donc, comme vous pouvez le voir, ce nâest pas aussi simple quâune puissance dâĂ©mission maximale en watts.
Maintenant, si vous avez votre licence de radio amateur (ham), la FCC vous permet dâutiliser certaines bandes rĂ©servĂ©es Ă la radio amateur. Il y a toujours des directives Ă suivre et des puissances dâĂ©mission maximales, mais au moins ces chiffres sont spĂ©cifiĂ©s en watts de puissance rayonnĂ©e effective. Ce graphique indique quelles bandes sont disponibles en fonction de votre catĂ©gorie de licence (Technicien, GĂ©nĂ©ral et Extra). Je recommande Ă toute personne intĂ©ressĂ©e par la transmission avec des SDRs dâobtenir sa licence de radioamateur, cf. ARRLâs Getting Licensed page pour plus dâinfo.
Si quelquâun a plus de dĂ©tails sur ce qui est autorisĂ© ou non, veuillez mâenvoyer un email.
Transmettre et recevoir simultanĂ©mentï
En utilisant lâastuce tx_cyclic_buffer, vous pouvez facilement recevoir et Ă©mettre en mĂȘme temps, en dĂ©clenchant lâĂ©metteur, puis la rĂ©ception. Le code suivant montre un exemple fonctionnel de transmission dâun signal QPSK dans la bande 915 MHz, de rĂ©ception et dâaffichage de la DSP.
import numpy as np
import adi
import matplotlib.pyplot as plt
sample_rate = 1e6 # Hz
center_freq = 915e6 # Hz
num_samps = 100000 # nombre d'échantillons par appel à rx()
sdr = adi.Pluto("ip:192.168.2.1")
sdr.sample_rate = int(sample_rate)
# Config Tx
sdr.tx_rf_bandwidth = int(sample_rate) # la coupure du filtre, il suffit de la rĂ©gler sur la mĂȘme frĂ©quence d'Ă©chantillonnage.
sdr.tx_lo = int(center_freq)
sdr.tx_hardwaregain_chan0 = -50 # Augmenter pour augmenter la puissance tx, la plage valide est de -90 Ă 0 dB
# Configurer Rx
sdr.rx_lo = int(center_freq)
sdr.rx_rf_bandwidth = int(sample_rate)
sdr.rx_buffer_size = num_samps
sdr.gain_control_mode_chan0 = 'manual'
sdr.rx_hardwaregain_chan0 = 0.0 # dB, augmenter pour augmenter le gain de réception, mais attention à ne pas saturer le CAN
# Créer une forme d'onde de transmission (QPSK, 16 échantillons par symbole)
num_symbols = 1000
x_int = np.random.randint(0, 4, num_symbols) # 0 to 3
x_degrees = x_int*360/4.0 + 45 # 45, 135, 225, 315 degrees
x_radians = x_degrees*np.pi/180.0 # sin() et cos() avec des angles en radians
x_symbols = np.cos(x_radians) + 1j*np.sin(x_radians) # ce qui produit nos symboles complexes QPSK
samples = np.repeat(x_symbols, 16) # 16 échantillons par symbole (impulsions rectangulaires)
samples *= 2**14 # Le PlutoSDR s'attend à ce que les échantillons soient compris entre -2^14 et +2^14, et non entre -1 et +1 comme certains SDRs.
# Start the transmitter
sdr.tx_cyclic_buffer = True # Activer les tampons cycliques
sdr.tx(samples) # début de la transmission
# Effacer le tampon juste pour ĂȘtre sĂ»r
for i in range (0, 10):
raw_data = sdr.rx()
# Recevoir des échantillons
rx_samples = sdr.rx()
print(rx_samples)
# ArrĂȘter la transmission
sdr.tx_destroy_buffer()
# Calculer la densité spectrale de puissance (version du signal dans le domaine de la fréquence)
psd = np.abs(np.fft.fftshift(np.fft.fft(rx_samples)))**2
psd_dB = 10*np.log10(psd)
f = np.linspace(sample_rate/-2, sample_rate/2, len(psd))
# Tracer le domaine temporel
plt.figure(0)
plt.plot(np.real(rx_samples[::100]))
plt.plot(np.imag(rx_samples[::100]))
plt.xlabel("temps")
# Tracer le domaine freq
plt.figure(1)
plt.plot(f/1e6, psd_dB)
plt.xlabel("Frequences [MHz]")
plt.ylabel("DSP")
plt.show()
Vous devriez voir quelque chose qui ressemble à ceci, en supposant que vous avez des antennes appropriées ou un cùble connecté :
Câest un bon exercice que de rĂ©gler lentement sdr.tx_hardwaregain_chan0 et sdr.rx_hardwaregain_chan0 pour sâassurer que le signal reçu devient plus faible/fort comme prĂ©vu.
Exercices Pythonï
Au lieu de vous fournir du code Ă exĂ©cuter, jâai créé plusieurs exercices oĂč 95 % du code est fourni et oĂč le code restant est du Python assez simple Ă crĂ©er. Les exercices ne sont pas censĂ©s ĂȘtre difficiles. Il leur manque juste assez de code pour vous faire rĂ©flĂ©chir.
Exercice 1 : DĂ©terminer le dĂ©bit de votre USBï
Essayons de recevoir des Ă©chantillons du PlutoSDR, et dans le processus, voyons combien dâĂ©chantillons par seconde nous pouvons pousser Ă travers la connexion USB 2.0.
**Votre tĂąche consiste Ă crĂ©er un script Python qui dĂ©termine le taux de rĂ©ception des Ă©chantillons en Python, câest-Ă -dire compter les Ă©chantillons reçus et suivre le temps pour dĂ©terminer le taux. Ensuite, essayez dâutiliser diffĂ©rents taux dâĂ©chantillonnage et tailles de tampon pour voir comment cela affecte le taux le plus Ă©levĂ© rĂ©alisable.
Gardez Ă lâesprit que si vous recevez moins dâĂ©chantillons par seconde que le taux dâĂ©chantillonnage spĂ©cifiĂ©, cela signifie que vous perdez/supprimez une certaine fraction dâĂ©chantillons, ce qui se produira probablement Ă des taux dâĂ©chantillonnage Ă©levĂ©s. La Pluto utilise uniquement lâUSB 2.0.
Le code suivant servira de point de départ mais contient les instructions dont vous avez besoin pour accomplir cette tùche.
import numpy as np
import adi
import matplotlib.pyplot as plt
import time
sample_rate = 10e6 # Hz
center_freq = 100e6 # Hz
sdr = adi.Pluto("ip:192.168.2.1")
sdr.sample_rate = int(sample_rate)
sdr.rx_rf_bandwidth = int(sample_rate) # la frĂ©quence de coupure du filtre, il suffit de la rĂ©gler sur la mĂȘme frĂ©quence d'Ă©chantillonnage.
sdr.rx_lo = int(center_freq)
sdr.rx_buffer_size = 1024 # c'est le tampon que le Pluto utilise pour mettre en mémoire tampon les échantillons
samples = sdr.rx() # recevoir des échantillons au large de Pluton
En outre, afin de dĂ©terminer la durĂ©e dâune opĂ©ration, vous pouvez utiliser le code suivant :
start_time = time.time()
# faire des chodes
end_time = time.time()
print('secondes écoulées:', end_time - start_time)
Voici quelques conseils pour vous aider à démarrer.
Conseil 1 : Vous devrez placer la ligne « samples = sdr.rx() » dans une boucle qui sâexĂ©cute plusieurs fois (par exemple, 100 fois). Vous devez compter combien dâĂ©chantillons vous obtenez Ă chaque appel Ă sdr.rx() tout en suivant le temps qui sâest Ă©coulĂ©.
Astuce 2 : Le fait que vous calculiez des Ă©chantillons par seconde ne signifie pas que vous devez effectuer exactement 1 seconde de rĂ©ception dâĂ©chantillons. Vous pouvez diviser le nombre dâĂ©chantillons reçus par le temps Ă©coulĂ©.
Conseil 3 : Commencez avec sample_rate = 10e6 comme le montre le code car ce taux est bien plus que ce que lâUSB 2.0 peut supporter. Vous serez en mesure de voir combien de donnĂ©es sont transmises. Ensuite vous pouvez modifier rx_buffer_size. Faites-le beaucoup plus grand et voyez ce qui se passe. Une fois que vous avez un script fonctionnel et que vous avez modifiĂ© rx_buffer_size, essayez dâajuster sample_rate. DĂ©terminez jusquâoĂč vous devez descendre pour ĂȘtre capable de recevoir 100 % des Ă©chantillons en Python (câest-Ă -dire Ă©chantillonner Ă un cycle de service de 100 %).
Conseil 4 : Dans votre boucle oĂč vous appelez sdr.rx(), essayez dâen faire le moins possible afin de ne pas ajouter de dĂ©lai supplĂ©mentaire dans le temps dâexĂ©cution. Ne faites rien dâintensif comme afficher Ă lâintĂ©rieur de la boucle.
Dans le cadre de cet exercice, vous aurez une idĂ©e du dĂ©bit maximal de lâUSB 2.0. Vous pouvez vĂ©rifier vos rĂ©sultats en ligne.
En bonus, essayez de changer la fréquence centrale et la largeur de bande rx_rf_bandwidth pour voir si cela a un impact sur la vitesse à laquelle vous pouvez recevoir des échantillons du Pluto.
Exercice 2 : crĂ©er un spectrogrammeï
Pour cet exercice, vous allez crĂ©er un spectrogramme, comme nous lâavons appris Ă la fin du chapitre Domaine frĂ©quentiel. Un spectrogramme est simplement un ensemble de FFT affichĂ©es empilĂ©es les unes sur les autres. En dâautres termes, câest une image avec un axe reprĂ©sentant la frĂ©quence et lâautre axe reprĂ©sentant le temps.
Dans le chapitre Domaine frĂ©quentiel nous avons appris le code Python pour effectuer une FFT. Pour cet exercice, vous pouvez utiliser les extraits de code de lâexercice prĂ©cĂ©dent, ainsi quâun peu de code Python de base.
Indices:
Essayez de définir sdr.rx_buffer_size à la taille de la FFT de sorte que vous exécutez toujours 1 FFT pour chaque appel à sdr.rx().
Construisez un tableau 2d pour contenir tous les rĂ©sultats de la FFT oĂč chaque ligne reprĂ©sente 1 FFT. Un tableau 2d rempli de zĂ©ros peut ĂȘtre créé avec : np.zeros((num_rows, fft_size)). AccĂ©dez Ă la ligne i du tableau avec : waterfall_2darray[i, :].
plt.imshow() est un moyen pratique dâafficher un tableau 2d. La couleur est mise Ă lâĂ©chelle automatiquement.
Comme but ultime, faire la mise Ă jour du spectrogramme en direct.