Von C++ über die serielle Schnittstelle nach Objective-C & Cocoa, oder so ähnlich...

F

firehenry

Registriert
Thread Starter
Dabei seit
28.04.2008
Beiträge
4
Reaktionspunkte
0
Glück auf!

Mangels bezahlbarer Mac-Anwendungen für die Messtechnik versuche ich nun selbst den Start in die Programmierung solcher Anwendungen.
Mit C++ komme ich eigentlich ganz gut klar. Und da bei Unix alles eine Datei ist, vereinfacht sich das Ganze für mich auch.
Schnell konnte ich mit einem einfachen Konsolen-Progrämmchen mein Speicheroszilloskop (DSO) dazu überreden mit dem Mac zu kommunizieren.
(Codeschnipse anbei)
Das ganze ist wie folgt aufgebaut:
DSO -> USB-Seriell-Adapter -> Mac
Soweit so gut. Nun kriege ich aber die Kurve nicht in Richtung einer Cocoa-Anwendung die eigentlich nur das gleiche machen soll, allerdings eben in einem Fenster.
Die Header-Dateien kennt Xcode nicht, wenn ich eine Cocoa-Anwendung schreiben möchte. Und die ganze Sache mit "open,read,write" zu gestalten, ist mir bis jetzt noch nicht gelungen.
Wer könnte mir aus meinem Code-Schnipsel hier eine kleine Cocoa-Anwendung schreiben und kommentieren, sodass ich endlich mal ein Erfolgserlebnis in dieser Sache habe kann?

Beste Grüße
Henry
---
Code:
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
   	char SerielleSchnittstelle[28] = "/dev/tty.usbserial-FTBTCM8J";		// Der Pfad der seriellen Schnittstelle.
   	int Zaehler = 0;				// Das digitale Speicheroszilloskop (DSO) gibt 12 Zeichen zurück. Danach soll Schluss sein.
   	cout <<  "digitales Speicheroszilloskop: " << SerielleSchnittstelle << "\n";	// Als erste Ausgabe für die Konsole (nur so).
   	ofstream fout(SerielleSchnittstelle);		// öffnet die serielle Schnittstelle zum schreiben
   	ifstream fin(SerielleSchnittstelle);		// öffnet die serielle Schnittstelle zum lesen      
	fout <<"V3\n";					// Dem DSO sagen, es soll die gemessene Spannung ausgeben. Befehl V3 und LF
	fout.close();					// Es braucht nicht mehr in die serielle Schnittstelle geschrieben werden, also zumachen.
	char ch;
	while (Zaehler < 12)		 	// Schleife zum Einlesen der gemessenen Spannung.
	{
		fin.get(ch);			// Das übermittelte Zeichen vom DSO auslesen.
		cout << ch;			// Das vom DSO übermittelte Zeichen auf der Konsole ausgeben.
		Zaehler++;			// Zähler einen hochsetzen.
	}
  	fin.close();				// Lesen der seriellen Schnittstelle beenden.
	return 0;
}

Die Ausgabe sieht dann in der Xcode-Konsole wie folgt aus:

[Session started at 2008-04-28 19:14:21 +0200.]
digitales Speicheroszilloskop: /dev/tty.usbserial-FTBTCM8J
023.3mV DV
The Debugger has exited with status 0.
 
Welche Header kennt Xcode nicht?

Du solltest die Dateien entweder .mm oder .cpp nennen.

Alex
 
Wenn ich über File -> New Project -> Core Data Application ein neues Projekt erstelle, dann ist <iostream> und <fstream> Xcode nicht bekannt.
Bild1.png

Ich seh' schon. Der Umstieg ist nicht so einfach. Und das Buch Ojective-C und Cocoa verwirrt mich eher...
 
Wenn ich über File -> New Project -> Core Data Application ein neues Projekt erstelle, dann ist <iostream> und <fstream> Xcode nicht bekannt.

Ja. Weil die Dateien als Objective-C übersetzt werden.

Sie müssen aber als "Objective-C++" übersetzt werden. Das kannst Du:

* Global für das Projekt/Target einstellen
* Individuell für die Datei einstellen
* Oder die Datei einfach ".mm" nennen. An dieser Endung erkennt Xcode Objective-C++ Dateien.

Alex
 
* Oder die Datei einfach ".mm" nennen. An dieser Endung erkennt Xcode Objective-C++ Dateien.

Genau das war's. Tausend Dank! So komm ich endlich hier weiter. :D
 
und kannst du dein erfolgreiches Beispiel posten?

ich habe auch ein Prog in c++ - Terminal geschrieben, das eine GPS maus ausliest.

