Eigenbau Fernsteuerung mit HF-Modul Frsky XJT: Anbindung Empfänger X8R/S8R

Hi @Wolfi , @netti57
nein, leider alles unverändert. Ich konnte das Problem bisher nicht weiter einkreisen. Ich bin mir definitiv sicher, dass das Signal korrekt erzeugt wird und konsistent zum Sendemodul gelangt. Ich werde es nochmal mit einem neuen Sendemodul ausprobieren, bin allerdings etwas ratlos.
Ich habe auch den Abstand beim Binden variiert und habe es in unterschiedlichen Bereichen ausprobiert, u.a. auch den Bereich 1-2m abgedeckt.
 
Du solltest den Tipp aus #17 aufgreifen und dir jemanden mit einem FrSky-Sender oder Radiomaster und co suchen . Dann ist in 2 Minuten getestet ob Dein Sendemodul und/oder Empfänger funktioniert
 
Du solltest den Tipp aus #17 aufgreifen und dir jemanden mit einem FrSky-Sender oder Radiomaster und co suchen . Dann ist in 2 Minuten getestet ob Dein Sendemodul und/oder Empfänger funktioniert
Ja, den Punkt habe ich nicht vergessen. Ich habe bisher leider noch niemanden mit FrSky-Equipment getroffen. Die meisten bei mir fliegen mit Graupner oder Multiplex...
 

Wolfi

User
Das einzige was mir noch einfällt ist Sendemodul und Empfänger nochmal updaten, auch wenn du das schon gemacht hast. Vielleicht ist ja dabei was schief gegangen.
 

PeGru

User
Du solltest den Tipp aus #17 aufgreifen und dir jemanden mit einem FrSky-Sender oder Radiomaster und co suchen . Dann ist in 2 Minuten getestet ob Dein Sendemodul und/oder Empfänger funktioniert

oder einen nachweislich funktionierenden Sketch aufspielen.
Zum Beispiel von hier: https://mode-zero.uk/viewforum.php?f=27

oder Vorschlag von Bernd.

Wenn das so funktioniert, dann ist klar, wo der Hund begraben ist.

Peter
 
Ja, den Punkt habe ich nicht vergessen. Ich habe bisher leider noch niemanden mit FrSky-Equipment getroffen. Die meisten bei mir fliegen mit Graupner oder Multiplex...
Du bist doch bei EngelMT im Frsky Forum angemeldet.
Nimmt die Suchfunktion: Suche über Postleitzahl.
Dort findest du jemanden, der die gleiche Postleitzahl hat. (Herrmann R... hat Anlagen mit JR-Schacht)
Den kannst du ja mal kontaktieren (z.B. über PN im Forum).
Grüße netti57
 
Mission accomplished! Ich konnte das Problem (bzw. die Probleme) nun endlich lösen, vielen Dank euch für die zahlreichen Tipps und Hilfen.

Das ursächliche Problem lag am HF-Modul, dies hatte tatsächlich einen Schuss abbekommen und hat nicht mehr richtig gesendet (vielleicht war ich zu Beginn mal bei den Kontakten doch etwas unvorsichtiger als gedacht). Da ich zuerst den S8R-Empfänger verwendet hatte und diesen ohne den Stabilisierungsmodi nicht richtig binden konnte, ist währenddessen wohl versehentlich das Modul kaputt gegangen, ohne dass ich es hätte merken können oder es von Anfang an defekt. Somit konnte ich jedenfalls dieses im Folgenden auch nicht mehr mit dem X8R-Empfänger verbinden. Nach vielem Hin- und Herprobieren, unzähligem Flashen blieb mir schlussendlich nur noch die einzige Vermutung, dass das Sendemodul defekt sein müsse.

Ich habe daher nochmal ein neues Sendemodul ausprobiert. Diesmal das XHT statt dem XJT (im Prinzip gleich aber ohne Gehäuse), das passt später auch besser in den Umbau. Dies hatte allerdings auch erst nicht funktioniert, da ich versehentlich beim Anschluss den Signal-Kontakt auf Masse gezogen habe. Naja, wenn es schon nicht läuft, dann halt richtig ;-).

