Paralleler Funktionsaufruf / Mehr als ein Rückgabewert

Dabei habe ich das doch extra mit ins Beispiel übernommen!

Frage dich: Wozu gibt es den Returntype Result?
Was könnte Combie damit wohl beabsichtigt haben?
Richtig, um 2 Werte bei einem Aufruf berechnen zu können!

void setup() 
{
  Serial.begin(115200);
  delay(2000); // Dem Serial kurz Zeit geben...
  Result k {kreis(2.2)};
  weiterrechnen(k.flaeche, k.umfang);
}
1 Like

Oh Gott, ist das peinlich:

Ob du es glaubst oder nicht, das hatte ich aufgrund des Anzeigebereichs übersehen:

Scheiße, sorry. Tut mir voll leid jetzt.
DIe ganze Verwirrung umsonst.

Ich bin einfach zu tollpatschig :wink:

Danke Danke @combie

Hast mir voll weitergeholfen.
Wieder was dazugelernt.

Schönen Abend euch, ihr seid die Besten :upside_down_face:

Vermutlich das falsche!

Ich hoffe mal nicht :wink:
Für eure Geduld mit mir wird euch auf jeden Fall ein Orden verliehen

Das hatte ich mir vorgestellt das du dies suchst: Dein Beispiel minimal geändert

#include <WiFi.h>
#include <WebServer.h>
WebServer server(80);

#include <ArduinoJson.h>

// Verbindungskrimskrams
unsigned long connTimer=0;
unsigned long dauer = 10000;
const char ssid[14] = "Meine SSID";
const char password[21] = "MeinPasswort";

// Hier sehe ich das Problem, dass diese Variablen 
// durch zeitliche Überschneidungen beim Funktionsaufruf u.U. falsch/durcheinander befüllt werden
uint16_t ergebnis_eins = 0;
uint16_t ergebnis_zwei = 0;


static const char indexPage[] PROGMEM = R"=====(
<!doctype html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
  </head>
  <body>
    <button type='button' onclick='meinefunktion(2, 3);'>Button 1</button>
    <button type='button' onclick='meinefunktion(4, 5);'>Button 2</button>
  </body>
</html>

<script>
function meinefunktion(wert_eins, wert_zwei) {
  var xmlhttp;
  var url="/meinefunktion?wert_eins="+wert_eins+"&wert_zwei="+wert_zwei;
  xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function(){
      if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
          let obj = JSON.parse(xmlhttp.responseText);
          console.log(obj.rueckgabewert_eins);
          console.log(obj.rueckgabewert_zwei);     
      }
  }
  xmlhttp.open("GET", url, true);
  xmlhttp.send();
}
</script>

)=====";


void display_root() {
  const char * httpType PROGMEM = "text/html";
  server.send_P(200,  httpType, indexPage);
}


void setup() {
  delay(2000);
  Serial.begin(115200);
  
  // Erstverbindung aufbauen
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  connTimer = millis();
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println(WiFi.localIP());
  
  server.on("/", display_root);
  server.on("/meinefunktion", meinefunktion);
  
  server.begin();
}

void loop() {
  server.handleClient();
}


void meinefunktion() {
  StaticJsonDocument<48> doc;
  String output="";
  
  uint16_t wert_eins = server.arg("wert_eins").toInt();
  uint16_t wert_zwei = server.arg("wert_zwei").toInt();
  
  // Berechnungen in Nebenfunktion durchführen
  nebenfunktion(wert_eins, wert_zwei);  // call by refernce

  // Mit Ergebnissen aus Nebenfunktion weiterarbeiten
  //uint16_t rueckgabewert_eins=ergebnis_eins +10;
  //uint16_t rueckgabewert_zwei=ergebnis_eins +20;

  doc["rueckgabewert_eins"] = wert_eins;
  doc["rueckgabewert_zwei"] = wert_zwei;

  serializeJson(doc, output);
  server.send(200, "application/json", output);
}


void nebenfunktion(uint16_t &wert_eins, uint16_t &wert_zwei) {
  // Ergebnisse in globale Variablen schreiben, sodass die Werte anschließend 
  // in "meinefunktion()" weiterverwendet werden können
  wert_eins = wert_eins * 10;
  wert_zwei = wert_zwei * 10;
}

Würde ich auch gerne!

z.B. das.

Ein Tipp:
Je öfter man etwas wiederholt, desto fester glaubt man selber daran.
Damit sollte man vorsichtig sein!
Das Verfahren nennt sich Autosuggestion.

Dein Haupt-Fehler war übrigens nicht das fehlende Scrollen!
Sondern das nicht erkennen des Rückgabetypen der Funktion.
Das nicht wissen um die Tragweite.

Denn:
Mit dem Wissen/Erkennen hättest du gar nicht scrollen müssen!
Da unten verbirgt sich keine Überraschung, keine Heilung, nix was anhaltende Erkenntnis bringt.

Also:
Schön, dass du den Scrollbalken jetzt gefunden hast.
Wichtiger wäre aber, dass du dich mal mit Datentypen und ihre Verwendung schlau machst. Auch wie man eigene bauen kann.

Du hast ja so Recht :rofl:

Aber trotzdem ists halt so: EIn Mensch ist, wie er ist.
Ein bissl was geht, aber vieles besteht!
Ich geb mir trotzdem größte Mühe mich zu bessern - kann aber nicht versprechen, morgen schon wieder "nicht zu scrollen" :wink:
In diesem Sinne: Guts nächtle allerseits und bis zur nächsten Panne!

Ach, die Panne ignoriere ich noch nicht einmal!
Und das solltest du auch wohl tun...

1 Like

Ich geb mein Bestes..ob es wohl reicht ?

