Neuling mit einigen Fragen (Grundlagen, FSX, etc.)

Guten Tag,

ich habe seit Mitte Dezember einen Arduino und experimentiere im Moment ein wenig.
Mir ist leider kein besserer Threadtitel eingefallen, da ich noch am Anfang stehe.

Kurz zu meiner Person:

Ich bin Moritz, 26 Jahre alt und komme aus dem hohen Norden (nahe Bremen).
Ich habe vor einigen Jahren eine Ausbildung zum Fachinformatiker für Systemintegration abgeschlossen, ein bisschen Programmierung und IT-Kenntnisse sind mir also nicht ganz fremd.

Was will ich tun?
Ich bin von der Fliegerei begeistert und möchte den Arduino Uno mit FSX / P3D nutzen.
Ebenso finde ich aber auch andere Themen spannend (Temperatur im Serverschrank messen etc.).

Was habe ich bisher gemacht?
Auf Basis des Tools Link2FS (JimsPage) habe ich ein paar LED's ansteuern können, ich konnte per Drehimpulsgeber Werte Anpassen, den Autopiloten per Pushbutton ein und ausschalten usw. Gear up, Gear down. Einiges funktioniert schon und man hat Erfolgserlebnisse.

Bisher ist der Weg aber immer "vom Arduino" in den PC - das soll sich ändern.
Teilweise hänge ich aber auch an einfachen Problemen fest.

Wo liegen aktuelle Probleme?

If mit Serial.Println

Ich möchte, dass abhängig von einem Kippschalter (angeschlossen an Pin 8) Werte ausgegeben werden.
Wenn der Kippschalter == HIGH ist, dann soll Serial.println("AP on") ausgegeben werden, sonst Serial.println("AP off).

Das funktioniert nun auch soweit, jedoch habe ich das Problem, dass er mir den Wert immer neu sendet, logisch, da im Loop.

Wie kann ich es nun so einstellen, dass er mir den jeweiligen Wert nur sendet, wenn eine Änderung von LOW auf HIGH oder von HIGH auf LOW vorlag?
Ich meine ich habe das mal mit einer zweiten Variable gelöst ("apstatusold") und miteinander vergleichen.

Ich habe den Code leider zu Hause und momentan keinen Zugriff (tut mir leid).
Der Code sah "menschlich" ungefähr wie folgt aus:

Erläuteurung: apstatus enthält digitalRead(apkippschalter)

Wenn (apstatusold != apstatus)
{

Wenn (apstatus == 1) Serial.println("AP on");
Wenn (apstatus == 0) Serial.println("AP off");
}
else
{
}

apstatusold == apstatus;

Ich werde das Forum hier in Zukunft öfter nutzen (müssen), mein nächstes Problem ist das Einlesen von Informationen, die der PC an den Arduino sendet - aber erstmal langsam :-).

Vielen Dank,

Du hast es doch brauchbar gelöst. Welches Problem hast du noch damit?

nicht apstatusold == apstatus;
sondern apstatusold = apstatus;

Ging es dir im anderen Forum nicht schnell genug?
https://www.mikrocontroller.net/topic/385482#new

Auf die Antwort hast du noch nicht reagiert.

Hallo zusammen,

erst einmal Danke für die Antworten.

@ EIEspanol: Tjah, ich werde den Code heute Abend noch einmal vergleichen, gestern funktionierte es nicht fehlerfrei.

@ HotSystems: Korrekt, das war ich. Ich habe die "Deutsch-Fraktion" hier später entdeckt, vermutlich deine Antwort erst nach deinem Post hier gesehen. Wie Switch Case funktioniert ist mir geläufig. Ich muss mich mit dem Thema noch einmal ausseinander setzen, da ich das noch nicht durchschaut habe.

Danke euch beiden :slight_smile:

Wenn du uns deinen Sketch postest, können wir dir sicher weiter helfen.
Allerdings solltest du Crosspostings zukünftig vermeiden.

Das ist auch wieder ein einfacher endlicher Automat!
Ob der mit if oder switch gebaut wird, ist dabei völlig egal.

Einzig die Betonung, bzw. der Fokus, auf den Status/Zustand ist relevant, und führt zum Ziel.

Das, was Du gemacht hast, nennt man Flankenerkennung, wobei Du sowohl die steigende wie die fallende auswertest.
Da der Schalter nur zwei Positionen kennt, kannst Du mit einer logischen Variablen arbeiten:

bool apstatus;
bool apstatusold;

Wenn (apstatus && !apstatusold){ Serial.println("AP steigende Flange"); }
Wenn (!apstatus && apstatusold){ Serial.println("AP fallende Flanke"); }

apstatusold = apstatus;

Nicht besser, nur anders.

Guten Abend zusammen,

ich habe es nun so gelöst:

int apstatus;
int apstatusold;

int inputPin = 8;               // choose the input pin (for a pushbutton)
int val = 0;                    // variable for reading the pin status

void setup() {

pinMode(inputPin, INPUT);   
Serial.begin(115200);
}

void loop(){
val = digitalRead(inputPin);  // read input value
if (val == HIGH) {            // check if the input is HIGH
apstatus = 1;
}
else {
apstatus = 0;
}

if(apstatus != apstatusold)
{
  if(apstatus == 1) Serial.println("B02"); //B02 turns AP off
  if(apstatus == 0) Serial.println("B03"); //B03 turns AP on
}

delay(50);
apstatusold = apstatus;

}

Das funktioniert auch hervorragend.
Vielleicht war es gestern Abend einfach zu spät.
Danke für die Unterstützung!