Also insgesamt war es eine zähe Kiste, aber jetzt funktioniert es stabil und ich kann mit dem Umbau weitermachen. Ich habe nochmal ein wenig an den Arduino-Code geschraubt, aber im Grundprinzip ist er so wie vorher. Wesentlicher Unterschied ist, dass ich dank dem Tipp von @Wolfi das Schreiben ins PPM-Array in einen Atomic-Block gesetzt habe, um den Zugriff aus der ISR abzusichern. Ich glaube allerdings, dass die Auswirkung ohne Atomic-Block nicht kritisch war, da die ISR nur liest und keine Veränderung an dem Array vornimmt und daher ein mutual exclusive Zugriff nicht nötig ist. Entweder würde dann der alte oder der neue Wert im PPM-Array stehen. (Ob man nun eine for-Schleife in einen Atomic-Block packen sollte, darüber lässt sich streiten, allerdings wären die permanenten Kontext-Switchen beim Funktionsaufruf innerhalb der Schleife auch sehr Prozessorlast-intensiv, die ich dafür vermeide. Wohl einfach Geschmackssache...).

Hier noch ein Bild vom finalen Aufbau:

PXL_20230522_182716832.jpg


Und dass sich der Servo tatsächlich bewegt, kann man hier sehen 🥳:

PXL_20230522_182648210.jpg
PXL_20230522_182650780.jpg


Falls jemand an dem letzten Stand vom Code interessiert ist, den habe ich beigefügt.
 

Anhänge

  • Tests_PPM.ino.txt
    9 KB · Aufrufe: 49

Wolfi

User
Schön dass es funktioniert. 👍

Ich muss Dir nur widersprechen was die Aussage betrifft dass man keinen exklusiven Zugriff braucht wenn in der ISR nicht geschrieben wird.

Das Problem ist daß das ppm Array ein int Array ist, und daher immer 2 load/store opcodes zum Ändern eines Wertes gebraucht werden.
Die Werte sind ja Microsekunden und sollten zwischen 1000 und 2000 sein.

Die ISR kann auch zwischen den beiden store opcodes zuschlagen. Dann kriegst du das H Byte vom neuen Wert und das L Byte vom alten Wert weil das H Byte vor dem L Byte geschrieben wird.

Beispiel:
alter Wert 1040 uSec (H = 4, L = 16)
neuer Wert 1020 usec (H = 3, L = 252)

Dann wird H=3, L=16 gelesen was 256*3+16 = 784 uSec ergibt.

Kann sein dass es deinen Code nie trifft, weil es sich vom timing her nicht ergibt.
Aber wenn Du in 2 Jahren mal was änderst und plötzlich zuckt ein Servo alle 10 Minuten mal, dann viel Spaß beim Fehler suchen.

Nicht dass ich nicht auch schon mal so einen Bock geschossen hätte 😇


Edit: typo korrigiert
 

Wolfi

User
(Ob man nun eine for-Schleife in einen Atomic-Block packen sollte, darüber lässt sich streiten, allerdings wären die permanenten Kontext-Switchen beim Funktionsaufruf innerhalb der Schleife auch sehr Prozessorlast-intensiv, die ich dafür vermeide. Wohl einfach Geschmackssache...).

Ja, da bin ich bei Dir. Atomic Blocks so kurz wie möglich weil die ja die ISR blockieren und dein Timing der ISR beeinflussen.
Daher wenn du ATOMIC_RESTORESTATE nicht brauchst weil sicher ist dass interrupts immer eingeschalten sind dann lieber ATOMIC_FORCEON
(ergibt nur ein cli / sei ) und den atomic block in die Schleife ziehen und auch die Berechnung aus dem Atomic Block raus halten.
 
Schön dass es funktioniert. 👍

Ich muss Dir nur widersprechen was die Aussage betrifft dass man keinen exklusiven Zugriff braucht wenn in der ISR nicht geschrieben wird.

