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.