Spiele mich seit einigen Tagen mit der FW auf github
für den uSDX+ (white buttons, Ver. 4.00e)
Nachdem es mit gelungen ist die FW in der Arduino IDE
(2.3.9) zur compilieren und auf das Gerät zu laden wollte
ich mir die CW Aussendung mal am Oszi anschauen.
Dabei habe ich den unschönen Anfangs-Spike beim Start der
Aussendung beobachtet und wollte den reduzieren, siehe Anhang.
Leider ist mir ein besseres CW Shaping noch nicht gelungen.
Im .ino Code spielt sich die Sache offensichtlich im Zeilen-
Bereich an/ab Position 2870++.
Mir scheint aber , dass die HF Formung erst nach ca. 1,5ms
tatsächlich von diesen Code beeinflusst wird, wo hingegen
der Anfangs-Spike aus der Initialisierung der Si5351 herrührt.
Ich habe keinen Parameter in der laufenden FW wie auch kein
#define im Code gefunden, der mir da weiter hilft, bin aber
auch kein Experte was AVR und Arduino angeht.
Leider habe ich mit dieser Frage auch kein Erfolg in dem ucx
Forum von https://groups.io gehabt, da meine Postings trotz
gültiger Anmeldung in diesem Forum immer ins Leere laufen und
Emails an die Mods auch nicht beantwortet wurden.
Hatte mich am Rande mit dem uSDX beschäftigt, genauer mit der Qualität der SSB-Signalerzeugung. Stecke nicht tief drin, mit Arduino hatte ich nur mal ein PoC aufgebaut.
Trotzdem: ich denke auch, du hast die richtige Stelle im Code für die CW-Rampe gefunden. Das trotzdem ein Click entsteht liegt wohl am falschen Timing.
Damit der Empfänger von der Antenne getrennt wird und der SI5351-Takt die Endstufe erreicht, muss PB0 auf low schalten. Eine weitere Sendebedingung ist ein aktivierter SI5351-Takt.
Damit kein Glitch entsteht, muss früh genug das Output-Compare Register OCR1BL auf 0 stehen, damit über PB2 und Q5 die Endstufe Q2/Q3/Q4 keinen Takt erhält. Früh genug heißt incl Integrationszeit R28/C23, 0,5ms vor PB2 oder CLK2 sollten genügen wenn der im Netz ausgegrabene Stromlaufplan mit deinem Gerät übereinstimmt.
Um die Sache einzugrenzen, könntest Du PB0 und PB2 auf dem Oszi mitschneiden. Hast du noch ein Kanal frei, auch CLK2 vom SI5351.
Außerdem den Schalter #ifdef KEY_CLICK anschauen.
Weitere Codestellen: Zeile 4976
1
#ifdef KEY_CLICK
2
if(OCR1BL!=0){
3
for(uint16_ti=0;i!=31;i++){// ramp down of amplitude: soft falling edge to prevent key clicks
Ich habe die Variante, die keinen vierten BS170 zum Schalten der drei PA FETs verwenden.
siehe Anhang. Signal kommt direkt über PB2 und ein RC-Glied als PA-BIAS als geglättete
PWM an das Gate der drei FETs und von einem Gate als Buffer vom Si5351.
PB0 ist zum RX Muten und so glaube ich hat es keinen Einfluß auf das CW HF Signal am Ant.
Ausgang.
Die von Dir genannten Code-Stellen habe ich mir bereits angesehen und habe auch mit dem
OCR1B1 gespielt, der alle Werte der LUT annehmen kann.
Die diversen Codestellen mit den
for (uint16_t i = 31; i != 0; i--) { // soft rising slope against key-clicks
OCR1BL = lut[pgm_read_byte_near(ramp[i])];
delayMicroseconds(60);
}
die die Rampe rauf und runter, je nachdem in welcher Richtung die LUT durchlaufen wird,
formen, setzen alle erst viel später an (ca. 1.5ms) nachdem die erste HF am Ant.-Ausgang
erscheint.
Deswegen vermute ich, dass bei der Initialisierung beim Wechsel von RX zu TX der Spike
erzeugt wird und eine andere Ursache hat.
Ist halt etwas lästig jedes mal wieder neu zu Flashen, um die Modifikationen im Code
in ihrer Wirkung am Oszi zu sehen.
Werde weiter mehr den Code durchforsten und hoffe die entsprechende Stelle zu finden.
Du hast die OCX-Variante gepostet, auch mit viertem BS170.
Aber gut, wenn PB0 nicht mit dem Takt CLK2 verriegelt ist, fällt der Portpin als Ursache raus. Der schützt dann tatsächlich nur den Empfängereingang.
Bleibe aber dabei, mindestens 0,5ms vor dem Umschalten auf TX muss PB2 / OCR1BL auf 0 sein. Das passiert offensichtlich nicht. Die Umschaltung auf TX scheint ab Zeile 4924 implementiert. RX ist PB0. si5351.SendRegister(SI_CLK_OE, TX1RX0) schaltet den Takt ein.
Arduino ist wegen fehlender Tracemöglichkeit bei größeren Sachen äußerst nervig, ist mir schleierhaft warum die Entwickler so einen zeitkritischen Code darin umgesetzt haben.
1
if(tx_enable)
2
{
3
// TX
4
5
if(practice){
6
fastdigitalWrite(RX,LOW);// TX (disable RX)
7
lcd.setCursor(15,1);lcd.print('P');
8
si5351.SendRegister(SI_CLK_OE,TX0RX0);// Do not enable PWM (KEY_OUT), do not enable CLK2 - DISABLE CLK2 which is the TX PA gate clock
9
}
10
else
11
{
12
fastdigitalWrite(RX,LOW);// TX (disable RX)
13
14
// GW8RDI Note: Enable TX before setting PLL frequency?????? todo revise
15
#ifdef NTX
16
fastdigitalWrite(NTX,LOW);// TX (enable TX)
17
#endif //NTX
18
#ifdef PTX
19
fastdigitalWrite(PTX,HIGH);// TX (enable TX)
20
#endif //PTX
21
22
lcd.setCursor(15,1);lcd.print('T');// Show Transmitting on LCD
ich habe den Eindruck, dass der SI_CLK_OE zu einem etwas späteren Zeitpunkt
gesetzt werden müsste und nicht gleich mit der Programmierung des Si5351.
Ist aber nur so ein grobes Gefühl, ohne es genau begründen zu können.
Dazu muss ich mir erst einmal die I2C Sendroutine ansehen, die die PLL mit
Werten befüllt.
Es werden zwei der drei PLL Clock-Takte für den RX-Tayloe verwendet und ein
Clock für den TX. Diese werden durch die Konstanten TX1RX0, TX0RX1, TX0RX0
und TX1RX1 entsprechend aktiviert bzw. deaktiviert, wobei mir die letzte
Konstante etwas unklar ist.
Ab Code-Pos. 518 ...
1
#ifdef TX_CLK0_CLK1
2
#ifdef F_CLK2
3
#define TX1RX0 0b11111000 // 248 (10) F8 (hex)
4
#define TX1RX1 0b11111000
5
#define TX0RX1 0b11111000
6
#define TX0RX0 0b11111011 // 251 (10) FB (hex)
7
#else //!F_CLK2
8
#define TX1RX0 0b11111100 // 252 (10) FC (hex)
9
#define TX1RX1 0b11111100
10
#define TX0RX1 0b11111100
11
#define TX0RX0 0b11111111 // 255 (10) FF (hex)
12
#endif //F_CLK2
13
#else //!TX_CLK0_CLK1
14
#define TX1RX0 0b11111011 // 251 (10) FB (hex)
15
#define TX1RX1 0b11111000 // 248 (10) F8 (hex)
16
#define TX0RX1 0b11111100 // 252 (10) FC (hex)
17
#define TX0RX0 0b11111111 // 255 (10) FF (hex)
18
#endif //TX_CLK0_CLK1
Werde also noch etwas experimentieren müssen, sofern
nicht jemand schon eine genaue Vorstellung hat, wo das
Problem liegt.
Hier würde ich zunächst zwischen dem CW-Shaping im AVR-Code und dem Einschaltverhalten des Si5351 unterscheiden. Wenn der Spike bereits vor dem eigentlichen Ramp-Code auftritt, wird eine Änderung an ramp[] vermutlich wenig bringen. Interessant wäre deshalb, an welcher Stelle dsp_tx_cw() den Si5351 aktiviert bzw. dessen Output einschaltet. Wenn du die Oszilloskop-Aufnahme und die .ino-Datei hier hochlädst, kann man die zeitliche Abfolge anhand des Codes genauer nachvollziehen und gezielt nach der Si5351-Initialisierung bzw. dem Output Enable suchen.
danke für den Hinweis. Das war bereits mein Gedanke, siehe weiter oben im Thread.
Den Code habe ich bereits als zip Datei hochgeladen, erstes Posting.
Ich habe noch einen .cpp Code nun hinzugefügt, bei dem Versuch nur den PP (Präprocessor)
Lauf des Compilers zu ermitteln um die ganzen #defines aufzulösen.
Darin sieht man auch die ganzen Funktions-Prototypen am Anfang des Listngs.
Muss an der richtigen Stelle aufgerufen werden, um den CW Träger zu aktivieren bzw. deaktivieren.
Nun muss ich nur die richtige Stelle finden ;-)
Markus
PS.:
So wird der Si5351-Takt via SI_CLK_OE=3 und TX0RX0=0b11111111 und si5351.SendRegister ein- bzw. ausgeschaltet.
if (tx == 1) { OCR1BL = 0; si5351.SendRegister(SI_CLK_OE, TX0RX0); } // disable carrier
bzw.
if (tx == 255) { si5351.SendRegister(SI_CLK_OE, TX1RX0); } // enable carrier TX1RX0=0b11111000
Wobei es noch andere TX0RX0 und TX1RX0 Konstanten ja nah #define gibt - da muss ich mich noch bei der
Si5351 Dokumentation einlesen. Siehe Posting #8093175
PS2.:
Ab Zeile 3036-3052 der .ino.cpp. Datei habe ich schon meine Versuche der Modifikation (//MW) Kommentar
eingebaut. War aber bis jetzt noch nicht erfolgreich.
Da habe ich mich noch nur auf die u.g. Funktion konzentriert.
void dsp_tx_cw()
Die verschiedenen Konstanten hinter SI_CLK_OE berücksichtigen, wenn ich es richtig verstanden habe, auch die verschiedenen Hardware-Varianten. Nicht alle nutzen CLK0 & CLK1 für den Mischer und CLK2 für den Sender.
Ich würde nicht in die SI5351-Routinen eingreifen. Sondern eher PB2 bzw. das damit verbundene OCR zurücksetzen. Vermute, dass man schon einen Teilerfolg erzielt, wenn man das zeitgleich zum Setzen von TX1RX0 (Sendetakt ein) einfügt. Aber eigentlich muss es ein paar hundert µs vorher passieren.
Dazu müsste man den zeitlichen Ablauf des Codes verstehen.
Vielleicht die Stelle finden, wo der Sendeknopf entprellt wird.
Nach dem genaueren Betrachten der usDX+ Platine ist mir
aufgefallen, dass der verbaute Si5351(B) in der MOSP10
Variante gar bein OEB-Pin herausgeführt hat.
D.h. wohl, das das Enabeln des Outputs der drei Clocks
nur via I2C passiert.
Damit wäre die Reihenfolge des Register-Beschreibens aus-
schlaggebend, wann der Clock am Output sichtbar wird.
Nach dem genaueren Betrachten der usDX+ Platine ist mir
aufgefallen, dass der verbaute Si5351(B) in der MOSP10
Variante gar kein OEB-Pin herausgeführt hat.
D.h. wohl, das das Enabeln des Outputs der drei Clocks
nur via I2C passiert.
Damit wäre die Reihenfolge des Register-Beschreibens aus-
schlaggebend, wann der Clock am Output sichtbar wird.
Markus
PS.: Warum können jetzt im Forum keine .jpg Anhänge mehr platziert werden?
So viel Angst vor den Sicherheitsrisiken beim Bildaufbau?
Beim ersten Posting gab es da keine Probleme. Ist das eine neue Policy
oder ist gerade nur irgendetwas nicht am Funktionieren?
Genau, nur dachte ich, dass man damit zwar den Takt frei gibt aber trotzdem
zwecks Synchronisation ein OE-Pin hat, wie bei den großeren Gehäusen, siehe DB.
In der AN619 zum Si5351 ist das Folgende zum OE zu finden.
Damit stellt sich bei mir die Frage, ohne richtig den .ino Code bis jetzt verstanden zu haben,
ob die OE Sequenz via I2C gleich nach dem Programmieren der PLL Freq. Register erfolgt, oder
wirklich erst gewartet wird, bis das HF Signal erscheinen soll.
Ich möchte mir jetzt an dem CW-Keyer einen Triggerpunkt setzen um am Oszi zu sehen, nach welchen
Zeitraum tatsächlich die HF am Ant.-Ausgang ansteht.
D.h. ein Kanal am PB4 und ein Kanal am Gate-Ausgang von dem Gatter von CLK2 (TX-Clock), damit ich
ein Gefühl dafür bekomme, wie viel ms tatsächlich nach einem CW-Tastendruck vergehen, bis die HF
erscheint.
Dadurch hoffe ich besser den Code zu verstehen und eher zu erkennen, an welcher Stelle was vor sich
geht.
die Bilder wurden mit einem SP gemacht, so wie immer.
Die Größe beträgt im jpg Format so um die 4-8MB (4608 × 3456 Pixel).
Diese Bilder werden dann via Gimp 3.x auf jeweils 50% der Kantenlänge
reduziert, d.h. auf ein Viertel der orig. Größe und dann ins
Forum hochgeladen. So mache ich das schon immer.
Es ist mir halt aufgefallen, dass er das jpg Format beim letztem Posting
nicht annehmen wollte (drei Bilder), weshalb ich sie nach gif konvertiert
habe. Kann aber nicht ausschließen, dass bei der jpg Erzeugung via Gimp
was schief gelaufen ist.
Werde es ja beim nächsten Versuch ja sehen. War nur etwas perplex, als es
vorhin moniert wurde. Habe mir aber da noch keine Gedanken dazu gemacht,
sondern nur das andere Bildformat gewählt, da ich den Beitrag posten wollte.
Die haben eine bessere Auflösung uns sogar Nachtsichtfähigkeit.
Bei meinem SP handelt es sich um ein simples Smart Phone.
Der Begriff SP ist durchaus geläufig.
Damit stellt sich bei mir die Frage, ohne richtig den .ino Code bis
jetzt verstanden zu haben,
ob die OE Sequenz via I2C gleich nach dem Programmieren der PLL Freq.
Register erfolgt, oder
wirklich erst gewartet wird, bis das HF Signal erscheinen soll.
Ist doch für dein Ziel egal, in welchem zeitlichen Abstand PLL gesetzt und OE gegeben wird. Du willst die Amplitude sanft hochfahren und dazu trägt der SI5351 nichts bei. Der schaltet immer hart ein und aus.
Die Rampe macht einzig der PB2 mit dem nachgeschaltetem Integrationsglied. Das OCR der PWM wird über eine LUT gefüttert, die nur die Aufgabe der Linearisierung hat. Die Leistungssteuerung der PA über das Gate-Bias ist natürlich alles andere als linear.
Ich fand im Code noch eine TX-Verzögerungsfunktion. Weiß nicht ob die aktiv ist, ist von Compilerschaltern eingerahmt. Siehe Zeile 4851 - 4864. Der Wert heißt txdelay und ist im Code auf 0 gesetzt. Zeile 4820.
Vielleicht kannst du was ausrichten, wenn du da ein paar 100 µs spendierst.
Habe nun die Testpunkte ermittelt und konnte ohne Löten daran messen.
Punkt und Strich Kontakt sind auf den ICP-Stecker geführt und das BS170
FET Gate Signal ist an einem unbesetzten Lötpad abgreifbar, siehe die ersten
beiden Anhänge.
Nachdem das ermittelt war (mittels DVM und Durchgangsprüfer-Mode mit Ton)
konnte ich die este Messung vornehmen.
Zeitspanne und Signal-Form des Key-Down und der HF am Ant. Ausgang.
Siehe Anhang. Sind knapp 1,5ms, wobei ein Spike auf der CW-Key Leitung,
entweder durch Prellen oder einen anderen Effekt zu dem HF-Spike vor der
CW Start Rampe führt.
Nun muss die entsprechende Stelle im Code gefunden werden, um das Übel
abzustellen.
Da Arduino kein Echtzeit-Trace oder Breakpoints unterstützt, ist das nicht ganz so einfach. Mit dem im Betrieb ungenutzten PB3 am ISP-Stecker könnte man im Code kurze Flankenwechsel einfügen und auf einen Kanal des Oszi legen. Dann siehst du ob die Stelle zeitlich passt. Etwa so:
1
fastdigitalWrite(PB3,LOW);
2
fastdigitalWrite(PB3,HIGH);
3
fastdigitalWrite(PB3,LOW);
Ein Kandidat wäre Zeile 4861. Oder gleich mal txdelay = 1 in Zeile 4822 ausprobieren.
Die Stelle macht nur Sinn, wenn die in Abhängigkeit der zahlreichen Compilerschalter auch durchlaufen wird. Siehst du in der Arduino-IDE.
Deshalb habe ich die .ino.cpp weiter oben drangehängt.
Das müsste der Output des Compilers sein, bei dem nur
der PP (PräProcessor) durchlaufen wird, wenn ich es
richtig interpretiert habe.
Ich werde mir die von Dir genannten Stellen mal genauer
ansehen und die Write-Toggel mal ausprobieren.
Diese befindet sich in der Funktion 'void start_rx() // Start radio receiver' aus Zeile 4802?
Müsste es nicht eine start_tx Funktion sein?
Sehe gerade es gibt eine 'void switch_rxtx(uint8_t tx_enable)' Funktion ab Zeile 4833.
Ich habe mal fastdigitalWrite(PB3, LOW/High/LOW); vor und nach Zeile 4861 in den Code eingefügt.
Werde gleich mit dem DSO schauen, wie da der Zeitliche Zusammenhang ist.
Habe nun das Ergebnis, siehe Anhang.
Erstes Bild - die Flanke vom PB3 und das Auftauchen der HF am Ant. Ausgang.
Bild zwei zeigt zwei CW-Punkte (20wpm) mit PB3 vers HF.
Was ich nicht ganz verstehe, ist der Umstand das PB3 nicht zwei kurze Inpulse
Macht, sondern bis Zum Ende der Aussendung eines Punktes auf High-Pegel bleibt.
Deshalb habe ich die .ino.cpp weiter oben drangehängt.
Das müsste der Output des Compilers sein, bei dem nur
der PP (PräProcessor) durchlaufen wird,
Nein, mit Sicherheit nicht. Hab zwar auch keine Ahnung von Arduino, aber soweit ich weiß, ist die ino.cpp die Haupt-Quelldatei. Darin gibts immer zwei zu befüllende Methoden, setup() und loop(). Das Ganze nennen die Sketch.
Der Präprozessor läuft anschließend, der interpretiert natürlich die #define wie jeder andere Präprozessor auch, ergänzt aber noch unsichtbar includes auf die Arduino-Libraries.
Ein gcc nimmt den Code deshalb ohne diese Ergänzungen nicht. Aber in deiner Arduino-IDE siehst du ganz schnell, ob der Code ausgegraut ist oder nicht.
Was ich nicht ganz verstehe, ist der Umstand das PB3 nicht zwei kurze
Inpulse
Macht, sondern bis Zum Ende der Aussendung eines Punktes auf High-Pegel
bleibt.
Wirklich seltsam. Jetzt wären Arduino-Kenntnisse nützlich. Vielleicht darf man die Ports nicht so schnell ein- und ausknipsen. In C oder Assembler wäre das ok.
Komisch ist auch die um 1/2 Volt überschießende Spannung.
Aber ich glaube die Stelle ist gut. Füge doch mal OCR1BL = 0; ein.
Edit: jetzt sehe ich das korrekte zweite Bild, warum auch immer. PB3 sieht sehr merkwürdig aus. Steht der Kanal auf AC? Würde aber auch nicht alles erklären.
Habe doch geschrieben, dass wir das fastdigitalWrite falsch benutzen. Als erster Parameter muss die sog. Arduino Pin Number verwendet werden. PB3 hat die 11. Also
1
digitalWrite(11,LOW);
2
digitalWrite(11,HIGH);
Zuvor muss der Pin zumindest einmal konfiguriert werden. Das macht man in Arduino vermutlich so:
1
fastpinMode(11,OUTPUT);
Das musst du oben in der Initialisierung des Controllers unterbringen. Dann werden die Pulse hoffentlich wie vermutet aussehen.
nun haben wir zwei Toggel-Punkte am DSO.
Der Erste innerhalb der "switch_rxtx(uint8_t tx_enable)" Funktion
und der zweite im Bereich der "Switch(mode)" CASE Anweisung bei dem
der dsp_tx_cw Funktions-Pointer an func_ptr übergeben wird, der wohl
innerhalb einer Interrupt-Routine angesprungen wird.
Diesen Toggel sehen wir unmittelbar vor dem Auftauchen der HF an der
Antenne, siehe Anhang.
Der von mir geänderte txdelay Wert von 0 auf 10 liefert die ca 8.5ms
Verzögerung bevor die HF startet. Erst danach kommt die Rampe, ebenfalls
mit einer etwas kleineren Verzögerung von 1.5ms.
Hallo Markus, bitte den gelben Oszi-Kanal auf DC schalten. Den blauen auch gleich. Dann sehen die Signale nicht so merkwürdig aus, irritiert mich irgendwie :-)
txdelay auf 1 hätte auch gereicht, vielleicht gehts auch mit semi_qsk_timeout und txdelay = 0, wenn man sich das Timing genau anschaut. Kann man später mal probieren.
Der grobe Ablauf sieht für mich in etwa so aus:
in void switch_rxtx(uint8_t tx_enable){...} wird die Umschaltung von RX auf TX (und umgekehrt) vorbereitet. Hoffentlich (!) wird die nur einmal pro Tastendruck / loslassen durchlaufen.
in der oben genannten Funktion wird der von dir angesprochene Funktionspointer func_ptr = dsp_tx_cw; gesetzt.
void dsp_tx_cw() wird zyklisch im TIMER2_COMPA_vect - Interrupt angestoßen.
Soweit so gut, aber OCR1BL = 0; muss ohne Schaden funktionieren, und zwar an der Stelle wo die jetzt funktionierenden PB3-Flankenwechsel eingefügt sind.
Wenn das nicht funktioniert hieße das, dass der Interrupt nicht kommt. Oder lut[255]=0 ist.
Man könnte natürlich in der Interruptroutine auch Pins toggeln, um das abzusichern. Aber eigentlich kann das nicht sein.
das mit der AC am CH1 habe ich auch mittlerweile bemerkt.
Das war der erste Kanal, mit dem ich am Anfang die HF gemessen habe.
Nun da er auf DC steht, sind die Abklingeffekte an den Flanken
nicht mehr vorhanden.
Ich werde für einige Tage ab Morgen offline sein, da auf Reisen,
melde mich aber wieder ab kommendem Mittwoch.
LG und bis dann.
Danke für die Unterstützung bei dem Problem mit dem uSDX+