Hallo,
Du könntest Dir auch mal das ansehen
https://de.wikibooks.org/wiki/C%2B%2B-Programmierung/_Weitere_Grundelemente/_Prozeduren_und_Funktionen

und da in Deinem Fall den Abschnitt "call-by-reference

Heinz

1 Like

Kuck ich mir an. Mir ist halt wichtig, dass die Funktion für jeden User, der einen der Buttons meines Beispiels drückt, das entsprechende Ergebnis liefert und die Werte nicht vermischt oder überschrieben werden durch zeitliche Überschneidungen beim Funktionsaufruf. Und das ich mehrere Rückgabewerte hab. Von daher bin ich mit Combies Lösung schon sehr glücklich

Die Arbeit mit Strukturen ist schon effektiver, als mit einzelnen Referenzen.
Evtl. könnte man noch eine Referenz auf eine Struktur ins Spiel bringen :wink:
Aber bleibe mal lieber bei der Rückgabe der Struktur.

Gruß Tommy

Ich verstehe das Problem überhaupt noch gar nicht.
Sehe nicht, was sich da vermischen könnte.

Aber ist auch egal......

1 Like

Hallo,
ich verstehe Dein Problem auch nicht so richtig.
Du hast eine Webseite mit zwei Buttons und sagen wir mal damit schaltest Du eine LED ein und aus. Wo soll es jetzt da ein Problem mit dem Aufruf geben wenn die Seite jetzt z.B von zwei unterschiedlichen usern mit eigenen Brausern "gleichzeitig" aufgerufen wird ? Im Prinzip sind die beiden Brauser parallel Brauser1 kann ein und ausschalten und ebenso Brauser2 und das auch gemischt, also Brauser1 schaltet ein und Brauser2 aus.
Ich könnte mir allerdings vorstellen das Dir eigentlich das Thema "Classen" und Instanzen unbewusst durch den Kopf geistert. Ein einfaches Beispiel dazu , zwei LED´s sollen unabhängig voneinander blinken. Dann verwendest Du eine Klasse "Blinker" und legst zwei Instanzen an.

Blinker blink1()
Blinker blink2()

Dabei hat dann jede Instanz seine eigenen Blinkzeiten und Zustände.
Wenn Du das jetzt auf Deine Webseite beziehst und zwei User ( Brauser) greifen auf den ESP zu und jeder User soll seine eigenen "Daten" Verarbeiten können dann musst Du sicher im ESP mitführen wie viele User da gerade angemeldet sind. Das kann man mittels der zugehörigen IP Adresse machen.
Beispiel aus dem realen Leben
auf einer Webseite ( Online Schopping) sind gleichzeitig mehrere Leute aktiv, das können hunderte sein. Die Bestellungen sollen ja aber nicht durcheinander laufen sondern schon zugeordnet werden.
Heinz

Ich versuchs nochmal zu beschreiben.
Bei meinem Beispielsketch nutze ich zwei globale Variablen zum Zwischenspeichern von Werten, um mit diesen in einer Nebenfunktion weiterzuarbeiten. Und ich habe eben hier "Angst" dass user 1 den Button 1 drückt, die globalen Variablen dann mit den entsprechenden Werten befüllt werden und dann- bevor die Nebenfunktion diese Werte abgreift - user 2 den anderen Button drückt und damit die globalen Variablen wieder mit anderen Werten überschreibt. Versteht ihr was ich meine? Zwei Clients beschreiben zeitgleich die gleichen globalen Variablen.

Oder an einem Realbeispiel dargestellt:

Ich habe zwei Teller (=die globalen Variablen), leg in jeden ne Scheibe Käse rein (=ich drück Button 1) um mir anschließend ein Brot zu machen. Ich bin User 1.
Noch bevor ich mir das Brot machen kann ersetzt User 2 die Scheiben Käse durch Wurst weil er ja die gleichen Teller nutzt und weil er eben eine Microsekunde später oder sogar gleichzeitig den Button 2 drückt.

By the way: bei den Buttons und Funktionen handelt es sich natürlich nur um sinnlose Beispiele zur Demonstration der Problematik - falls es überhaupt eine gibt. Kann natürlich auch sein, dass ich hier falsch liege.

Grundsätzlich versuche ich eben auch immer, wenn möglich, globale Variablen zu vermeiden.

Es ist doch sichergestellt, das erst die „Nebenrechnung“ ausgeführt wird, bevor auf einen weiteren Button Druck reagiert wird.

Code wird Zeile für Zeile ausgeführt. Nur Interrupts können dies unterbrechen, und nach dem Interrupt, geht es dort weiter wo „rausgesprungen“ wurde

Dann würde ich natürlich falsch liegen.
Aber Zeile für Zeile ausgeführt wäre ja auch
Button 1 wird gedrückt
Käse drauf
Button 2 wird während der Käse drauf gelegt wird gedrückt
Die Wurst wandert drauf noch bevor die Nebenfunktion den Käse runternehmen kann.

Und wenn ich mir jetzt vorstelle dass noch hundert weitere user gleichzeitig unterschiedliche Buttons drücken stell ich mir eben vor, dass das dann zu einem Problem führen könnte, wenn immer die zwei gleichen globalen Variablen als Zwischenpuffer verwendet werden.

Aber wahrscheinlicher denk ich hier zu abstrakt.

Dein Code reagiert erst auf einen neuen Button Druck, wenn die entsprechende Codezeile erreicht wird. Ich denke du hast keine Vorstellung wie schnell dein Microkontroller ist. 16MHz bedeutet 16 Millionen Aktionen pro Sekunde.

Ok, dann denk ich zu kompliziert.
Aber ich fühl mich mit Combies Lösung trotzdem wohler als mit den globalen Variablen.