der Umstieg auf Cocoa fällt mir jedoch enorm schwer. gibts da kein Beispiel oder leichte Einführungen?
 
Hi,

wenn Cocoa für Euch so fremd ist, würde ich empfehlen, erstmal die Schritt-für-Schritt-Tutorials von Apple durchzugehen und nicht versuchen, Eure spezifischen Programme in einem Mix aus C/C++ und Objective-C "herbeizuhacken".

Denn wenn Ihr einmal warm geworden seid mit Obj-C und Cocoa, ist das Umsetzen mittels des Stream Programming Guide for Cocoa ein Leichtes.

Um ein richtiges Cocoa-Programm draus zu machen, bietet es sich wohl eher an, die Cocoa-Klassen zu nehmen anstatt der iostream c++ Klassen, denn dann könnt ihr die Brücken in die restliche Cocoa-Welt problemlos nutzen (NSData, NSString, von da aus ins GUI usw.).

Bei Fragen einfach hier posten oder PN senden.

Beste Grüße, SMJ
 
Zuletzt bearbeitet:
Hallo Silence7!

Bin Momentan noch nicht viel weiter gekommen. Rätsel grade noch, wie ich aus einer Aktionsgesteuerten Abfrage (Button drücken) eine kontinuierliche Abfrage (Zeitintervalle) der Schnittstelle machen...

Hier meine Controller.mm

Code:
#import "ControllerHenry.h"
#import <iostream>
#import <fstream>
#import <string>

using namespace std;
using std::string;

@implementation ControllerHenry

- (IBAction)DMMumschalten:(id)sender
{
	cout <<  "DMM-Betrieb\n";
	char SerielleSchnittstelle[28] = "/dev/tty.usbserial-FTBTCM8J";
	ofstream fout(SerielleSchnittstelle);			
	fout <<"F2\n";	
	fout.close();	
}
- (IBAction)LGAumschalten:(id)sender
{
	cout <<  "LGA-Betrieb\n";
	char SerielleSchnittstelle[28] = "/dev/tty.usbserial-FTBTCM8J";
	ofstream fout(SerielleSchnittstelle);			
	fout <<"F1\n";	
	fout.close();	
}
- (IBAction)DSOumschalten:(id)sender
{
	cout <<  "DSO-Betrieb\n";
	char SerielleSchnittstelle[28] = "/dev/tty.usbserial-FTBTCM8J";
	ofstream fout(SerielleSchnittstelle);			
	fout <<"F0\n";	
	fout.close();	
}
- (IBAction)SpannungAnzeigen:(id)sender
{
	// DMM des DSO auslesen
	char SerielleSchnittstelle[28] = "/dev/tty.usbserial-FTBTCM8J";			// Der Pfad der seriellen Schnittstelle.
	string Puffer;			// Puffer für die Ausgabe der Spannung an das Fenster (#import <string>)
	int Zaehler = 0;		
   	ofstream fout(SerielleSchnittstelle);		// öffnet die serielle Schnittstelle zum schreiben
   	ifstream fin(SerielleSchnittstelle);		// öffnet die serielle Schnittstelle zum lesen 
	fout <<"V3\n";				// Dem DSO sagen, es soll die gemessene Spannung ausgeben. Befehl V3 und LF
	fout.close();				// Es braucht nicht mehr in die serielle Schnittstelle geschrieben werden, also zumachen.
	char ch;
	while (Zaehler < 12)		 	// Schleife zum Einlesen der gemessenen Spannung.
	{
		fin.get(ch);			// Das übermittelte Zeichen vom DSO auslesen.
		Puffer = Puffer + ch;		// das übermittelte Zeichen in den Puffer schreiben
		Zaehler++;			// Zähler einen hochsetzen.
	}
	fin.close();				// Lesen der seriellen Schnittstelle beenden.
	// Puffer Auswerten
	
	// Rückgabe an das GUI
	NSString *DMMPuffer;		// NSString definieren
	DMMPuffer = (NSString*)CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)Puffer.c_str(), Puffer.size(), kCFStringEncodingUTF8,false);	 // std::string in NSString konvertieren
	[Spannungsausgabe setStringValue:DMMPuffer];	// Spannung in das "Spannungsausgabefenster" schreiben.
}
@end

Und meine Controller.h
Code:
/* ControllerHenry */

#import <Cocoa/Cocoa.h>

@interface ControllerHenry : NSObject
{
    IBOutlet NSTextField *Spannungsausgabe;
}
- (IBAction)DMMumschalten:(id)sender;
- (IBAction)DSOumschalten:(id)sender;
- (IBAction)LGAumschalten:(id)sender;
- (IBAction)SpannungAnzeigen:(id)sender;
@end

