Rp2040 connect Sensordaten ueber WiFi senden

Ich würde gerne die Sensordaten von Gyroskop und Beschleunigungs-Sensor über WiFi an ein c++ Programm auf Ubuntu schicken.
Sensordaten auslesen und auf einem LCD anzeigen funktioniert schon.
Ein Beispielprogramm um etwas über WiFi in einem Browser anzuzeigen habe ich auch schon erfolgreich ausprobiert.
Die Frage ist jetzt wo findet man die grundlegenden Informationen um Daten übers WiFi zu senden.
Wobei ich wohl gleichzeitig auch noch herausfinden muss wie man unter Ubuntu die Daten vom WiFi wieder empfangen kann.

Oder wäre vielleicht Bluetooth die bessere Wahl?

Ihr Beitrag wurde an seinen aktuellen Speicherort verschoben, da er besser geeignet ist.

Dann ist das Thema Server schon erledigt.

Sicherlich gibt es fertige HTTP Client Komponenten für dein C++

Hallo,
was für einen Controller wolltest Du verwenden. Du könntest einen ESP 8266 verwenden, das macht vieles einfacher. UDP oder TCP geht sicher am schnellsten. Allerdings wirst Du dazu eine Anwendung auf dem PC verwenden müssen die das kann .
Die einfachste Variante ist sicher auf dem PC einen Brauser zu verwenden, und auf dem ESP einen Webserver mit einer geeigneten HTML Seite.
Allerdings wirst Du Dich da etwas in Java-Skript einarbeiten müssen. Du kannst Dich ja mal bei https://fipsok.de/ umsehen, sicher findest Du da etwas für Dich.
Heinz

Mein Controller ist der "rp2040 connect". Den ESP 8266 kenne ich nicht. Hat der denn auch einen Beschleunigungssensor und Gyroskop eingebaut?
Das Programm zum die Sensordaten empfangen ist c++. Meine Idee ist es eine Bewegungssteuerung in mein angefangenes Spielprogramm einzufuegen. Und dieses ist in C++ geschrieben.

Hallo,
Nein, aber das kann man über I2c anschließen. Den Vorteil sehe ich darin das Du für den ESP jedem Menge Beispiele findest , da wir auch was passendes für Dich bei sein.

Die Seite wirst Du ja sicher kennen
Heinz

Stichworte "HTTP Client" war ein guter Hinweis. Vielen Dank.
Ich habe ein entsprechendes Beispielprogramm gefunden. War etwas schwierig zu verstehen, da nur spärlich kommentiert. Muss es jetzt noch anpassen (eine Menge für meine Anwendung unnötiges löschen), und auch den Serverteil noch anpassen. Dies kann noch eine Weile dauern.

Wenn du sowieso beide Seiten anpassen willst, dann kann ich dir sogar eine Richtschnur an die Hand geben:

Nach vielen Stunden Programmieren habe ich es endlich geschafft mal ein einfaches Beispielprogramm zu erstellen.
Der Durchbruch war erreicht als ich festgestellt hatte, dass dies nicht funktioniert:

  client.println("HTTP/1.0 200 OK");
  client.println("Content-type:text/html");
  client.println();

Damit es funktioniert muss man es so schreiben:

  client.println("HTTP/1.0 200 OK\nContent-type:text/html\n\n");

Mir ist allerdings immer noch nicht klar warum und wieso.
Im Beispielprogramm "WEB SERVER EXAMPLE" von Karl Soederby hatte auch die erste Variante funktioniert.
Ein ähnliches Programm ist auch unter docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-web-server-rgb zu finden. Da scheint aber ein Fehler passiert zu sein, denn mit fehlenden Leerstellen und Zeilenumbrüchen ist es sehr schwer lesbar. Kann man eigentlich irgendwie Fehler an docs.arduino.cc melden?

Mein jetzt funktionierendes Programm habe ich mal auf meine Homepage gestellt:
http://www.rolfp.ch/elektronik/#bewsens
Es besteht aus dem Arduino-Programm wifisens.ino und dem empfangenden c-Programm httpclient.cc. Ein makefile zum einfacheren Compilieren unter Linux ist auch mit dabei. Auf Windows habe ich es noch nicht getestet.

Grundsätzlich ist mir immer noch nicht ganz klar wann man OK-Bestätigungen zwischen Server (Programm auf dem Controller) und Client (Programm am Computer) machen sollte.
Verschiedene Beispielprogramme und Hinweise in Wikipedia (mit Suchwort HTTP) widersprechen sich da.

Ich habe bei mir gerade mal nachgesehen, das sieht hier beim UNO mit W5100 ein wenig anders aus.
Kannst Du mal testen:

          client.println("HTTP/1.1 200 OK");
          client.println("Connection: close");
          client.println("Content-Type: text/html; charset=UTF-8");
          client.println("Content-Language: de");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
[...]