Neue Frage:
Ich würde den Code nun gerne so erweitern, dass auf Basis der Angaben aus dem FSX eine rote oder grüne LED leuchtet.
Ich kann das natürlich recht einfach oben mit in die If (apstatus == x) hängen, das will ich aber nicht.

Der FSX meldet einen Datenstring zurück den ich gerne auslesen möchte, und zwar folgenden:

AP einschalten: "=a1"
AP ausschalten: "=a0"

Die Daten kommen auch alle korrekt an meinem Arduino an (siehe Screenshot).
Um mich an die Switch Case Thematik ran zu tasten, habe ich im Sketch gesagt, dass er in Abhängigkeit des Cases "An" oder "Aus" ausgeben soll (ist ja etwas weniger fehleranfällig als die LED-Ansteuerung).

Leider kommt bei mir aber immer "Aus" zurück, auch wenn der Datenstring "=a1" ist.
Hier der Code und unten dann noch der Screenshot aus Link2FS.

int CodeIn;// used on all serial reads
void setup()
{
  Serial.begin(115200);
}

void loop() {

  if (Serial.available()) {//checks the serial read buffer
    CodeIn = getChar();// reads one charactor via it's own routine
    if (CodeIn == '=') {
      EQUAL(); // The first identifier is "=", goto EQUAL void
    }
    if(CodeIn == 'a'){
      APONOFF(); // The second identifier is "a", goto APONOFF void
        switch (CodeIn){
        case '1':  Serial.println("An"); // Wenn der dritte Char 1 ist
        case '0':  Serial.println("Aus"); // Wenn der dritte Char 0 ist        
        break;
        } 
    }
  } //end of yes there is something to read
} // end of void loop (The main one)

char getChar()// Get a character from the serial buffer
{
  while (Serial.available() == 0); // wait for data
  return ((char)Serial.read()); // Thanks Doug
}// end of getchar void.

void EQUAL() {   // The first identifier was "="
  CodeIn = getChar(); // Get the second identifier
} // End of EQUAL

void APONOFF() {   // The second identifier was "a"
  CodeIn = getChar(); // Get the third identifier
} // End of APONOFF

Vielen Dank für die Unterstützung!

Die serielle Routine ist Mist, viel zu unflexibel. Ich muss mal den Post suchen, wo eine universelle Einleseroutine gepostet wurde.

Der erste Sketch, so ist das etwas kompakter und trotzdem anfängerfreundlich lesbar:

bool apstatus, apstatusold;
byte inputPin = 8;               // choose the input pin (for a pushbutton)

void setup() {
Serial.begin(115200);
}

void loop(){
  
apstatus = digitalRead(inputPin);  // read input value
if(apstatus != apstatusold)
{
  if(apstatus) Serial.println("B02"); //B02 turns AP off
  else Serial.println("B03"); //B03 turns AP on
}
delay(50);
apstatusold = apstatus;
}

Edit: Habs gefunden: Beitrag #6 von Serenifly

Du scheinst auch einer dieser Leute zu sein die denken "void" bedeutet "Funktion"...

Am flexibelsten ist man bei sowas wenn man beim Senden den String mit einem Linefeed/newline abschließt um das Ende zu markieren und dann erst mal komplett einliest. Dann ist Einlesen und Auswertung getrennt:

const int SERIAL_BUFFER_SIZE = 10;
char serialBuffer[SERIAL_BUFFER_SIZE];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (readSerial(Serial) == true)
  {
    parseSerial();
  }
}

void parseSerial()
{
  if (strncmp(serialBuffer, "=a", 2) == 0)
  {
    switch (serialBuffer[2])
    {
      case '0':
        Serial.println("aus");
        break;
      case '1':
        Serial.println("an");
        break;
    }
  }
}

bool readSerial(Stream& stream)
{
  static byte index;

  while (stream.available())
  {
    char c = stream.read();

    if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c;
    }
    else if (c == '\n' && index > 0)
    {
      serialBuffer[index] = '\0';
      index = 0;
      return true;
    }
  }
  return false;
}

Den Parser kann man auch anders machen. Ich habe einfach mal abgefragt ob der String mit "=a" anfängt. Das ist aber nicht die einzige Lösung

Wichtig es eben dass du beim Senden in LF hinten anhängst!

Hallo,

vielen Dank für die schnelle Hilfe.
Den ersten Sketch habe ich so wie von EIEspanol beschrieben übernommen, Danke dafür!

@ Serenfly:
Wenn ich deinen Code so übernehme, dann bekomme ich zwar die Daten vom FSX zu Links2FS gesendet, aber die Println-Anweisungen wirken nicht. In Link2FS sieht es wie im Screenshot aus (Baudrate angepasst).

Und ja: Ich dachte bisher das void für Funktionen ist.
Magst du mich aufklären?

Vielen Dank für die klasse Unterstützung!

Ich dachte bisher das void für Funktionen ist.

Wie erklärst du dir dann "char getChar()"?

Void ist ein Datentyp:

In diesem Fall bedeutet dass die Funktion nichts zurück gibt

Ich habe zweimal gesagt dass der String mit einem LF abgeschlossen werden muss! Nun sehe ich aber nicht dass man das in dieser Software einstellen kann (vielleicht unter "communication settings"?). Dann kann man alternativ ein Nicht-Steuerzeichen wie '#' nehmen.

Dann muss du den Code so abändern:

    if (c == '#' && index > 0)
    {
      serialBuffer[index] = '\0';
      index = 0;
      return true;
    }
    else if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c;
    }

Also zuerst auf das Endzeichen abfragen