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.
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.
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.
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:
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.
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
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.
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.
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.