Datenerfassung über 2 RS232 Schnittstellen



  • markus.z84 schrieb:

    Habe für jede Com einen Thread gemacht und erhalte auch die übertragenen Werte.

    In deinem Post kann ich das nicht erkennen. Wie initialisierst du die Threads und vor allem wo und wo steht der von dir gepostete Code?
    Ich denke, dass der Fehler nicht in dem von dir geposteten Code steht sondern das Problem mit der Threadsynchro zu tun hat. Aber das sagte ich ja bereits.



  • Steh zur Zeit sehr auf der Leitung, aber hoffe dass ich jetzt den "richtigen" Code poste.

    Wird eine der Zwei Coms ausgewählt, dann wird die Funktion Open aufgerufen.
    In dieser werden zuerst die Einstellungen für die jeweilige Schnittstelle übernommen und dann der Thread gestartet. Mit dem Thread wird zuvor nichts gemacht!!!

    Open ( CString sPortName, 
    					   DWORD dwBaudRate, 
    					   BYTE bDataBits, 
    			           BYTE stopbit, 
    					   BYTE parity, 
    					   BYTE fc,
    					   int Portselect )
    {
    	if ( IsOpen() ) return FALSE;
    
    	CString sPort = _T("\\\\.\\");
    	sPort += sPortName;
    	m_hComm = CreateFile( sPort,
                        GENERIC_READ | GENERIC_WRITE,
                        0,    // must be opened with exclusive-access
                        NULL, // no security attributes
                        OPEN_EXISTING, // must use OPEN_EXISTING
                        FILE_FLAG_OVERLAPPED, 
                        NULL  // hTemplate must be NULL for comm devices
                        );
    
    	TRACE ( _T("Error: %d\n"), GetLastError() );
    
       if (m_hComm == INVALID_HANDLE_VALUE) 
       {
    		TRACE  (_T("CreateFile failed with error %d.\n"), GetLastError());		
    
    		CloseHandle( m_hComm );
    		m_hComm = INVALID_HANDLE_VALUE;
    	    return FALSE;
       }
    
       // reconfigure port 
       DCB dcb; 
       BOOL fSuccess = GetCommState(m_hComm, &dcb);
    
       if (!fSuccess) 
       {
          TRACE (_T("GetCommState failed with error %d.\n"), GetLastError());
    
    	  CloseHandle( m_hComm );
    	  m_hComm = INVALID_HANDLE_VALUE;
          return FALSE;
       }
    
       dcb.BaudRate = dwBaudRate;  
       dcb.ByteSize = bDataBits;
       dcb.Parity   = parity;
    
    .
    .
    Hier werden die Einstellungen vorgenommen
    .
    .  
    
       // Install new adjustment
       fSuccess = SetCommState(m_hComm, &dcb);
       if (!fSuccess) 
       {
          TRACE (_T("SetCommState failed with error %d.\n"), GetLastError());
    
    	  CloseHandle( m_hComm );
    	  m_hComm = INVALID_HANDLE_VALUE;
          return FALSE;
       }
    
       // launch comm event handler
    
       DWORD dwId; 
       m_hThread = CreateThread( NULL, 0, EventHandler, (LPVOID)this, CREATE_SUSPENDED, &dwId );
       }
    
       if ( m_hThread != NULL )
       {
    	  m_hEventTerminate = CreateEvent( NULL, FALSE, FALSE, _T("OnStopThread") );
    	  lReqTerminate = 1; 
    	  ResumeThread( m_hThread );
       }
       else 
       {
    	  CloseHandle( m_hComm ); 
    	  m_hComm = INVALID_HANDLE_VALUE;
    	  return FALSE;
       }
    
       return TRUE;
    }
    

    Dieser Code befindet sich in einer Datei, die ich im Inernet gefunden habe, sie ist mit der Datei serial.cpp zu vergleichen jedoch ausführlicher !!

    Ich hoffe dass du nun mehr erkennen kannst!! Bin mir jedoch überhaupt nicht sicher......
    Weis zur Zeit nicht weiter !!!



  • Du hattest doch in deinem ersten Post geschrieben, dass du 2xRS232 verwendest und du hast für jede Schnittstelle einen Thread. Wie meinst du jetzt

    markus.z84 schrieb:

    Steh zur Zeit sehr auf der Leitung, aber hoffe dass ich jetzt den "richtigen" Code poste.

    Wird eine der Zwei Coms ausgewählt, dann wird die Funktion Open aufgerufen.
    In dieser werden zuerst die Einstellungen für die jeweilige Schnittstelle übernommen und dann der Thread gestartet. Mit dem Thread wird zuvor nichts gemacht!!!

    Dieser Code befindet sich in einer Datei, die ich im Inernet gefunden habe, sie ist mit der Datei serial.cpp zu vergleichen jedoch ausführlicher !!

    Ich hoffe dass du nun mehr erkennen kannst!! Bin mir jedoch überhaupt nicht sicher......
    Weis zur Zeit nicht weiter !!!

    Ich bin davon ausgegangen, dass beide COM-Ports initialisiert werden damit du auf die RS485 lesend und schreibend zugreifen kannst. Außerdem wollte ich wissen innerhalb welcher Klasse oder Memberfunktion dieser Code steht. hast du jetzt immer nur einen Thread aktiv? Dann hab ich das ganze irgendwie nicht verstanden... 😕



  • Hab nun das problem fast gelöst!!

    Verwende 2 Coms jedoch nur zum lesen der Daten. Eine Com verwende ich für die RxD und die zweite für die TxD Leitung des Busses.

    Für die einzelnen Schnittstellen wird ein Thread gemacht der immer weiterläuft sobald ich etwas am Port einlese. Also ist immer nur einer aktiv.

    Ich verwende eine andere Software die als Master Daten an einen Slave im RS485 Busses sendet. Der Slave antwortet auch.

    Nun habe ich erkannt, dass die Software immer Daten sendet und nicht wartet bis der Slave antwortet oder die Antwort nicht kontrolliert ob sie für diesen Befehl oder fü einen anderen war. (Zeitproblem)

    Bin der Meinung, dass durch dieses Verhalten der SW mein Programm die Probleme erhalten hat ! Jedoch werde ich noch einige Test machen um sicher zu gehen dass das das Problem war !!

    Danke trotzdem



  • hatte gedacht ich habe das Problem gelöst, jedoch lag ich da falsch!!

    habe nun die TxD und die RxD leitung des Busses mittels Diode auf nur EINE COM angehängt und erhalte immer eine Anfrage vom Master und kurze Zeit später die Antwort des SLAVES. (immer in richtiger reihenfolge)

    Werden nun die beiden Leitungen über 2 verschiedene COM-Schnittstellen zum PC geführt erhalte ich des öfteren 3 Anfragen von verschiedenen Mastern und dann eine Antwort.
    Es sieht so aus, als würde die Antwort zu spät kommen und ein neuer Befehl schon geschickt werden. Jedoch kann dies nicht sein, da der Master erst den nächsten Befehl schickt, wenn er die Antwort erhalten hat.

    Schätze habe ein Problem bei der Thread synkronisation.......
    Finde jedoch nichts! Die darüber angeführten Codebeispiele müssten helfen..

    lg



  • also, wenn immer nur EIN Thread aktiv ist, ist es denn sinnvoll ZWEI Thread zu haben.. schein elegant aber vll. zu unsicher wegen der syncro...

    kansnt du nich nicht EIN Thread machen, welcher beide Com port unterhält? so wie ich gelesen habe, schickst du bspw. mit Com1 ein Anfragebzw. Commando, und mit Com2 wartest du auf die antwort oder? Solange com2 auf die antwort wartet, kann com1 auch kleine "neue" Anfgrage schicken odeR? bin ich richtig?



  • also, wenn immer nur EIN Thread aktiv ist, ist es denn sinnvoll ZWEI Thread zu haben.. schein elegant aber vll. zu unsicher wegen der syncro...

    kansnt du nich nicht EIN Thread machen, welcher beide Com port unterhält? so wie ich gelesen habe, schickst du bspw. mit Com1 ein Anfragebzw. Commando, und mit Com2 wartest du auf die antwort oder? Solange com2 auf die antwort wartet, kann com1 auch kleine "neue" Anfgrage schicken odeR? bin ich richtig?



  • BorisDieKlinge schrieb:

    also, wenn immer nur EIN Thread aktiv ist, ist es denn sinnvoll ZWEI Thread zu haben.. schein elegant aber vll. zu unsicher wegen der syncro...

    kansnt du nich nicht EIN Thread machen, welcher beide Com port unterhält? so wie ich gelesen habe, schickst du bspw. mit Com1 ein Anfragebzw. Commando, und mit Com2 wartest du auf die antwort oder? Solange com2 auf die antwort wartet, kann com1 auch kleine "neue" Anfgrage schicken odeR? bin ich richtig?

    Unter Umständen ist das schon sinnvoll. Aber er hat ja sogar 3 Threads, du hast den GUI-Thread vergessen. Was die Synchronisierung angeht: erstens müssen sich die beiden Workerthreads untereinander synchronisieren. Da man hier auf das Abarbeiten von Ereignissen wartet wäre es hier sinnvoll mit Events zu arbeiten. Zweitens müssen sich die beiden Worker-Threads noch mit dem GUI- oder Mainthread synchronisieren. Da es sich hier meist um die "gemeinsame" Nutzung von Variablen handelt, sind hier CriticalSections nicht ganz verkehrt. Das alles scheint ja auch umgesetzt worden sein, aber irgendwo funktionierts nicht ganz so. Ich verwende CriticalSections immer über

    CSingleLock locked(&m_criticalsection, TRUE);
    

    Dann hat man nicht den Stress mit Enter und Leave und die Aufräumarbeiten erledigt das CSingleLock-Objekt selbst. Ebenfalls arbeite ich nicht mit CreateThread; bisher hat das alles immer mit AfxBeginThread funktioniert. Dies hat aber keinen Einfluss auf die Synchro, um die muss man sich nach wie vor kümmern. Die Events hab ich immer als Member einer Klasse verwendet und diese dann mit SetEvent oder ResetEvent gesetzt oder wieder rückgesetzt.



  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • ja klar, das es ein mainthread gibts ist klar^^ aber zwei trhead syncornisieren ist besser als 3 ... und 2 thread zu verwenden für Com 1 +2 ist nicht unbedingt "sicher"...

    Pseudo:

    DWORD ThreadFunc (LPPARAM *p Data){
    
     while(1){
    
        //hier Warten bis Com1 ein commando schickt (singleobject)
    
        while(1){
    
         //Com2 auf daten warten lassen und lesen, wenn fertig aus schleife springen
    
        }
    
     }
    
    }
    


  • Was soll den der Quatsch? Ob ich nun einen oder zwei Threads synchronisiere ist glaub ich nicht der Mega-Aufwand, wenn man es konsequent durchzieht. Solche Konstrukte wie du da grad gepostet hast sind totaler Käse, weil du ja nicht weißt an welcher Stelle das Event als erstes ankommt. Er geht zwar davon aus das es in einer gewissen Reihenfolge vorliegt, nur wird genau das sein Problem sein warum es nicht funktioniert. Ich würde wie schon vorhin gesagt jede COM in einen Thread stecken und die Synchronisierungsmechanismen klar und strukturiert durchziehen. Dann kann man ja auch sehen in welcher Reihenfolge was wo ankommt. Außerdem hab ich nie behauptet das bei zwei Threads was sicherer ist... 😕



  • hallo leute,
    hab erst jetzt die ganzen Antworten gesehen!!
    erstmal danke für eure Hilfe und ich werd versuchen die lösungsvarianten einzeln zu testen und dann die ergebnisse zu posten



  • wenn definitv klar ist, das Com 1 ne anfrage sendet, und com 2 auf die antwort wartet. und das konsiquent durchgezogen wird, werden events richtig ankommen?

    wenn du jemand ne frage stellst bekommst ne antwort, oder bekommst du ne antwort ohne davor ne frage gestellt zu haben? du kannst ne frage stellen und es kommt keine antwort, gibts keine reaktion frägst evtl. nochmal^^ timeout..



  • BorisDieKlinge schrieb:

    wenn definitv klar ist, das Com 1 ne anfrage sendet, und com 2 auf die antwort wartet. und das konsiquent durchgezogen wird, werden events richtig ankommen?

    wenn du jemand ne frage stellst bekommst ne antwort, oder bekommst du ne antwort ohne davor ne frage gestellt zu haben? du kannst ne frage stellen und es kommt keine antwort, gibts keine reaktion frägst evtl. nochmal^^ timeout..

    Wenn das so klar wäre würde es ja funktionieren. Sollche Anmerkungen "wenn definitiv klar ist" sollte man nie machen, wenn man auf perifere Geräte zugreift. Deine Annahmen sind zwar kausal, aber wenn du Windows eine Frage stellst, bekommst du nicht immer eine kausale Antwort drauf. Deshalb sollte man das so machen, denn es ist nicht sicher (eben wegen der Überschneidung durch die Abarbeitung der Message-Loop), dass diese Annahme (erst COM1 dann COM2) immer gilt. Somit muss man diesen, wenn auch nicht gewollten oder vermuteten Fall auch ausgrenzen.
    Als Beispiel: ich hab eine Anwendung für eine Maschinensteuerung geschrieben. Dort war ein Aktor auszuwerten, dessen einzige Zustände "Anschlag links" oder "Anschlag rechts" sind. Jetzt wird einleuchten, dass wenn das Ding links anliegt, es nicht rechts sein kann und umgekehrt. Blöd war eben nur, dass das Umschalten einige wenige Millisekunden dauerte und wenn man genau dann abgetastet hatte, war keiner der beiden Zustände erreicht. Das kam zufällig alle 1000 Schaltvorgänge vor und das Programm hängte sich auf. Timeouts gingen hier nicht, da die Abfolge der Abfragen zeitlich sehr hintereinander lagen. Somit habe ich den eigentlichen Zustand "mittig" definiert, den es nach der Aussagenlogik so nicht gab. Und damit hatte ich das Problem im Griff.



  • Es ist ja so dass ich nicht davon ausgehen kann, dass ich über COM1 eine anfrage bekomme und COM2 gleich die Antwort, denn es könnte ja passieren, dass keine Antwort zurück kommt und deshalb die anfrage nochmal gestellt werden muss!!! ich bekomme folgendes ergebnis:

    anfrage x
    anfrage y
    antwort x
    anfrage z
    antwort y

    passiert es öffter, dass die hintereinander anfragen folgen, wird die antwort immer weiter nach hinten versetzt. Kommen jedoch mehrere Antworten hintereinander, so geht dies in die gegengesetzte richtung!!!
    Man könnte ja nun warten bis sich das wieder einpendelt, jedoch sind die Zeiten die bei anfrage x und antwort x "gemessen" werden zu verschieden und haben nichts mehr mit der realität zu tun, da sie verfällscht werden !!



  • markus.z84 schrieb:

    Es ist ja so dass ich nicht davon ausgehen kann, dass ich über COM1 eine anfrage bekomme und COM2 gleich die Antwort, denn es könnte ja passieren, dass keine Antwort zurück kommt und deshalb die anfrage nochmal gestellt werden muss!!! ich bekomme folgendes ergebnis:

    anfrage x
    anfrage y
    antwort x
    anfrage z
    antwort y

    passiert es öffter, dass die hintereinander anfragen folgen, wird die antwort immer weiter nach hinten versetzt. Kommen jedoch mehrere Antworten hintereinander, so geht dies in die gegengesetzte richtung!!!
    Man könnte ja nun warten bis sich das wieder einpendelt, jedoch sind die Zeiten die bei anfrage x und antwort x "gemessen" werden zu verschieden und haben nichts mehr mit der realität zu tun, da sie verfällscht werden !!

    👍 meine Rede. Ist genau das, was ich vermutet habe. Deine Chance ist nur, jede COM in einen Thread zu stecken und sauber die Synchronisation durchzuziehen. Eventuell müsstest du cachen oder mit timeouts arbeiten, wenn dir nach einer gewissen Zeit die Daten nichts mehr nützen.


Anmelden zum Antworten