[C] fopen() in einer while()-Schleife

Diskutiere [C] fopen() in einer while()-Schleife im Developer Network Forum im Bereich Hardware & Software Forum; Liebe C-Coder, Ich habe ein kleines Spiel programmiert und parallel dazu einen Wii-Mote gebastelt, der per USB am Computer ausgelesen wird. Ich...
  • [C] fopen() in einer while()-Schleife Beitrag #1
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Liebe C-Coder,
Ich habe ein kleines Spiel programmiert und parallel dazu einen Wii-Mote gebastelt, der per USB am Computer ausgelesen wird.
Ich habe folgenden Code
Code:
      port=fopen("/dev/ttyUSB0", "r+");
	while(i!=14)
	{
	column[i]=fgetc(port);
	printf("%c",column[i]);
	i++;
	}
	x=((int) column[1] - '0') *100+((int)column[2] - '0') *10+((int)column[3] - '0');
	y=((int) column[5] - '0') *100+((int)column[6] - '0') *10+((int)column[7] - '0');
	z=((int) column[9] - '0') *100+((int)column[10] - '0') *10+((int)column[11] - '0');
	val=((int) column[13] - '0');
	printf("\n x==%d y==%d z==%d Button.value==%d\n",x,y,z,val);
(errno.h, stdio.h)
schon erfolgreich kompiliert.
Nun versuche ich, ihn in einem Spiel unterzubringen, d.h. in einer while()-Schleife.
Sobald sich das "fopen" in der Schleife befindet, gibt das Programm unsinnige Zahlen aus, z.B. val==16, dabei kann der int "val" nur die Werte 0 und 1 annehmen. Außerhalb der Schleife gibt das Programm Werte aus, die sehr gut stimmen könnten, diese bleiben aber konstant, immerhin wird die Datei nur einmal ausgelesen.
Meine Frage: Welchen Befehl soll ich statt "fopen("/dev/ttyUSB0","r+");"
nehmen?
Ich nutze Debian GNU/Linux Lenny und parallel dazu XUbuntu 9.04.
Außerdem kompiliere ich mit gcc.
 
  • [C] fopen() in einer while()-Schleife Beitrag #2
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Willst du den ganzen Code also in die Hauptschleife des Spiels packen? Dann solltest du den Port bei der Initialisierung vor der Hauptschleife öffnen und offen lassen. Das Problem wird höchstwahrscheinlich die Synchronisierung sein; wenn fopen aufgerufen wird, ist nicht gesagt, welches Zeichen gerade vom Controller gesendet wird - der kann also gerade mitten in der Übertragung sein.
Um so etwas robust zu programmieren braucht man irgendein Übertragungsprotokoll, z.B. Frame-basiert in der Art, dass jeder Frame mit einem definierten Startzeichen beginnt (das optimalerweise nicht in den Daten vorkommen kann), dann evtl. die Länge der Nutzdaten/Anzahl der Parameter (falls die veränderlich sein kann), evtl. ein Zeichen für den Typ der Message (falls es verschiedene gibt), danach Nutzdaten, evtl. eine Prüfsumme, und schließlich evtl. noch ein Stopp-Zeichen.
Auf der PC-Seite dann eine passende Verarbeitung, am einfachsten in Form einer Statemachine. Zusätzlich kann man darüber nachdenken, die Verarbeitung in einem separaten Thread auszuführen, die einfach Variablen (die die Steuerung repräsentieren) aktualisiert, sobald ein gültiger Frame empfangen wurde.
Die Ausführung in einem separaten Thread hat den Vorteil, dass das Spiel nicht hängt, wenn kurz kein Signal kommt. Overlapped IO wäre auch eine Möglichkeit dafür, aber ich persönlich finde einen eigenen Thread einfacher. Multithreading ist allerdings ein eigenes Gebiet für sich mit einer Menge Besonderheiten und Fehlerquellen. Z.B. muss die Aktualisierung der Variablen thread-sicher sein.
 
  • [C] fopen() in einer while()-Schleife Beitrag #3
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Was soll ich dann machen? Ich will es möglichst unkompliziert. Mir ist es einfach nur wichtig, dass erstmal irgendetwas da ist, damit ich dann später ins Detail gehen kann. Die fopen-Methode funktioniert ja gar nicht mal so schlecht, solange das ganze außerhalb einer Schleife steht.
 
  • [C] fopen() in einer while()-Schleife Beitrag #4
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Hab ich doch geschrieben; fopen nur einmal aufrufen, bevor du in die Hauptschleife gehst. Damit bleibt der Port geöffnet und du kannst alles der Reihe nach in deiner Schleife einlesen. Beim Beenden machst du den Port mit fclose einfach wieder zu.
Die Methode funktioniert übrigens nicht nur nicht schlecht, sondern wunderbar. Das Problem ist nur die falsche Anwendung derselben. ;)
 
  • [C] fopen() in einer while()-Schleife Beitrag #5
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Der modifizierte Code:
Code:
FILE *port=fopen("/dev/ttyUSB0", "r");
  while (!quit)
    {
      SDL_PollEvent (&e);
      alle_tasten = SDL_GetKeyState (NULL);
	while(i!=14)
	{
	column[i]=fgetc(port);
	printf("%c",column[i]);
	i++;
	}
	x=((int) column[1] - '0') *100+((int)column[2] - '0') *10+((int)column[3] - '0');
	y=((int) column[5] - '0') *100+((int)column[6] - '0') *10+((int)column[7] - '0');
	z=((int) column[9] - '0') *100+((int)column[10] - '0') *10+((int)column[11] - '0');
	val=((int) column[13] - '0');
	printf("\n x==%d y==%d z==%d Button.value==%d\n",x,y,z,val);
        [...]
	fclose(port);

Irgendwie verstehe ich das immer noch nicht.
Es kommt nämlich folgende Fehlermeldung raus:

342 352 416 0
x==342 y==352 z==416 Button.value==0

x==342 y==352 z==416 Button.value==0
Speicherzugriffsfehler
 
Zuletzt bearbeitet:
  • [C] fopen() in einer while()-Schleife Beitrag #6
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Naja, du machst in der Schleife den Port zu und greifst im nächsten Durchlauf drauf zu. Nicht direkt ein Mysterium, dass das nicht klappt. ;)
Darum hab ich ja geschrieben, dass du ihn beim Beenden wieder zumachen sollst...
 
  • [C] fopen() in einer while()-Schleife Beitrag #7
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Also... Ich habe das fopen am Anfang der Hauptschleife und das fclose am Ende. Jetzt gibt es mir wieder die selben Zahlen aus, in jedem Durchlauf ist es
x=340 y=351 z=415 und val=0.
Ich kann den Sensor schütteln wie ich will, nichts passiert.
 
  • [C] fopen() in einer while()-Schleife Beitrag #8
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Dann kommen wohl diese Zahlen vom Controller. Was für ein Teil ist das denn genau - was selber gebasteltes? Stimmen die Einstellungen wie Baudrate usw.? Ansonsten mal mit z.B. Hyperterminal nachsehen, was der Controller sendet.
 
  • [C] fopen() in einer while()-Schleife Beitrag #9
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Das Teil habe ich selbst gebaut - mit einem Arduino Nano 2 (läuft mit der IDE unter "Duemillanove") und einem Beschleunigungssensor und ein paar Kabeln und Widerständen, das Set gibt es für 60-70€ auf Segor electronics.
Baudrate ist 9600.
Mit diesem Programm:
Code:
#include<errno.h>
#include<stdio.h>
#include<string.h>

