Datenaustausch mit einem Mikrocontroller



  • Hallo,

    ich möchte mit meinem Mikrocontrollerboard (Arduino) zwei Variablen an meinen PC senden via serielle Schnittstelle. Diese werden dann dort verarbeitet und der Rückgabewert soll dann wieder auf der seriellen Schnittstelle landen und vom Mikrocontrollerboard empfangen werden.

    Den Code für mein MC-Board habe ich schon fertig:

    float ergebnis;
    //float ergebnis = 0.0;
    int wert1;						//Regeldifferenz, ist e ein Integerwert oder float?
    int wert2;						//Regelldifferenz über die Zeit
    
    void setup() {					//SETUP
    
      Serial.begin(9600);
     // pinMode(ledPin, OUTPUT);
    
    }
    
    void loop() {					//Programmschleife
    
      Serial.print('@'); 			// sende Startzeichen			
      Serial.print(","); 			// sende Zeichen Feldtrennung
      Serial.print(wert1);
      Serial.print(",");			
      Serial.print(wert2);
      Serial.print(",\n");			// neue Zeile, Ende Uebertragung
      Serial.flush(); 				// wartet bis alles uebertragen ist!
    
      if (Serial.available() > 0)  	//wenn sich Daten auf der seriellen Schnittstelle befinden 
      {
    	float ergebnis = Serial1.parseFloat(); //suche nächsten Float-Wert
    	delay(1000);				// warte 1 Sek.
    	Serial.write(ergebnis); 	//schreibe den empfangenen Wert wieder auf die Schnittstelle 
    	lcd.print(ergebnis); 		//schreibe den empfangenen ergebnis auf das LCD Display
      }
    }
    

    Die passende Windows.exe dazu möchte ich mit DevCpp erstellen. Doch wie sieht der passende Code dazu aus, um die beiden Integer-Variablen von der seriellen Schnittstelle auszulesen und das Ergebnis dort wieder hinzuschreiben?
    Den Code für die Verarbeitung der beiden Werte habe ich bereits erfolgreich in mein DevCpp Projekt eingebunden und getestet.

    Leider finde ich bei Google kein passendes Beispiel dafür.
    Ich habe lediglich gelesen, dass ich die windows.h inkludieren muss.

    Danke.

    LG Dennis



  • Servus
    Der erste Treffer bei google: http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c5425/Serial-Communication-in-Windows.htm

    Im Grunde ist COM-Port lesen wie Datei lesen, Beim öffnen musst du nur den "richtigen" Dateinamen angeben. Einzig was ich schade finde, habe noch kein Beispiel mit Filetsteaks gefunden.

    MfG mdn



  • Danke, das hat mir sehr geholfen habe den Code jetzt am laufen und er schreibt mir auch auf die serielle Schnittstelle.

    In der Konsole passt der Wert, doch auf der seriellen Schnittstelle sagt er immer dieser sei 0.0000:

    long stell;
    DOUBLE **outputMatrix;
    
    PRINTF("Stellwert = %.12f", stell);  //das funktioniert, hier wird der richtige Wert angezeigt
    
    file = fopen("COM4:","w");
    fprintf(file,"%.12f", stell); //hier wird nur 0.000000000 angezeigt
    fprintf(file,"\nDaten erfolgreich gesendet..."); //das funktioniert
    fclose(file);
    

    Ich habe es schon mit %d, %i und sprintf probiert. Aber er zeigt mir einfach den Wert nicht an. Woran mag das liegen?

    LG



  • Hallo

    Du solltest deine Datentypen auch aufeinander abstimmen, am Microcontroller verschickst du float und am Pc Long, ist das so gewollt?

    Und wenn ja, dann mit %lu (Unsigned Long) bzw %ld (signed Long).

    MfG mdn



  • Habe ich gerade probiert. Funktioniert leider nicht.

    Ich habe auch versucht den float in eine Integer Wert zu konvertieren. Der Wert den er dann aber auf die Schnittstelle schreibt bleibt 0.

    Wenn ich den selben wert dann aber über

    PRINTF("Stellwert = %.12f", stell)
    

    ausgebe funktioniert es

    genauso mit:

    PRINTF("Stellwert = %.0f", stell)  //Kommastellen abgeschnitten
    

    gehe ich aber her und gebe einen von mir angelegte Integer Variable aus z.B.

    int a = 12;
    

    und sage dann

    fprintf(file,"%i", a);
    

    funktioniert das einwandfrei. Die Zahl 12 wird dann auf der seriellen Schnittstelle richtig ausgegeben.

    Hat das vielleicht was damit zu tun, dass

    stell = outputMatrix[i][j];

    ist? nur warum zeigt er es dann mit printf richtig an und mit fprintf nicht?
    Muss ich eine andere Funktion dafür verwenden? Habe jetzt auch alle Formatierungen mal ausprobiert: %d, %i, %f, %lu, %ld, %c etc.

    LG



  • Hallo

    Geb doch bitte mal ein komplett kompilierbares Beispiel an, sonst ist es aktuell nur ein Ratespiel dir zu helfen.

    Aber nochmal, die Datentypen deiner Werte passen einfach nicht zusammen, wenn deine Werte Gleitkommazahlen sind, dann sollte die Variable "stell" auch vom Typ double/float sein und nicht vom Typ long. Eine Zuweisung einer Gleitkommazahl nach Long sollte dir dein Compiler auch schon als Warnung ausgeben.

    Und was ist eigentlich die Funktion "PRINTF"? Ist das ein Makro oder eine selbst geschriebene Funktion?

    Und welche Formatierung du benutzt musst, kommt auf den Typ der Variable an, die du ausgeben willst. Formatierung zum Datentyp-Tabelle siehe hier

    MfG mdn



  • Hallo,

    ich habe Dir die Dateien mal in eine ZIP-Datei zusammengepackt:

    http://www.file-upload.net/download-9509213/fuzzy0.zip.html

    PRINTF ist eine Standardfunktion für die Ausgabe auf der Eingabeaufforderung.

    Die Datentabelle kenne ich und mit diesen Werten habe ich auch mal gespielt und auch die Datentypen angepasst.

    LG



  • Hallo,

    falls das Codeproject-Beispiel Probleme bereitet, kann ich nur die com-Toolbox
    von Anton Zechner (http://members.inode.at/anton.zechner/az/ ) empfehlen:

    tp://members.inode.at/anton.zechner/az/ComTools.zip

    Da ist alles drinnen was man braucht.

    MfG



  • Hallo

    @7x7-7: Das schaut sehr interessant aus.

    @Dennis2014: Dein Beispiel kann ich leider nicht laden, da die Website mir statt deiner ZIP-Datei eine EXE-Datei zum Downloaden anbietet. Könntest du die relevanten Teile nicht einfach hier in Code-Tags posten.

    Und wegen der frage zu PRINTF, C++ ist CaseSensitive und ich kenne nur eine printf-Funktion und wie man sieht wird die anders geschrieben.

    MfG mdn



  • Hallo,

    Das Code-Beispiel von Anton Zechner ist jedoch in C++ geschrieben und funktioniert sehr gut. Leider ist der Fuzzy Regler in C geschrieben und wenn ich diese C Datei dann in das C++ Projekt icludiere meckert der Compiler.

    Ich lade die ZIP gleich hier nochmal hoch.

    LG



  • Die zip-Datei ist in Ordnung. Aber file-upload.net macht blöde Werbung die wie Download-Buttons aussehen... wenn man keinen Ad-Blocker hat.

    Das ganze nutzt MathWorks und PRINTF ist halt je nach dem, was gebaut wird, eine andere Ausgabe. 😉

    Zu dem Code und der Ausgabe... was gibt der Code, den du hochgeladen hast genau aus? Und was erwartest du, das ausgegeben wird?

    Edit:
    Die Schleife in Zeile 113 sieht so aus, als wenn du die Klammern vergessen hast.
    In Zeile 139 verwendest du einen falschen Index, du meinst z .
    Die Zeilen aus deinem zweiten Post kommen so nirgends vor. (Versuch mal zu schauen, was in stell steht.)
    In Windows ist es eventuell ratsam die Datei im binären Modus zu öffnen.





  • Hallo

    So konnte den Code nun auch herunterladen.

    Wie schon angemerkt, könnte es sein das du bei Z113 die Klammern vergessen hast. Wenn das Absicht ist, dann ist der Wert von "stell" undefiniert, da du bei Z118 über dein Array hinaus liest (j == fis->out_n).

    Z117 ist hoffentlich immer auskommentiert, sonst überschreibst du dir die äußere Variable und die behält dann den Original-Wert.

    Geb doch mal zum testen, den Wert von "stell" direkt in Z152 aus, nur dort weißt du dann wirklich welcher Wert in deiner Variable steht.

    MfG mdn



  • Der Code gibt einen Double Kommawert aus zwischen 0 und 255.

    Mir reicht aber auch ein Integerwert von 0-255. Wenn ich einen reinen Integerwert habe, dann kann ich den auch ohne Probleme mit fprintf auf die Schnittstelle schreiben, so dass er auch richtig angezeigt wird.

    Somit muss wahrscheinlich nur noch der bisherigr double (float) Wert aus der outputMatrix [i][j] in einen Integerwert von 0-255 umgewandelt werden. Dann sollte es laufen denn:

    DOUBLE **outputMatrix;
    stell = outputMatrix [i][j];
    


  • Ja das stimmt wohl soweit, aber deine Zuweisung

    stell = outputMatrix[i][j]
    

    ist aktuell an einer Stelle, bei der du dir nicht sicher sein kannst, welcher Wert herauskommt. (Array Überschreitung)

    Hast du jetzt schon mal den Wert an Zeile 152 ausgegeben?

    MfG mdn



  • Ja habe ich gerade gemacht. Wenn ich den stell Wert in Zeile 152 ausgebe ist er 0

    152: PRINTF("Stellwert = %.12f \n\n, stell);
    


  • Bis Zeile 125 kann ich ihn ausgeben. Danach nicht mehr. Aber auch nur mit %.0f oder %.12f mit %i ist er auch da Null.



  • Hast du es schon mal probiert, wenn du Zeile 118 wie folgt abänderst:

    stell = (int)outputMatrix[i][j]
    

    Und nochmal, deine Zugriff auf die outputMatrix[i][j] ist bei deinem letzten Schleifendurchlauf außerhalb des Arrays, da j > als dein höchstes Element ist.

    Zum testen könntest du noch die Variable "stell" statt mit einem Wert aus der Matrix, mit einem konstanten Wert auf Zeile 118 belegen, somit würdest du sehen ob es rein die Zuweisung ist oder du deine Variable mehrfach deklarierst und sie durch verlassen des Scopes entfernt wird.

    Könntest du auch bitte mal eine Ausgabe deiner Software hier posten, dann könnte man dies mit deinem Code vergleichen.

    MfG mdn



  • also wenn ich in der Zeile 128 die Variable stell auf 8.17 setze und dann weiter unten über fprintf %i ausgebe, gibt er mir auf der seriellen Schnittstelle nur die 8 aus.

    Wenn ich hingegen stell als int stell = 8.17; oberhalb von main deklariere und dann stell mit fprintf %f auf die serielle Schnittstelle schreibe, schreibt er 0.0000

    Wenn ich aber in der Zeile 127 stell = 8.18; schreibe, gibt er auf der seriellen Schnittstelle 8.180000 aus.

    Also kann er scheinbar den double Rückgabewert von outputMatrix nicht über fprintf ausgeben.

    Gibt es nicht eventuell eine Möglichkeit die letzte ausgegebene Zeile auf der Eingabeaufforderung wieder einzulesen in eine int Variable, denn da stellt er den Wert aus der outputMatrix ja richtig da?!

    auch mit

    stell = (int)outputMatrix[i][j]
    

    funktioniert es nicht



  • Servus

    So hab mir die arbeit gemacht und dein Programm übersetzt und debugged, und wie ich dir schon mal angemerkt habe, greifst du aus dem Array raus, hier mal einen Version, mit der es funktioniert:

    /* print output vector */
    	for (i = 0; i < data_row_n; i++) {
    		for (j = 0; j < fis->out_n; j++)
    			PRINTF("stellwert = %.12f", outputMatrix[i][j]);
    		PRINTF("\n");
    		stell = (int)outputMatrix[i][j-1]; // Hier -1 da j = fis->out_n ist und damit man rausgreifen wuerde
    		PRINTF("Stellwert = %i \n\n", stell);
    	}
    

    Mit dem Code-Schnippsel bekomm ich folgende Ausgabe:

    Starte Fuzzy Logic...
    
    Oeffne COM-Port: 4...
    
    stellwert = 85.008714548229
    Stellwert = 85
    

    MfG Mdn


Log in to reply