Jump to content
Schiffsmodell.net

Multiswitch für Taranis mit Arduino


Meinolf Höhler

Recommended Posts

Meinolf Höhler

Für die Taranis Steuerungen mit OpenTX gibt es leider keine Multiswitche, wie z.B. von IMTH für die Graupner Anlagen.

Dafür kann man aber die X9E mit selbst geschriebenen Programmen füttern, und ein Befehl in der API sah verdächtig danach aus, Daten über den Telemetriekanal vom Sender zum Empfänger zu schicken: sportTelemetryPush()

Wenn FrSky-Empfänger oder Sensoren darüber Daten empfangen können, müsste es doch auch gehen, dass man einen Sensor mit einem Arduino ähnlichen Gefährt soweit zu emulieren, dass man das Signal darüber zweckentfremdet und für die eigenen Dienste nutzen kann.

Eine Internetrecherche ergab, dass ich nicht der Einzige mit dem Vorhaben war, und es schon eine Bibliothek gibt, mit der man einen „beliebigen“ Sensor darstellen kann (https://www.rcgroups.com/forums/showthread.php?2245978-FrSky-S-Port-telemetry-library-easy-to-use-and-configurable ). Von der werden also die weiteren Bemühungen ausgehen.

FrSkyMultiswitch.zip

MtSw.zip

Link to post
Meinolf Höhler

Die Bibliothek funktioniert entweder mit einem Arduino kompatiblen Teensy 3.0/LC, ESP8266, oder einem Board mit ATmega328P. Der Letztere ist für mich erst einmal die interessante Variante, da ich davon ein paar zu Hause rumfliegen habe.
Die Idee war dann zuerst, alles auf einen anderen Microcontroller zu portieren, nämlich den ATMEL SAMD21. Mehr Speicher, mehr Leistung? Warum nicht, kann doch nicht all zu schwer sein.
Leider dann doch, weil eine wichtige Information erst durch tieferes graben ans Licht kam.

Man braucht einen Chip, der die folgenden Eigenschaften erfüllen sollte:
- der UART muss im Halbduplex laufen können
- der Chip muss idealerweise mit einem invertieren UART-Signal sofort zurecht kommen

Laut Datenblättern kann man die UART des SAMD21 zwar in den Halbduplex-Modus umschalten, aber dazu muss man einiges in den Kernkomponenten der Arduino IDE umschreiben.
Der zweite Punkt ist mit dem SAMD21 gar nicht zu machen, ohne zusätzlich eine Schaltung zwischen Empfänger und Microcontroller zu setzen.

Pläne sind dazu da, um sie zu ändern, also zurück zum ursprünglichen Plan, zu einem Board mit dem 328P, was auf 3,3V läuft.

Ausgewählt habe ich für das Sensorreplikat von Adafruit den Pro Trinket 3V ( https://www.adafruit.com/product/2010 ). Der läuft mit 12 MHz Takt ausreichend schnell, hat allerdings den Nachteil, dass ein paar KB des Speichers von einem Bootloader belegt sind, der auch die Kommunikation über USB regelt. Dafür ist die Bauform schön kompakt.

Es soll ja was geschaltet werden, vorzugsweise LED. Da der ProTrinket nur relativ wenige Ausgänge besitzt, muss eine andere Lösung her, wie man externe Geräte schaltet. Da das meiste LEDs sein werden, nehme ich ebenfalls von Adafruit einen, bzw mehrere 16 Kanal-PWM Module mit dem PCA9685 ( https://www.adafruit.com/product/815 ). Dieser Chip wird über I2C-Bus angesteuert und behält den Befehl für einen Ausgang so lange bei, bis ein neuer Befehl kommt, oder der Strom abgeschaltet wird. Das charmante an dem Board ist die eingebaute Konstantstromquelle, die Ideal für die LED ist. Außerdem kann man einen Kanal von ganz aus bis ganz an in 4096 Stufen sagen, wie hell man die LED haben will. Damit wird nachher die Beleuchtung so eingestellt, dass sie einigermaßen realistisch aussieht, und nicht die Positionslaternen mit der Helligkeit eines Suchscheinwerfers leuchten.

Den „Sensor“ haben wir, einen Baustein, der was schaltet haben wir, der Empfänger, der den S.Port abgibt ist ein X6R, 6 Kanal PWM + 16 Kanal SBUS mit Telemetrie.

Um den ganzen Kram mit Strom zu versorgen, brauchen wir noch ein paar Dinge. Der ProTrinket kann 16V DC ab, weil der einen eigenen Spannungsregler eingebaut hat. Da der Regler aber nur 150mA extern liefern kann, werden die PWM Module mit einer eigenen 3,3V Versorgung bedacht. Dafür verwende ich einen einfachen StepDown Regler von Pololu.

Im Modell wird der Empfänger über das BEC des Fahrmotors versorgt. Da der Testaufbau eh an einem Labornetzteil hängt, will ich mir da den Aufwand erst einmal sparen und verwende ein 5V BEC, was direkt im Empfänger eingesteckt ist. Alle Spannungsquellen sind über eine gemeinsame Leitung von - und GND zusammengeschaltet.

Die Schaltung ist damit fast komplett. Weil der ProTrinket über die USB Schnittstelle keine Debugausgabe, wie die anderen Arduinos, bereitstellen kann, muss ich das anders machen. Da ich noch von Adafruit ein OLED-Display habe, was ebenfalls über I2C angesteuert wird, hänge ich das auch noch an den Bus dran und gebe mir bestimmte Daten darüber aus.

  • Like 1
Link to post
Meinolf Höhler

Die Schaltung sieht also so aus: X6R (S.Port) <-> ProTrinket Pin 4 /// I2C (Pin A4 und A5) <-> PWM Module 1&2 <-> OLED-Display

Dann geht es ans Programmieren, zuerst der Sender, weil der am einfachsten geht.
In die X9E wird ein Funktions-Script geschrieben. Ein Funktions-Script, weil Zugriff auf das Display erst einmal nicht nötig ist. Es soll „nur“ die Stellung der Schalter zum Empfänger geschickt werden.
 

Apropos, was wird eigentlich übertragen? Wieviel und wie?

Das Protokoll ist für uns nicht direkt interessant. Wir müssen nur wissen, wie die übertragenen Daten aussehen.
Insgesamt werden 10 Byte übertragen. Byte 1 ist eine Art Startsignal, und ist immer 0x7E. Byte 2 ist die Zieladresse, in diesem Fall 0x0D. Byte 3 und 4 sind für uns uninteressante Daten, die bleiben auf 0x10 und 0x01 stehen. In Byte 5-8 steht der übertragene Wert, und Byte 9-10 sind Prüfsummen.

Es stehen also 4 Byte/32 Bit zur Verfügung, in denen etwas sinnvolles übertragen werden kann.

32Bit = 32 Schalter bzw Schaltstellungen? Das ist mal eine Hausnummer, und die können theoretisch vollständig verwendet werden, da die X9E maximal 18 Schalter mit drei Positionen verarbeiten kann.

3 x 18 ist 54?

Mathematisch ja, schaltungstechnisch nein, denn die AUS-Stellung aller Schalter, wie auch immer man die festlegt, wird durch die 0 übertragen. Das wird nachher aus der Logik etwas klarer werden.

Meine X9E hat nur 6 3-Stellungsschalter eingebaut, was aber erst einmal völlig ausreichend ist.

Ich lege für mich selber fest, dass die Mittelstellung der Schalter AUS oder 0 bedeutet, und jeweils „nach oben“ (+) oder „nach unten“ (-) einer EIN-Stellung ist.
Jedem der Schalter wird nun eines der 32 Bit zugeordnet.
Schalter SA bekommt im niederwertigsten Byte das Bit 1 und 2, SB Bit 3 und 4, SC Bit 5 und 6 etc etc.
Ist Schalter 1 > 10 (SA+) wird Bit 1 auf 1 gesetzt, indem zu dem zu sendenden Wert 1 hinzuaddiert wird. Ist SA < 10 (SA-), wird dem Wert 2 hinzuaddiert. Bei SB sind es 4 und 8 etc etc.
Ist ein Schalter 0, also weder + noch - wird nichts unternommen. Soweit zur Theorie, im Code sieht das dann so aus:

Der zu übertragende Wert wird mit 0 überschrieben

channelValue = 0

Schalter SA wird auf + abgefragt

 

if (getValue('sa') > 10) then

Wenn SA+ ist, addiere 1 zur Variablen

channelValue = channelValue + 1 --0x01 00
end

Schalter SA wird auf - abgefragt

if (getValue('sa') < -10) then

Wenn SA- ist, addiere 2 zur Variablen

channelValue = channelValue + 2 --0x02 00
end

Gleiches dann für SB mit den Additionen von 4 und 8

if (getValue('sb') > 10) then
channelValue = channelValue + 4--0x04 00
end
if (getValue('sb') < -10) then
channelValue = channelValue + 8--0x08 00
end

usw für alle Schalter, die man übertragen will.

Im Anschluss an die Schalterauswertung wird dann mit

sportTelemetryPush(0x0D, 0x10, 0x01, channelValue)

der Wert zum Empfänger geschickt, der das auf dem S.Port weiterleitet.

Um ein paar Schalter zu übertragen, die das Licht schalten, muss das Script nicht ständig so schnell wie möglich die Daten zum Empfänger schicken. Wenn man den Schalter betätigt darf ruhig bis zu einer Sekunde beginnen.
Daher ist die Auswertung in eine Abfrage eingebettet, die prüft, ob seit dem letzten Durchlauf 500ms vergangen sind.

Was steht nun in channelValue drin?

Die Liste zeigt zur Vereinfachung nur die ersten zwei Byte der Variablen, und die zugehörigen Bits.

Wichtig ist zu verstehen, wo die Daten nachher liegen.

Byte 1

Byte2

...

Bit 8

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 8

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

...

SD-

SD+

SC-

SC+

SB-

SB+

SA-

SA+

 

 

 

 

SG-

SG+

SE-

SE+

...

Das minderwertigste Byte wird zuerst gesendet, steht also ganz links, dann folgen Byte 2-4 in aufsteigender Reihenfolge.

Die Bits innerhalb eines Byte stehen von rechts nach links.

  • Like 1
Link to post
Meinolf Höhler

So gehen wir auf die Arduino-Seite.

Wie eingangs geschrieben verwende ich eine Bibliothek von „Pawelsky“ (Link im ersten Post). Die verwende ich aber weitgehend dazu, die Kommunikation zum Empfänger herzustellen.

In der Bibliothek ist in der Klasse FrSkySportTelemetry eine Funktion send(), die das Senden von Daten übernimmt, aber auch den Datenempfang.
Da ich keine Daten senden möchte, sondern nur das, was nach Adresse 0x0D gesendet wird, empfangen, schreibe ich mir eine eigene Klasse, die Teile der send-Funktion verwendet.

Die Klasse habe ich FrSkySportTelemetryReader getauft, und die einzige Funktion ist receive().
Die ersten Anweisungen stammen aus der S.Port-Klasse. Sie prüfen ab, ob der der Serielle Port zum Empfänger „offen“ ist, und überhaupt Daten vorhanden sind. Ist beides der Fall wird ein Byte eingelesen.

uint8_t data= serial.port->read();

In der Datenübertragung vom Empfänger zu den Sensoren ist 0x7E das Startsignal, dass der Empfänger was zu sagen hat.

if (data == FRSKY_TELEMETRY_START_FRAME) {
dataCounter = 0;
available = false;
}

Diese Anweisungen prüfen, ob 0x7E empfangen wurde, was in der Definition FRSKY_TELEMETRY_START_FRAME hinterlegt ist. Ist das Startsignal empfangen, wird ein Zähler zurückgesetzt, und der Marker available auf false gesetzt.

Der Zähler dataCounter und der Marker available hängen mit der zu empfangenden Datenlänge ab.
Es werden insgesamt 10 Byte mit Daten erwartet, in denen dann die 4 Byte Nutzdaten liegen.
Solange ich nicht 10 Bytes in meinem Datenpuffer habe, macht es keinen Sinn, die Daten weiterzugeben.

Daher

available = false;

Die korrekte Anzahl Daten kann ich nur feststellen, wenn ich vom Startsignal aus zähle. Daher wird bei Empfang von 0x7E der Zähler zurückgesetzt.

dataArray[dataCounter] = data;
dataCounter++;

Dieser Teil schreibt die Daten in einen Puffer und zählt den Zähler um 1 hoch.

if ((dataCounter == 10) && (dataArray[1] == 0x0D)) {
	aUiRxValue[0] = dataArray[5];
	aUiRxValue[1] = dataArray[6];
	aUiRxValue[2] = dataArray[7];
	aUiRxValue[3] = dataArray[8];

	available = true;
}

Jetzt geht es an eine erste Auswertung. Wenn 10 Bytes empfangen wurden, und das zweite Byte den Wert 0x0D hat, werden die 4 Byte Nutzdaten in einen Ausgabepuffer geschrieben, und der Marker für verfügbare Daten auf true.

Link to post

Das mit dem Daten Senden wirst du wahrscheinlich doch noch erledigen müssen:

Es werden die Sensoren vom SPort regelmässig angesprochen, die auf ihre Anfrage auch Antworten:

sind also die ID's 2,5,12 Datenmässig vorhanden ist die die Abfragereihenfolge ( nach einigen Durchläufen )

1,2,5,12,2,3,5,12,2,4,5,12,2,5,6,12......

Wenn deine Adresse 14 ( 0D ) also öfter angesprochen werden soll muss diese auch regelmässig ANTWORTEN....

Ralf

 

ps. wie weit bist du mit der Impulsgeschichte für die Momo Sauerland Module

Edited by r41065
Link to post
Meinolf Höhler

Hab gerade einen Dauertest von über einer Stunde laufen und keine Probleme, und da sind in den S.Port ein Liposensor und der Drehzahlsensor mit eingeschleift.
Mit der Adresse muss man wahrscheinlich mehr aufpassen, dass man nicht einen realen Sensor verwendet, sondern einen, der eben nicht im System aktiv ist.

Link to post

Rückmeldung:

Habe das Script für meine X9Lite ( die hat weniger Schalter ) angepasst und beim Arduino Nano die Ausgänge direkt zum Schalten genutzt.

Funktioniert...

 

Danke für die Anregung

Ralf

Link to post
Am 31.8.2019 um 21:35 schrieb Meinolf Höhler:

channelValue = 0

if (getValue('sa') > 10) then

 

 

Hast Du das mal in größerem Rahmen probiert? Man kann (wenn ich mich richtig erinnere) nur 6 Schalter pro Lua Script abfragen. Läuft das noch wenn Du mehrere Scripte parallel fährst um mehr Schalter abzufragen?. Ich hatte den Lösungsansatz aus diesem Grund vor einiger Zeit verworfen und einen anderen Weg (über SBUS) gewählt soetwas zu realisieren.

Link to post
Meinolf Höhler

Leider nicht, aber ist mal eine Idee, die ich die Woche testen kann.

Warum sollte man nur 6 Schalter abfragen können? Der Schalter ist ja auch nur ein Wert von -100 - +100? Da müsste ich nochmal die Handbücher durchsuchen.

Link to post

irgendwo bin ich darüber gestolpert. Vielleicht ist die Grenze mittlerweile auch aufgehoben.

Meine, mittlerweile erprobte und vielfach eingesetzte Lösung, habe ich hier vorgestellt:

http://rc-network.de/forum/showthread.php/679660-SBUS-Switch?p=4538997#post4538997

Funktionsbeschreibung ab Beitrag #5
Die Auswertung der Kanäle kann man narürlich auch mit einem Arduino umsetzen.

Link to post

Hallo Ulf:

der SPort ist Bidirektional, ich habe schon ein 2. GPS und Spannungssensoren am SPort direkt im Sender angeschlossen.

Ich denke ein paar zusätzliche Schalter per MC einzulesen und als "Telemetriewert" zu senden  oder ein Lua Script welches auf dem Display zusätzliche Schalter simuliert sind die nächsten logischen Schritte um einen Multiswitch über diesen Weg zu realisieren....

Vorlagen für Eigenbau SPort Sensoren gibt es ja mittlerweile genug im www.

Ralf

Edited by r41065
Link to post
Meinolf Höhler

So weiter im Tex...Programm.

Das Programm im Arduino ist schwieriger zu erklären, daher versuche ich die wichtigsten Punkte abzudecken. Ich hoffe die Kommentierung des Quelltexts ist ausreichend.

// Sensor definition to initialize telemetry
FrSkySportSensorAss ass(FrSkySportSensor::ID14); //create a sensor

Auch wenn das Programm funktioniert, ohne, dass der Sender in dem Arduino einen Sensor erkennt, muss trotzdem irgend einer der Sensoren instantiiert werden, damit die Telemetriebibliothek compiliert werden kann. Ich habe den Erstbesten genommen, und das ist der AirSpeedSensor ASS.

// configure telemetry serial port
telemetry.begin(FrSkySportSingleWireSerial::SOFT_SERIAL_PIN_4, &ass);

Das Telemetrieobjekt bekommt zwei Parameter übergeben. Der Erste ist der Pin, an dem der S.Port angeschlossen ist. Hier hat sich anscheinend Pin 4 als am besten geeignet (so ist es in dem Beispiel von Pawelsky beschrieben).

Der zweite Parameter ist der „Pseudo-Sensor“, der zu Anfang instantiiert wurde.

if (telemetry.available && ((uiValue[0] != telemetry.aUiRxValue[0])
                        || (uiValue[1] != telemetry.aUiRxValue[1])
                        || (uiValue[2] != telemetry.aUiRxValue[2])
                        || (uiValue[3] != telemetry.aUiRxValue[3]))) {
uiValue[0] = telemetry.aUiRxValue[0];
uiValue[1] = telemetry.aUiRxValue[1];
uiValue[2] = telemetry.aUiRxValue[2];
uiValue[3] = telemetry.aUiRxValue[3];

telemetry.available = false;
bValuesUpdated = true;
}

Weiter oben wurde ja schon das available Flag beschrieben, und das kommt hier nun zu seinem Einsatz.

Nur wenn Daten verfügbar sind, und sich eines der 4 Byte von den vorher empfangenen unterscheidet, genau dann werden die neuen Daten in den eigenen Puffer übernommen, und die Auswertung mit bValuesUpdated = true; freigegeben.

Wichtig für die nachfolgende Auswertung ist nun die Beziehung zwischen den Empfangenen Bytes und den LEDs an den PWM Modulen.

Für diese Beziehung habe ich eine Tabelle in LibreOffice gebaut, wo in den Spalten die 32 möglichen Schaltwerte stehen, und in den Zeilen die 32 Kanäle der PWM Module.

Nebenbei, die LED sind gleichmäßig auf die PWM Module verteilt, damit nicht eines zu viel Last auf einmal hat.

Wichtig ist nun, dass jedes der PWM Module einen Zwischenpuffer in Form eines Array aus 16 Booleanwerten bekommen hat, welcher den Zustand jeder LED speichert.

bool module1onOff[16];
bool module2onOff[16];

Kommt z.B. über den Empfänger das Signal für die Beleuchtung „in Fahrt“ (Byte 1 = 0x01), sollen die folgenden LED eingeschaltet sein:

- Topplicht (Modul 2, Kanal 0)
- Hecklicht (Modul 1, Kanal 0)
- Backbordlaterne (Modul 2, Kanal 2)
- Steuerbord (Modul 1, Kanal 2)

Um zu ermitteln, ob 0x01 in dem Signal des Empfängers vorhanden ist, anders ausgedrückt der gesendete Wert gerade oder ungerade ist, wird die Bitmaske 0x01 (binär 00000001) mit einem bitweisen UND auf den Puffer angewendet. Ist der Wert ungleich 0, ist der gewünschte Schalter an. Für die anderen Schaltzustände ist die Bitmaske entsprechend 0x02, 0x04, 0x08, 0x10 etc.

//fahrt
if ((uiValue[0] & 0x01) != 0) {
  module1onOff[0] = true; //heck
  module1onOff[2] = true; //navSB
  module2onOff[0] = true; //topp
  module2onOff[2] = true; //navBB
}

In den Arrays werden dann Wert 0 und 2 jeweils auf TRUE gesetzt.

Soll zusätzlich noch das Schlepplicht an sein (Byte 1 = 0x02), werden die Werte von oben, und zusätzlich jeweils Wert 1 auch auf TRUE für Topp- und Heckschlepplicht gesetzt.

Der Befehl, der die Werte in die Kanäle der PWM-Module schreibt benötigt als ersten Parameter die Nummer des Kanals. Da das Array genau so viele Werte hat, wie das Modul Kanäle hat, können die Werte über einfache for-Schleife geschrieben werden.

//write ledState to PWM modules
for (int i = 0; i < 16; i++) {
  if (module1onOff[i]) {
    pwmLed1.setPin(i, (uint16_t)pgm_read_word(&mappingModule1[i]), false);
  } else {
    pwmLed1.setPin(i, 0, false);
  }

  if (module2onOff[i]) {
    pwmLed2.setPin(i, (uint16_t)pgm_read_word(&mappingModule2[i]), false);
  } else {
    pwmLed2.setPin(i, 0, false);
  }
}

 

Link to post
  • 2 weeks later...
Meinolf Höhler

Weiter geht die wilde Fahrt...

Im August wurde eine neue Version von der S.Port Bibliothek heraus gegeben, in der der beliebte ESP8266 unterstützt wird. Wem das im Moment nichts sagt, der 8266 ist ein Chip bzw Board von Espressif, was einen leistungsfähigen Microcontroller mit einem WLAN Modul vereint. Das Ding ist entweder mit Lua programmierbar, oder mit C.

Da ich schon alles mit C geschrieben habe, und mein ESP8266 für Lua eine neue Firmware gebraucht hätte, bin ich bei C geblieben, und hab das Programm umgebaut.
Ich verwende (wen wunderts ) von Adafruit das Board Feather Huzzah ESP8266.

Warum der Wechsel zu dem Board? Verrückte Ideen sind noch genug vorhanden, der ESP liegt hier im Moment nutzlos rum, warum also nicht die Lichtorgel über das Mobiltelefon steuern, wenn das Boot irgendwo einfach gut aussehen soll, zur Not zu Hause im Regal.

 

Also was war zu tun?

Natürlich müssen in die Arduino IDE das Board und die Bibliotheken für das ESP eingebunden werden.

Das eigene Programm verwendet davon

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

Die Namen der Headerfiles sagen schon, was der Inhalt ist.

Es wird ein ESP8266WebServer Objekt benötigt, damit wir einen Webserver bauen können, der auf das Handy reagiert, außerdem zwei char-Konstanten, in denen die SSID und das Passwort des WLAN gespeichert sind.

In setup() sind die folgenden Zeilen dazu gekommen:

WiFi.mode(WIFI_AP_STA);
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();

Diese erstellen einen Soft-AccessPoint, der vom Handy gefunden und geöffnet werden kann. Durch einige Hintergrundmagie (die ich nicht weiter hinterfrage) bekommt man sogar eine IP, sodass alle Zutaten für einen Netzwerkzugriff au den ESP gegeben sind.

Das oben genannte Webserver-Objekt wird mit ESP8266WebServer server(80); erstellt, wobei 80 der Port ist, auf dem der Server lauschen soll.

Jetzt muss der Server wissen, was er machen soll, bzw worauf er wie reagieren soll.

  server.on ( "/", handleRoot );
  server.on ( "/FON", handleFahrtOn );
  server.on ( "/FOFF", handleFahrtOff );
  server.on ( "/SON", handleSchleppOn );
  server.on ( "/SOFF", handleSchleppOff );
  server.on ( "/BON", handleBluelightOn );
  server.on ( "/BOFF", handleBluelightOff );
  server.on ( "/MON", handleManeuverOn );
  server.on ( "/MOFF", handleManeuverOff );

  server.onNotFound ( handleNotFound );
  
  server.begin();

Die Parameter für die Anweisung server.on sind ein String aus der Adresse, mit der im Prinzip eine Webseite ausgewählt wird. Der zweite String ist ein Callback auf eine Funktion, die ausgeführt werden soll, wenn ein bestimmter Aufruf erfolgt. Die letzte Anweisung startet dann den Webserver.

Da jetzt so viele Funktionen dazu kommen, habe ich mich entschlossen, eine weitere Änderung im Code durchzuführen.

Die Arduino IDE lässt zu den Code auf Dateien zu verteilen. Die müssen im gleiche Ordner, wie die Projektdatei liegen, und sollen auch die Endung .INO haben.

In einer der Dateien sind nun die Funktionen für die Auswertung verschwunden, in der Anderen die Callback-Funktionen für den Webserver.

Die Callback-Funktionen erledigen das Gleiche, was im Sender das Lua-Script macht. Es setzt bei einer bestimmten Funktion einen bestimmten Wert in den "empfangenen Byte". Der Ort, wo der Wert ankommt, bleibt für die nachgelagerte Auswertung also gleich, nur die "Quelle" ändert sich.

void handleFahrtOn() {
  uiValue[0] |= B00000001; //Fahrtlicht EIN
  uiValue[0] &= B11111101; //Schlepplicht AUS
  
  bValuesUpdated = true;
  
  handleRoot();
}

Beispielhaft ist hier mal eine der Funktionen hineinkopiert. Sie soll das Licht für Fahrt schalten. Das versteckt sich bei Byte 1 in Bit 1. Über eine Bitmaske wird mit einem bitweisen ODER Bit 1 eingeschaltet. Da in meinem Sender das Fahrtlicht auf dem gleichen Schalter, wie das Schlepplicht liegt, schaltet die zweite Zeile das Schlepplicht aus. Dazu wird eine Bitmaske mit einem bitweisen UND auf das Byte angewendet.

Die Funktion handleRoot() am Ende schickt dem Handy die Webseite wieder zu, sodass weitere Funktionen geschaltet werden können.

Link to post
Meinolf Höhler

Fehlt noch die Funktion handleRoot():

void handleRoot() {
  char html[1500];

  // Build an HTML page to display on the web-server root address
  snprintf ( html, 1000,

"<html>\
  <head>\
    <meta http-equiv='refresh' content='10'/>\
    <title>SK33 Theodor Storm</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; font-size: 1.5em; Color: #000000; }\
      h1 { Color: #AA0000; }\
    </style>\
  </head>\
  <body>\
    <h1>SK33 Theodor Storm</br>\
    mit Nis Puk</h1>\
    </br>\
    <h2>\
      <p>Fahrtbeleuchtung:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/FON\">EIN</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/FOFF\">AUS</a><p>\
      <p>Schleppbeleuchtung:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/SON\">EIN</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/SOFF\">AUS</a><p>\
      <p>Blaulicht:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/BON\">EIN</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/BOFF\">AUS</a><p>\
      <p>Man&ouml;vrierbehindert:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/MON\">EIN</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"/MOFF\">AUS</a><p>\
    </h2>\
  </body>\
</html>");
  server.send ( 200, "text/html", html );
}

Das große sprintf() ist der HTML Code für die gelieferte Webseite. Hier ist alles nötige aufgeschrieben. Es ist nur Text mit den Links für die Schaltfunktionen drin, aber es funktioniert einwandfrei.

 

Eine Winzigkeit habe ich bis jetzt noch verschwiegen. Das Signal vom Sender könnte ja was anderes sagen, als was über den Webserver kommt.
Damit die sich nicht gegenseitig überschreiben habe ich an Eingang 13 einen Schalter gelötet, mit dem ich zwischen beiden umschalten kann.

SK33MultiswitchESP8266.zip

Link to post

Da meine X9Lite ja nur 5 Schalter hat, habe ich mich mal drangesetzt und eine grafische Oberfläche versucht um zusätzliche Schaltmöglichkeiten zu erschaffen.

Die Bedienung erfolgt per Scrollrad ( QX7 / X9Lite ), bzw nach anpassung im Script über die Tasten +- Enter  ( bei X9D/E)

Ich habe jetzt also 8 weitere Schaltmöglichkeiten , kann mit mehreren Seiten auch noch erweitert werden.

Für die X9D/E sollten so 16 Schaltmöglichkeiten pro Seite möglich sein.

 Aufrufen als Telemetriescript, das originale Function script von Meinolf dazu deaktivieren!

 

Ralf

 

 

screenshot_x9lite_19-09-25_11-11-57.png

 

SwLt.lua

 

ps. nur nicht zu lange Enter drücken, dann kommt die Frage nach Telemetrie Reset, das könnte man aber abfangen wenn ein anderer Taster zum Schalten genutzt würde...

Edited by r41065
Link to post
  • 9 months later...

Nachdem Meinolf in einem anderen Bericht bemängelt das mein Script die Schaltzustände nicht anzeigt hier noch ein paar Erläuterungen:

 

-- Kurzbezeichnungen innerhalb der Anzeigefelder:
local nm_s =
{
 "01", "02",
 "03", "04",
 "05", "06",
 "07", "08",
 "09", "10",
 "11", "12",
 "13", "14",
 "15", "16",}

Hier wird eine Kurzbezeichnung eingetragen die innerhalb der Rechtecke angezeigt wird.  Ich habe an der Stelle nur die "Funktionsnummern" als 2-Stellige durchnumerierung eingetragen.

Innerhalb der Rechtecke ist Platz für 4 Zeichen, Zeichen 3 habe ich als Trennzeichen Freigelassen, an der 4. Position wird der Schaltstatus 0 oder 1 ( Aus oder An ) angezeigt.

Wer will kann also 3 Stellige Kurzbezeichnungen eintragen.

Die aktuell zum Schalten ausgewählte Funktion wird invers dargestellt.

-- Langbezeichnungen, wird als Ueberschrift angezeigt
local nm_l =
{
 "01: Positionslampen",
 "02: Schlepplicht",
 "03: Blaulicht",
 "04: Ankerlicht",
 "05",
 "06",
 "07",
 "08",
 "09: Suchscheinwerfer",
 "10",
 "11",
 "12",
 "13",
 "14",
 "15",
 "16",
}

Die Langbezeichnung wird als Überschrift angezeigt, d.h. immer der Text passend zur angewählten Funktion(snummer).

Hier sind die entsprechenden Schaltgruppen im Klartext angezeigt.

unten drunter zeigt das Script den errechneten Variablenwert der zum Arduino gesendet wird.

Insgesamt sind die Textpositionen noch etwas angepasst das das Bild optisch zentrierter aussieht. Für das kleine Display der X7 / X(9)Lite haben sich 12 Positionen als gut Händelbar erwiesen.

In dem Script für X9D/E bleibt es bei mir bei 16 Schaltmöglichkeiten da meine verwendeten Arduino Nano nicht mehr I/O-Ports haben.

Der Rest ist das übliche, Berechnen der Textpositionen aufgeteilt auf 3 ( 2 beim grossen Display ) Zeilen, Sprung von der ersten zur letzten Position bzw. umgekehrt wenn die Randpositionen erreicht sind und Toggeln des Schaltzustand beim betätigen des Enter Tasters...

 

Da meine Modelle selten auf Ausstellungen zu sehen sind reicht mir die Schaltung über das Display vollkommen aus .

Der Schaltzustand bleibt ja erhalten auch wenn das Script nicht angezeigt wird sondern nur im Hintergrund arbeitet.

 

Alles in allem arbeitet das System seit über einem halben Jahr  ( auch mit V2 Firmware auf Sender / Empfänger und unter ACCESS ) auf 4 Sendern völlig störungsfrei.

 

Ralf

 

 

 

SwLt12.lua

Link to post
  • 1 month later...

Hallo Leute

 

Ich war so frech und hab euer (Meinolf Höhler, r41065) Projekt mal hergenommen und in Noob Programmierung es ein klein wenig verändert.

Ich benötige keinen Multiswitch, da ich ein Beier-Sound Modul verbaut habe und dieses die Prop-Kanäle aus dem S-Bus auslesen kann.

Im Beier-Modul kann man 12 Schaltfunktionen pro Prop-Kanal verwenden, wobei 4 davon "tastend" sind. Also bleiben 8 direkte Schaltfunktionen pro Kanal.

Für die Ausgabe über S-Bus verwende ich 2 Globale Variablen, die im Sender Kanälen zugewiesen werden können. (GV1 und GV2)

Die Funktionen der Schalter werden über Zeit gesteuert.

Das Beier-Modul kann:

Kurz (ca. 1 sec.):

-100%, -50%, 50% und 100%

Lang (min. 2 sec.):

-100%, -50%, 50% und 100%

ergibt in Summe unsere 8 Schalter.

Dies kann man für jeden Prop-Kanal machen, daher hätte man X Schaltmöglichkeiten bei 16 Kanälen.

Für meine Funktionen benötige ich nur 8 Schalter, das Script ist aber für 16 Schalter geschrieben, so wie eures eben im original.

 

Wie oben schon erwähnt bin ich programmier Anfänger, ich kann zwar viele Scripte lesen, aber mit selbst schreiben ist das so eine Sache.

Daher hab ich mir euer Script ausgeliehen und umgeschrieben. Aber auch wieder nur auf Anfänger Sprache. Ev. gibt es hier ja jemanden der besser programmieren kann und könnte das ganze vereinfachen und besser machen.

 

@Meinolf Höhler , @r41065 dürfte ich dieses veränderte Script im Truckmodellforum teilen, da es dort sicherlich auch einige Interessenten dafür gibt.

 

Lg Michael

SW8.lua

Edited by MichaelH1982
Link to post

Die Ursprungsidee zu der grafischen Oberfläche stammt von Suppenhuhn aus dem rc-modellschiffe.de Forum ( leider schon verstorben ) von daher sehe ich bei meinem Anteil keine Probleme...

Ich hatte seine Idee eine grafische Oberfläche und Lua Scripte zur Ansteuerung von Original Graupner / Robbe / Beier Multiswitchen zu nutzen ja auch nur an meine HW und Wünsche sowie Meinolf's Funktions-Script angepasst.

Leider hat er seine Ergebnisse / Scripte und Arduino Code nie veröffentlicht sondern nur ein Video als Beweis das es funktioniert...

 

Ralf

 

werde dein Script dann mal testen und einem Kollegen weiterleiten, der hat sich auch ein USM2 gegönnt...

Edited by r41065
Link to post

Ist eine tolle idee mit dem adurino.

 

meine änderungen im script haben nur einen kleinen bug, den ich nocht weiß wie ich ihn behebe.

wenn man zweimal kurz hintereinander mit der enter taste die funktion bestätigt, bleibt das script hängen, da eine variable einen zustand erreicht, der nicht abgefragt wird, derzeit hilft nur, funke aus und wieder ein, oder per taste das script neu einlesen lassen.

 

wie gesagt, vielleicht findet sich jemand, der das script effizient überarbeiten kann.

ich habs leider nicht besser hinbekommen. 
 

Vielen dank für deine freigabe.

das script von suppenhuhn hab uch bereits gelesen, dass es das gibt, hab mich in dem forum schon angemeldet.

 

lg

Link to post

In meinem Script gibt es die Abfrage

if timenow - timeprev > 20 then   timeprev = timenow

 

Dadurch wird das Script nur alle 200msec  durchlaufen und die Variablen haben definierte Zustände.

( Meinolf fragt in seinem Script die Schalter alle 500 millisec. ab )

Bin gerade nur per Handy unterwegs da ist das lesen deines Scripts etwas mühsam, habe eine solche Funktion bei der ersten Durchsicht nicht gefunden.

Die Zykluszeit von Lua Scripten auf der Taranis ist mit ca 20 msec deutlich schneller.

 

An deiner Stelle würde ich die Event Handler nur Erlauben wenn die GV beide auf Null stehen, dann dürftest du keine "undefinierten" Schaltzustände mehr provozieren können...

 

Ralf

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.