main()
{
	char *device="/dev/ttyUSB0";
	FILE *port=fopen(device, "r");
	int i=1;
	char column[13];
	column[0]=0;
	while(i!=14)
	{
	column[i]=fgetc(port);
	printf("%c",column[i]);
	i++;
	}
	int x=((int) column[1] - '0') *100+((int)column[2] - '0') *10+((int)column[3] - '0');
	int y=((int) column[5] - '0') *100+((int)column[6] - '0') *10+((int)column[7] - '0');
	int z=((int) column[9] - '0') *100+((int)column[10] - '0') *10+((int)column[11] - '0');
	int val=((int) column[13] - '0');
	printf("\n x==%d y==%d z==%d Button.value==%d\n",x,y,z,val);
}
erfüllt es seinen Zweck, bei Bewegung/drücken des Knopfes erscheint der entsprechende Wert.
Auf meiner XUbuntu-Partition habe ich es mit Processing und einem simplen Clone von Lunar Lander zum Laufen bekommen.
Komischer Tag heute...
 
  • [C] fopen() in einer while()-Schleife Beitrag #10
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Ich habe einen Fehler gefunden, der wohl dafür verantwortlich ist, dass überall die selben Werte kommen:
Das "int i=1;" stand über der Hauptschleife, daher wurde
Code:
while(i!=14)
	{
	column[i]=fgetc(port);
	printf("%c",column[i]);
	i++;
	}