Das Problem ist daß das ppm Array ein int Array ist, und daher immer 2 load/store opcodes zum Ändern eines Wertes gebraucht werden.
Die Werte sind ja Microsekunden und sollten zwischen 1000 und 2000 sein.

Die ISR kann auch zwischen den beiden store opcodes zuschlagen. Dann kriegst du das H Byte vom neuen Wert und das L Byte vom alten Wert weil das H Byte vor dem L Byte geschrieben wird.

Beispiel:
alter Wert 1040 uSec (H = 4, L = 16)
neuer Wert 1020 usec (H = 3, L = 252)

Dann wird H=3, L=16 gelesen was 256*3+16 = 784 uSec ergibt.

Kann sein dass es deinen Code nie trifft, weil es sich vom timing her nicht ergibt.
Aber wenn Du in 2 Jahren mal was änderst und plötzlich zuckt ein Servo alle 10 Minuten mal, dann viel Spaß beim Fehler suchen.

Nicht dass ich nicht auch schon mal so einen Bock geschossen hätte 😇


Edit: typo korrigiert
Ah, prima, danke für die Erklärung. Das erklärt es dann. Die Verwendung der "constrain"-Funktion macht es dann natürlich auch nicht besser ;-). Also am besten alles vorab berechnen und dann in einem Atomic-Block innerhalb der for-Schleife ins Array schreiben.
 

mha1

User
besser alles vorab berechnen und dann wenn dein Array steht alles in einen Buffer kopieren, den die ISR nutzt. Damit hat die ISR immer einen konsistenten Datensatz und Du kannst Dir mit der Rechnerei im Vordergrund Zeit lassen. So ungefähr:
C:
#define NCHANNELS 8

typedef uint16_t ppmIntArray_t[NCHANNELS];

setup() {
  ...
}

static ppmIntArray_t ppmIntArrayISR = { 1500 };

loop() {
  ppmIntArray_t ppmIntArrayWorking;
  ...
  // ppmIntArrayWorking befüllen 
 ...
 ppmIntArrayWorking[2] = 4711* yadayada*
 ...

 // jetzt ist ein konsistenter Datensatz da, update des ISR buffers
 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
   memcpy((void *)ppmIntArrayISR, (void *)ppmIntArrayWorking, sizeof(ppmIntArray_t));
  }
  ...
}

ISR(trigger) {
  // ISR arbeitet nur mit ppmIntArrayISR
  ...
  uint16t channel3 = ppmIntArrayISR[2];
  ...
}
 
besser alles vorab berechnen und dann wenn dein Array steht alles in einen Buffer kopieren, den die ISR nutzt. Damit hat die ISR immer einen konsistenten Datensatz und Du kannst Dir mit der Rechnerei im Vordergrund Zeit lassen. So ungefähr:
C:
#define NCHANNELS 8

typedef uint16_t ppmIntArray_t[NCHANNELS];

setup() {
  ...
}

static ppmIntArray_t ppmIntArrayISR = { 1500 };

loop() {
  ppmIntArray_t ppmIntArrayWorking;
  ...
  // ppmIntArrayWorking befüllen
 ...
 ppmIntArrayWorking[2] = 4711* yadayada*
 ...

 // jetzt ist ein konsistenter Datensatz da, update des ISR buffers
 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
   memcpy((void *)ppmIntArrayISR, (void *)ppmIntArrayWorking, sizeof(ppmIntArray_t));
  }
  ...
}

ISR(trigger) {
  // ISR arbeitet nur mit ppmIntArrayISR
  ...
  uint16t channel3 = ppmIntArrayISR[2];
  ...
}
Super, danke für den Tipp!
 
Ich habe mittlerweile den Hardware-Aufbau auf Basis zweier Arduinos abgeschlossen. Die Elektronik funktioniert soweit, alle Schalter und Potis können ausgelesen werden. Das HF-Modul ist ebenfalls erfolgreich angebunden. Die weitere Implementierung und Fortschritte dokumentiere und speichere ich auf GitHub:
Aktuell besteht das Repo nur aus der Dokumentierung der Elektronik unter:
RadioControl/doc/hardware
 
Ansicht hell / dunkel umschalten
Oben Unten