Red Pitaya - SDR - Erfahrungsaustausch gesucht

  • Hallo Markus,

    ich dachte Du meinst die Eingangsabtastung, aber nach Deinem Bild zu urleilen sind es die
    Ausgangssignale die der RP erzeugt, die nicht sauber sind - richtig?

    Richtig.
    Anfangs war ich mir nicht sicher, wo die Spurs im Spektrum herkamen, da ich das Spektrum mit den RP ADCs aufgenommen hatte. Mit dem externen Spektrum Analyzer zeigt sich nun, dass bereits die aus den DACs herauskommenden Signale verseucht sind. Ich hatte noch eine Vergleichsmessung gemacht, wo ich den Spektrum Analyzer Eingang einfach unbeschaltet gelassen hatte: Da waren keine Stoerungen zu sehen. Den Luefter moechte ich nochmal abklemmen um zu sehen, ob das eine Verbesserung bringt. Ich bin allerdings nicht sehr optimistisch. Ein weiterer Versuch waere, den Teil zwischen Kuehlkoerper und SMA Buchsen in Kupferfolie einzuwickeln. Hier gibt es noch viel zu experimentieren :thumbup:

    Ciao,
    Uwe / DO8UL.

  • Hallo Uwe, Markus und Mitleser,
    ich freue mich, dass der Thread wieder auflebt!
    Besonderen Dank an Markus für die Änderungen in der Datei "eth0".
    Gestern habe ich erfolglos herumprobiert, aber dank der Umstellung auf statische Adressen funktioniert es nun endlich...
    Mit Linux hatte ich lange Zeit nichts zu tun und muss mich wieder einarbeiten.
    Eine Frage am Rande: Wie vergrößert man gefahrlos (ohne Datenverlust) eine Partition auf der SD- Karte?
    73, Wolfgang

  • Hallo Wolfgang und Mitleser,


    um Partitionen zu bearbeiten benutze ich eine Live CD von "gparted" . Das ISO runterladen
    und CD brennen. Habe aber bisher nur danit an Festplatten gearbeitet und keine Fehlschläge
    hinnehmen müssen. Nur mal so als kleiner Beitrag, vielleicht hat ja jemand damit noch mehr
    Erfahrung.


    73 de

    Manfred , dl3arw

  • Hallo Wolfgang, Uwe und OMs,


    Ich habe einige Sereenshots zum IQ-Gen vom Uwe angehängt.
    Mir ist aufgefallen, dass ein XY-Darstellung nicht immer den selben
    Wert liefert.


    z.B.


    nach dem Einschalten des RP


    Bild #1: (Punkt in der Bildmitte, da kein Signal am DAC)


    Bild #2: (schöner Kreis bei dem Aufruf von iqgen mit folgenden Parametern)


    ./iq 1.0e6 -900 +0.0 +0.0


    Bild #3: (Nun Phase nicht um 90° sondern um 45° verschoben - Aufruf von iqgen mit folgenden Parametern)


    ./iq 1.0e6 -450 +0.0 +0.0


    Bild #4: (nun wieder den verhergehenden Zustand wieder herstellen d.h. Phase um 90° verschoben)


    ./iq 1.0e6 -900 +0.0 +0.0


    Leider liefert diese erneute Einstellung keinen unverzehrten Kreis mehr.



    Was meinst Du Uwe dazu?



    Wolfgang,


    um eine Partition einer SD-Karte unter Linux zu vergrößern, gehst Du bitte wie folgt vor.



    Partitionstabelle des Karten-Image mit fdisk -l /dev/<SD-Karten-Name> betrachten


    Bei mir ist <SD-Karten-Name> z.B. mmcblck0, könnte aber auch sdb oder sdc sein,
    je nach Anzahl der verbauten Disks im Rechner.


    Hilfreich ist der Befehl lsscsi und auch lsusb, der angeschlossene Devices zeigt.


    Bei meinem RP liefert fdisk -l die folgende Ausgabe



    root@red-pitaya:/home/sdr/iqgen# fdisk -l /dev/mmcblk0


    Disk /dev/mmcblk0: 14.9 GiB, 15931539456 bytes, 31116288 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0x0004085a


    Device Boot Start End Sectors Size Id Type
    /dev/mmcblk0p1 8192 30719 22528 11M e W95 FAT16 (LBA)
    /dev/mmcblk0p2 30720 31116287 31085568 14.8G 83 Linux


    Dies ist aber bereits die Ausgabe für meine vergrößerte Partition mmcblk0p2.


    Wenn Du das Original-Image auf die SD-Karte mit dd übertragen hast und der Aufbau
    wie folgt ist:


    /dev/mmcblk0p1 8192 30719 22528 11M e W95 FAT16 (LBA)
    /dev/mmcblk0p2 30720 XXXXXX YYYYYY ZZ.8G 83 Linux


    und du willst die letzte Partition vergroßern, so musst Du:


    1) mit fdisk die Partition #2 löschen
    2) mit fdisk die Partition #2 neu Anlegen (primär Partition)
    2a) als Startwert der Partition #2 den Endwert der Partition #1 + 1 angeben
    hier ist es der Wert 30720 = 30719 + 1
    2b) den Endwert der Partition #2 als letzten größtmöglichen Wert der SD-Karte nehmen.
    Diesen Wert ermittelt man am besten vor dem Draufspielen des Images mit fdisk -l /dev/...
    3) die neu angelegte Partition durch Speichern permanent machen.


    Die einzelnen Kommandos lauten unter fdisk:


    1) fdisk /dev/mmcblk0 (diesmal ohne -l für list d.h. nur ansehen und nichts modifizieren)
    2) <p> <== Partitionstabelle erneut zeigen
    3) <d> Partition
    3) <2> #2 löschen
    4) <n> neue partition anlegen
    5) <p> eine primäre Partition als Type wehlen
    6) ... Start und Stop Block setzen
    7) <p> Partitionstabelle nochmal ansehen und auf Fehler (Überlappungen) prüfen
    8a) <q> quit, ohne speichern raus - wenn nötig
    8b) <w> veränderte Partitionstabelle schreiben.
    8c) <q> program verlassen.


    Hoffe keinen Schritt vergessen zu haben - war aus dem Gedächtnis.


    Bevor man Punkt 1 - 8 durchführt muss man sicherstellen, das beim Einstecken der
    SD-Karte diese nicht sofort vom System eingebunden wurde (mount Befehl)
    Falls man einen Eintrag wie


    /dev/mmcblk0p1 on xyz
    /dev/mmcblk0p2 on xyz


    findet,
    diesen mit umount /dev/mmcblk0p1 oder/und umount /dev/mmcblk0p2 aushängen.


    Alles als root user!!!


    Jetzt muss man nur noch das Filesystem der zweiten Partition mit fsck analysieren


    fsck -f /dev/mmcblk0p2


    und dann den Resize-Vorgang anstoßen:


    resize2fs /dev/mmcblk0p2


    geschafft - und ich auch ;)


    Gruß
    Markus

  • Hallo Uwe,


    wie sind die Werte


    const int dcoffs = -155;
    const int trans0 = 30;
    const int trans1 = 300;


    aus der iq.c Datei zu verstehen.


    Hast Du diese empirisch ermittelt für Deinen RP?


    Bei mir liefert ein erneuter Aufruf mit +950 oder -850 als Parameter
    für die Phase einen kreisrunden Kreis.


    Sieht aus, alls wenn nach dem erstmalliegem Start, irgend ein Offset von
    50 in Phasen Buffer dazukommen würde.


    Gruß
    Markus
    DL8MBY

  • Hallo Uwe,


    einen habe ich noch ;)


    Ich verstehe folgenden Zusammenhang nicht:
    In der ersten if-Anweisung wird dafür gesorgt, dass der
    Phasenparameter zwischen -1799 und + 1800 liegt,
    sonst wird der Programmablauf unterbrohen.
    In der Zugehörigen else-Anweisung wird der Phasenwert
    Modulo 3600 geteilt, aber der Rest ist ja immer gleich dem
    ursprünglichem Wert des Phasenparameters, da dieser
    doch immer kleiner 1800 ist.


    Kannst Du mir erklären was Du mit der Modulo 3600 Division
    bezweckst. Irgend wie stehe ich auf dem Schlauch, was diese
    Codesequenz angeht.


    /* Phase Offset */
    int32_t phase_offset = atoi(argv[2]);
    if ((phase_offset < -1799) || (phase_offset > 1800)) { <============= 1.
    fprintf(stderr, "Invalid phase shift: %s\n", argv[2]);
    usage();


    return -1;


    } else {
    phase_offset = phase_offset % 3600; <============== 2.
    if (phase_offset < 0) {
    phase_offset += 3600;
    }


    /* scale it to match AWG buffer length */
    phase_offset = n * phase_offset / 3600;


    }



    Danke für Deine Mühe schon mal im Vorraus.


    Gruß
    Markus

  • Hallo Uwe,


    ich schon wieder,


    habe halt RP Blut geleckt ;)


    ist das der Code in dem Du eine LTU für den Sin/Cos aufbaust
    um sie dann an den Kanal A/B zu schicken?


    for(uint32_t i = 0; i < n; i++) {
    data = round(amp1 * cos(2*M_PI*(double)i/(double)n));
    if (data < 0) {
    data += (1 << 14);
    }

    g_awg_cha_mem[i] = data;

    data = round(amp2 * cos(2*M_PI*(double)((phase_offset + i) % n)/(double)n));
    if (data < 0) {
    data += (1 << 14);
    }

    g_awg_chb_mem[i] = data;


    Anscheinend braucht man diese _agw_ Funktionen um mit dem Konfiguriertem FPGA zu kommunizieren.


    Wo kann man sich über die Aufrufe


    g_awg_reg->state_machine_conf = 0x000041;


    und


    g_awg_reg->state_machine_conf = 0x110011;


    schlau machen, wie sind die Flags zu intepretieren.



    Markus


    Konnte meine Frage selbst beantworten:


    uint32_t state_machine_conf;
    /** @brief Offset 0x04 - Channel A amplitude scale and offset
    *
    * Channel A amplitude scale and offset register (offset 0x04) used to set the
    * amplitude and scale of output signal: out = (data * scale)/0x2000 + offset
    * bits [31:30] - Reserved
    * bits [29:16] - Amplitude offset
    * bits [15:14] - Reserved
    * bits [13: 0] - Amplitude scale (0x2000 == multiply by 1, unsigned)
    */


    aus fpga_awg.h

  • Hallo OMs,


    die ersten Schritte sind wie immer erwas Mühsam.


    Verstehe ich das soweit richtig, dass der RP im FPGA bereits vorkonfigurierte
    Funktionsblöcke beinhaltet, auf die man dan z.B. über Libs / Header-Files
    zugreifen kann.


    z.B. Arbitrary Waveform Generator (AWG) FPGA controller als Funktionsblock
    kann über die Files fpga_awg.h / fpga_awg.c angesprochen werden.


    Solange der FPGA nicht neu mit Strukturanweisungen gefüllt wird, wozu man ja die
    Xilinx-Tools braucht, kann man auf diese vorkonfigurierten Strukturen, die im
    Auslieferungszustand vorhanden sing, zugreifen.


    Für heute genug gespielt - Jetzt gehts ins Bett ;)


    Morgen ist ja auch noch ein Tag.


    Markus

  • Hallo Markus,

    Danke fuer die x/y Plots. Ich denke, Du hast einen Bug gefunden: Kannst Du auf die Schnelle mal hier:
    https://bitbucket.org/ul5255/c…/iq.c?at=default#iq.c-123


    die Konstante auf 0x410041 aendern und Deine x/y Plots nochmal machen? Die trans0 und trans1 sind Ueberbleibsel aus dem urspruenglichen Code und koennen raus. DCOFFS kalibriert evtl. vorhandene kleine DC Offsets heraus. Kannste ja mal auf Null setzen und versuchen Dein Hameg einen DC Offset berechnen zu lassen. Modulo 3600 kann auch raus. Am Anfang hatte ich den Check auf Bereich [-179.9, +180.0] nicht drinn und musste halt normieren. Ich freue mich sehr, dass Du den Code so durchspielst.


    Perspektivisch moechte ich die Signal-Generierung im FPGA umbauen. Ich finde den aktuellen Ansatz etwas "unkonventionell". Ich will eigentlich nicht bei jedem Frequenz oder Phasenwechsel jedes Mal wieder den kompletten AWG Buffer neu beschreiben. Bei einer klassischen DDS Implementierung reichen auch Updates eines Tuning Words oder des Phasenakkumulators. Aber an den Verilog Code habe ich mich noch nicht rangetraut.

    Ciao,
    Uwe / DO8UL.

  • Hallo Markus,

    Verstehe ich das soweit richtig, dass der RP im FPGA bereits vorkonfigurierte
    Funktionsblöcke beinhaltet, auf die man dan z.B. über Libs / Header-Files
    zugreifen kann.


    z.B. Arbitrary Waveform Generator (AWG) FPGA controller als Funktionsblock
    kann über die Files fpga_awg.h / fpga_awg.c angesprochen werden.

    Ja, dass ist richtig. Im Verilog (oder VHDL) definierst Du die Funktionsbloecke. Laufzeit-Parametrierung dann ueber Register die ueber mmap in den Linux Userspace eingeblendet werden und somit fuer normale Programme les-/schreibbar sind. Uebrigens kann der Red Pitaya ARM zur Laufzeit neue Bitstreams in den FPGA laden. Theoretisch kann man sich also auf der SD Karten eine ganze Bibliothek an fertig synthetisierten Komponenten ablegen und dynamisch den FPGA umkonfigurieren, ohne den Red Pitaya neu zu booten!

    Ciao,
    Uwe / DO8UL.

  • HAllo Uwe,


    danke für Deine ausführiche Antwort.


    Zu der Konstantenänderung (auf die schnelle klappt es leider nicht)


    "die Konstante auf 0x410041"


    musst Du mir bitte noch sagen wo ich diese ändern soll.


    Es gibt ja zwei Stellen, wo sie gesetzt werden:


    Zeile 123: g_awg_reg->state_machine_conf = 0x000041;


    und


    Zeile 145: g_awg_reg->state_machine_conf = 0x110011;


    oder sollen beide auf den o.g. Wert geändert werden?


    Markus

  • Hall Markus,
    nur Zeile 123 aendern. Da werden die Generatoren angehalten.
    Aktuell so woe ich das sehe leider nur ein Kanal. Deshalb auch
    der sich langsam akkumulierende Phasenversatz.

    Ciao,
    Uwe / DO8UL.

  • Hallo Markus und weitere Interessierte,
    Ich habe einen Update im Code gemacht, der hoffentlich die von Markus gefundenen Probleme behebt. Ich selbst werde fruehestens heute Abend dazukommen, alles auszuprobieren. Ueber Rueckmeldungen wuerde ich mich freuen.

    Ciao,
    Uwe / DO8UL.

  • Hallo Uwe,


    möglicherweise ist dies nicht der Richtige Ort diese Frage zu stellen.
    Ich versuche es trotzdem:


    Sollte es in der fpga_awg.h statt


    typedef struct awg_reg_t {
    /** @brief Offset 0x00 - State machine configuration
    *
    * State machine configuration register (offset 0x00):
    * bits [31:24] - Reserved
    * bit [ 23] - Channel B output set to 0
    * bit [ 22] - Channel B state machine reset
    * bit [ 21] - Channel B set one time trigger
    * bit [ 20] - Channel B state machine wrap pointer
    * bits [19:16] - Channel B trigger selector
    * bits [15: 8] - Reserved
    * bit [ 7] - Channel B output set to 0
    * bit [ 6] - Channel B state machine reset
    * bit [ 5] - Channel B set one time trigger
    * bit [ 4] - Channel B state machine wrap pointer
    * bits [ 3: 0] - Channel B trigger selector
    *
    */


    nicht


    typedef struct awg_reg_t {
    /** @brief Offset 0x00 - State machine configuration
    *
    * State machine configuration register (offset 0x00):
    * bits [31:24] - Reserved
    * bit [ 23] - Channel B output set to 0
    * bit [ 22] - Channel B state machine reset
    * bit [ 21] - Channel B set one time trigger
    * bit [ 20] - Channel B state machine wrap pointer
    * bits [19:16] - Channel B trigger selector
    * bits [15: 8] - Reserved
    * bit [ 7] - Channel A output set to 0
    * bit [ 6] - Channel A state machine reset
    * bit [ 5] - Channel A set one time trigger
    * bit [ 4] - Channel A state machine wrap pointer
    * bits [ 3: 0] - Channel A trigger selector
    *
    */


    oder umgekehrt


    typedef struct awg_reg_t {
    /** @brief Offset 0x00 - State machine configuration
    *
    * State machine configuration register (offset 0x00):
    * bits [31:24] - Reserved
    * bit [ 23] - Channel A output set to 0
    * bit [ 22] - Channel A state machine reset
    * bit [ 21] - Channel A set one time trigger
    * bit [ 20] - Channel A state machine wrap pointer
    * bits [19:16] - Channel B trigger selector
    * bits [15: 8] - Reserved
    * bit [ 7] - Channel B output set to 0
    * bit [ 6] - Channel B state machine reset
    * bit [ 5] - Channel B set one time trigger
    * bit [ 4] - Channel B state machine wrap pointer
    * bits [ 3: 0] - Channel B trigger selector
    *
    */


    heisen?


    Markus

  • Hallo Markus,
    die erste von Dir vorgeschlagene Variante ist richtig, siehe auch die Referenz dazu.
    Ich habe noch einen Update ins Repo geladen.

    Ciao,
    Uwe / DO8UL.

  • Hallo Markus,
    Hier uebrigens noch die offiziellen Anweisungen, wie man DC Offsets messen und kompensieren kann. Damit kannst Du dann Dein persoenliches dcoffs in iq.c entsprechend anpassen. Obwohl, wenn ich so drueber nachdenke: Eigentlich koennte der I/Q Generator ja gleich den EEPROM auslesen anstatt dass ich den DC Offset hart im Quell-Text reinschreibe :thumbup:
    Muss ich bei Gelegenheit mal ausprobieren ...

    Ciao,
    Uwe / DO8UL.

  • Hallo Uwe,


    kann bestätigen, dass der neue Code immer einen Kreis zeichnet.



    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 -900 +0.0 +0.0 <==KreIs
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 +900 +0.0 +0.0 <==KreIs
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 +450 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 +1350 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 -1350 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 -450 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 -900 +0.0 +0.0 <==KreIs
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 +900 +0.0 +0.0 <==KreIs


    Glückwunsch.


    Jetzt werde ich den DC-Offset bestimmen.


    Markus

  • Hallo Uwe,


    neues Problem ;)


    root@red-pitaya:/home/sdr/iqgen2# ./iq 10.0e6 +900 +0.0 +0.0 <= Bild #1 Kreis ok
    root@red-pitaya:/home/sdr/iqgen2# ./iq 1.0e6 +900 +0.0 +0.0 dito
    root@red-pitaya:/home/sdr/iqgen2# ./iq 5.0e6 +900 +0.0 +0.0 dito
    root@red-pitaya:/home/sdr/iqgen2# ./iq 8.0e6 +900 +0.0 +0.0 dito
    root@red-pitaya:/home/sdr/iqgen2# ./iq 9.0e6 +900 +0.0 +0.0 dito
    root@red-pitaya:/home/sdr/iqgen2# ./iq 10.0e6 +900 +0.0 +0.0 <= Bild #2 Kreis verformt
    root@red-pitaya:/home/sdr/iqgen2# ./iq 12.0e6 +900 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 11.0e6 +900 +0.0 +0.0
    root@red-pitaya:/home/sdr/iqgen2# ./iq 15.0e6 +900 +0.0 +0.0 <= Bild #3 kreis verformt und größer!



    Ab zehn MHz wird der Kreis Unsymetrisch - (keine Elipse sondern ein Tropfen!)
    Zudem steigt der Pegel an, verbeulter Kreis wird größer


    Siehe Anhang




    Markus


    Anbei noch meine Calibrationskonstanten aus dem EEPROM:


    root@red-pitaya:/home/sdr/iqgen2# calib -r -v
    FE_CH1_FS_G_HI = 45870551
    FE_CH2_FS_G_HI = 45870551
    FE_CH1_FS_G_LO = 1016267064
    FE_CH2_FS_G_LO = 1016267064
    FE_CH1_DC_offs = 78
    FE_CH2_DC_offs = 25
    BE_CH1_FS = 42755331
    BE_CH2_FS = 42755331
    BE_CH1_DC_offs = -150
    BE_CH2_DC_offs = -150