Nur einmal ausgeführt. Nun bekomme ich fast nur noch Störsignale wie
x==-7622
und so. Ich schätze mal, ich muss die Baud-rate ändern, zwar habe ich den Müll schon rausgefiltert, weil aber nur alle 5-6 Durchläufe was gescheites erscheint, bewegt sich die Figur langsamer.
 
  • [C] fopen() in einer while()-Schleife Beitrag #11
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Wenn dein Code noch so aussieht, solltest du dich aber fragen, woher das Minus überhaupt kommen kann. Schließlich verarbeitest du nur einzelne Ziffern und keine Zahlen.
 
  • [C] fopen() in einer while()-Schleife Beitrag #12
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Stimmt. Ich habe 2 verschiedene Ausgaben:
Code:
printf("%c",column[i]);
und
Code:
printf("\n x==%d y==%d z==%d Button.value==%d\n",x,y,z,val);
.
Die erste Ausgabe scheint Fehlerfrei, wenn ich aber column in seine Einzelteile zerlege und ausgebe kommt das Zahlen-Wirrwarr heraus.
Es muss also daran liegen:
Code:
	while(i!=13)
	{
	fscanf(port,"%c",&column[i]); 
	printf("%c",column[i]);
	i++;
	}
	x=((int) column[0] - '0') *100+((int)column[1] - '0') *10+((int)column[2] - '0');
	y=((int) column[4] - '0') *100+((int)column[5] - '0') *10+((int)column[6] - '0');
	z=((int) column[8] - '0') *100+((int)column[9] - '0') *10+((int)column[10] - '0');
	val=((int) column[12] - '0');
Ich schätze mal, dass diese Art von Typ-Konvertierung nicht die feine englische Art ist.
 
  • [C] fopen() in einer while()-Schleife Beitrag #13
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Versuch mal, um die column[...] - '0' - Terme eine runde Klammer herum zu setzten, damit der Cast auf int auf das Ergebnis angewendet wird. So gilt der nämlich nur für für das column[...].
Außerdem würde ich column[] als unsigned char deklarieren.
 
  • [C] fopen() in einer while()-Schleife Beitrag #14
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
column[] ist jetzt unsigned, um die 4 Terme sind Klammern gesetzt. Jetzt hängt das Spiel komplett. Mit der -Wall Option bekomme ich nichts heraus. Dummerweise hängt es sich auf, bevor ein log erscheint. Ich schätze mal, dass es am fscanf liegt, zuvor habe ich fgetc benutzt.
 
  • [C] fopen() in einer while()-Schleife Beitrag #15
cmddegi

cmddegi

Bekanntes Mitglied
Dabei seit
12.07.2001
Beiträge
4.740
Reaktionspunkte
0
Ort
Austria
Ich dachte, das hat schon funktioniert, so wie du es gepostet hast?!
 
  • [C] fopen() in einer while()-Schleife Beitrag #16
Cheddar

Cheddar

Bekanntes Mitglied
Dabei seit
05.04.2009
Beiträge
453
Reaktionspunkte
0
Ort
Cheddar (Somerset)
Ich habe nochmal den Ursprünglichen Code kompiliert - trotzdem stürzt es ab.
Es liegt wahrscheinlich an der Programmierung des Arduino.
 
Thema:

[C] fopen() in einer while()-Schleife

ANGEBOTE & SPONSOREN

https://www.mofapower.de/

Statistik des Forums

Themen
213.179
Beiträge
1.579.172
Mitglieder
55.878
Neuestes Mitglied
Satan666
Oben