Vielleicht habe ich mich etwas unklar ausgedrückt. Die Variante den Header mit drei client.println() Aufrufen zu senden funktioniert zwar wenn ich mit dem Browser abfrage, hingegen mit dem c-Programm als HTTP-Client funktioniert es nicht korrekt.
Es wird dann beim Empfang des Headers immer nur die erste Zeile empfangen, also "HTTP/1.0 200 OK". Die folgenden Zeilen kommen dann erst später an, aber meistens nicht alle.`
Mit der Variante den ganzen Header mit einem einzigen client.println() zu senden funktioniert jedoch alles.

Bei der vorgeschlagenen Variante von my_xy_projekt kommt beim Lesen des Headers auch nur die erste Zeile an.
Typischer Testlauf:
./httpclient
url: 192.168.4.1
path: /Data
portnr: 80
getrequest="GET /Data HTTP/1.1
HOST: 192.168.4.1

"
Socket created...
starte connect(sockfd ...)
Connection successful...

starte write(sockfd, getrequest ...)
buffer="HTTP/1.1 200 OK"
Fehler: buffer="
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Language: de

Tim: 111478 "

Dabei ist der erste Testausdruck "buffer=..." das was beim Lesen des Headers gekommen ist.
Der Testausdruck "Fehler: buffer=" ist das was beim Lesen der Daten angekommen ist, und im Parser als falsch erkannt wurde.

Ach,
dann ist Dein C-Programm kaputt!

Das fällt Dir früher oder später auf die Füsse, wenn Du Dich da mit irgendwelchen Krücken durchwurschtelst.

Mach es richtig!

dann funktioniert dein "c-Programm" nicht richtig, denn die HTTP-Headerfields werden mit CRLF getrennt.
[url]List of HTTP header fields - Wikipedia

Ich glaub jetzt habe ich den Fehler im Client (c-Program auf dem Computer) gefunden: ich rufe recv() einfach mehrfach auf bis eine Leerzeile gelesen wird, die dann das Ende vom Header markiert.

Also dieses
ret = recv(sockfd, buffer, BUF_SIZE, 0);
ersetzt durch
ret = mehrfach_recv(sockfd, buffer, BUF_SIZE, 0);

Mit entsprechendem neuen Unterprogramm:

int mehrfach_recv(int sockfd, char *buffer, int size, int flags)
{
 int ret,i,j, imax=1000000; //Schlaufenabbruch nach ca. 1 Sekunde
 int n=size;
 for(i=j=0; (ret = recv(sockfd, &buffer[j], n, flags)) >= 0 && i<imax; i++)
  {
   j += ret;
   if(j>3 && strncmp(&buffer[j-3],"\n\r\n",3)==0 || strncmp(&buffer[j-2],"\n\n",2)==0)
    {break;}//fertig wenn Leerzeile erkannt
   if(j>=size) {printf("Buffer zu klein\n"); return -1;}
   n=1; //im naechsten Durchlauf 1 weiteres Byte empfangen
   usleep(1); // 1 Microsekunde warten
  }
 if(i>=imax) {printf("timeout in mehrfach_recv()\n"); return -1;}
 if(ret<0) return ret;
 return j;
}

So funktioniert es auch wenn ich im Server den Header mit mehreren println() Aufrufen sende.
Fragt sich jetzt noch ob man das wirklich so kompliziert machen muss, oder ob es nicht doch auch einfacher gehen würde.

Danke für die Anregung

wieso erscheint dir das kompliziert? du veroderst dein

"\n\r\n",3)==0 || strncmp(&buffer[j-2],"\n\n",

und weist somit genau dass eine Leerzeile gekommen ist. Alternativ könntest du auch prüfen wann ein \n gekommen ist und ob das innerhalb der ersten zwei Zeichen der Zeile eingetroffen ist. Aber dein oder ist genauso gut.

Die ganze Schlaufe schien mir zu kompliziert zu sein. Ich habe dann auch eine etwas einfachere Variante gefunden, indem ich recv() durch read() ersetzt und den ürberflüssigen timeout-Test weggelassen habe:

int mehrfach_read(int fd,char *buf,int n)
{
 int ret;
 for(int j=0; j < BUF_SIZE-1 && (ret=read(fd,&buf[j],n)) > 0; )
  {
   j += ret;
   if(j>2 && (strcmp(&buf[j-2],"\n\n")==0 || strcmp(&buf[j-3],"\n\r\n")==0))
    {return j;}//fertig wenn Leerzeile gelesen
   n=1; //beim naechsten Durchlauf 1 weiteres Byte lesen
  }
 return -1;//Fehler wenn keine Leerzeile gefunden
}

Aufruf der Schlaufe mache ich dann so:

//ret = mehrfach_read(sockfd, buffer, BUF_SIZE);
ret = mehrfach_read(sockfd, buffer, sizeof(http_ok)+2);

Statt BUF_SIZE habe ich gleich die minimale Antwortlänge angegeben, sonst könnte es vielleicht Probleme geben falls es irgendwann mal einen schnelleren Controller gibt.

Mit dem Vorschlag von noiasca nach einfacherem Leerzeilen-Test wird es vielleicht nochmals etwas einfacher. Werde das demnächst noch ausprobieren.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.