@SumpfMonsterJun
Das hab ich bereits versucht, finde aber so keine Motivation in die "Mac"-Programmierung einzusteigen.
Ich arbeite lieber nach dem "Problem-Lösung"-System, sofern es so etwas gibt. ;)
 
Hi,

schau mal die Doku von NSTimer an:

http://developer.apple.com/document.../Classes/NSTimer_Class/Reference/NSTimer.html

Kann gut verstehen, dass der "Problem-Lösung"-Ansatz motivierender ist, man hat schneller Erfolgserlebnisse.

Der "richtig-einarbeiten-anhand-von-Appledoku" Weg ist sicher erstmal mühsamer, aber die Ergebnisse sind hinterher "sauberer" (Benutzung der Cocoa-Patterns).

Weiterhin viel Spaß beim Erforschen,

Beste Grüße, SMJ
 
Zuletzt bearbeitet:
Moin

sorry für die lange Pause aber hatte viel um die Ohren. will mich jetzt wieder dem Thema widmen und hab heute morgen ein bissel rumprobiert.

der code funktioniert... es lebe der Debugger :D

jemand was zum NSTimer gefunden?

Code:
#import "gps.h"
#import <iostream>
#import <fstream>
#import <string>

using namespace std;
using std::string;

@implementation gps
- (IBAction)read:(id)sender {
	
	char SerielleSchnittstelle[28] = "/dev/tty.BTGPS-SPPslave-1";			// Der Pfad der seriellen Schnittstelle.
	string Puffer;		
	string speed;
	string speedaverage;
	char String[1510];	
	int Start[100];
	Start[1]=0;
	char ch;
	
	int Zaehler = 1;
	int Zeile =1;
	int i = 1;
    int countn=0;
	int foundspeed =0;
	int Ende = 0;
	
	ifstream fin(SerielleSchnittstelle);		// öffnet die serielle Schnittstelle zum lesen 
	
	while (i < 1500 && Ende == 0)		 	// Schleife zum Einlesen der gemessenen Spannung.
	{
	fin.get(ch);			// Das übermittelte Zeichen vom DSO auslesen.
	i++;
		
		if (ch == '$')		// Finde erste ganze Zeile!
		{
		Zeile=Zeile+1;
		Start[Zeile]=Zaehler;
		}
		
		if (Zeile != 0)		// Hauptfunktion
		{
		String[Zaehler]=ch; // Sammel Zeichen
		Zaehler++;			// Zähler einen hochsetzen.
	
			if (Zeile > 1 && ch == '$')	// Eine Zeile Voll!
			{		
				//Untersuchung starten!!
				if ( String[Start[Zeile-1]] == '$' && 	String[Start[Zeile-1]+1] == 'G' && 	String[Start[Zeile-1]+2]== 'P' && 	String[Start[Zeile-1]+3] == 'V' && 	String[Start[Zeile-1]+4] == 'T' && 	String[Start[Zeile-1]+5] == 'G')
				{
					countn=0;
					
					for (i=Start[Zeile-1]+6; i < Zaehler;)
					{
						if (String[i] == ',')
						{
							countn = countn+1;
						}
						i=i+1;
						
						if( countn == 7)
						{							
							while (String[i] != ',')
							{
								Puffer = Puffer + String[i];
								i=i+1;
							}
							
							Ende = 1;
							countn=0;
							foundspeed=1;
							
						} // Ende Speed
					
					}// Ende Komma
				} //Ende String	 
			}//Ende Suche
		} //Ende Start
		
	} // While
	
	fin.close();				// Lesen der seriellen Schnittstelle beenden.
	NSString *DMMPuffer;
	DMMPuffer = (NSString*)CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)Puffer.c_str(), Puffer.size(), kCFStringEncodingUTF8,false);	 // std::string in NSString konvertieren
	[Disp1 setStringValue:DMMPuffer];
	[Disp2 setIntValue:Zeile];
	[Disp3 setIntValue:foundspeed];
	i=0;
	Ende=0;
	foundspeed=0;
	countn=0;
}

- (IBAction)stop:(id)sender {
	[Disp1 setIntValue:0];
	[Disp2 setIntValue:0];
	[Disp3 setIntValue:0];
	[Disp4 setIntValue:0];
}
@end
 
Zuletzt bearbeitet:
noch zur Erklärung

meine Zeilen sehen so aus:

$GPVTG.......
$Gxxxx.......

daraus suche ich mir die passende Zeile und Filter raus was ich brauche... funktioniert perfekt im Terminal nur hier noch net so...

P.S.: jemand was zum NSTimer gefunden?
 
Zuletzt bearbeitet:
Zurück
Oben Unten