- 12V Akku mit 280 Ah bauen         
Seite 2 von 5 ErsteErste 1234 ... LetzteLetzte
Ergebnis 11 bis 20 von 41

Thema: COM-Abfrage

  1. #11
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.11.2004
    Ort
    München
    Alter
    37
    Beiträge
    447
    Anzeige

    Praxistest und DIY Projekte
    Hi,
    Naja, das ist so ne Sache mit Threads .
    Mich haben die auch schon mal genervt weil ich mich damit auch nicht so gut auskenne.
    Du müsstest die Priorität des Threads runterschrauben. Entweder mit thread->Priority oder mit Mitteln, wie bei meinem Link unten beschrieben.
    Das sollte helfen - wenn nicht bin ich auch fast Ratlos...
    MfG Alex

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    Ich hoffe das es hier um ein windows kiste geht.

    Immer dran denk windows kann kein Multitasking. Sonder es ist TimeSlot
    gesteuert. Das heist bei windows 2000 ist es so das alle 18 ms der Trhead gewechselt wird. Jedes program ist mindestens ein Thread wo bei ich keines
    kenne was wirklich nur eine hat. Auch wenn den nicht selbst programmiert.

    Auch deine Tastatur hängt in dieser Falle. wäre nur anders wenn du die tastatur per DireckX abfragst dann ist die Prioritäte etwas anders.

    Zur Instabilität kenn ich ein Fhler den viel am anfang tun. du draf auf keine Fall auch bildschirm element aus dem Thread zugreien oder auf global varialen diese zugriffe muß du sycronnisieren oder anders machen.

    Vielleicht hilft die das ja weiter.

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  3. #13
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.07.2004
    Ort
    um Berlin
    Beiträge
    346
    Der Thread im Link von @hl_angel ist offenbar unvollständig.
    Pollen ist in Fall einer seriellen Kommunikation schlecht, da hilft auch die Herabsetzung der Priorität nicht viel. Besser ist es, im Thread auf das Empfangen eines(mehrer) Bytes zu warten mit WaitForSingleObjekt(...).

    Im folgenden Beispiel wird im Empfangsthread (ComThread) mit WaitForSingleObjekt(...) auf Ereignisse an der seriellen Schnittstelle gewartet. Auf alle muß man natürlich nicht warten, EV_RXCHAR reicht schon. Die Priorität wird hier sogar noch erhöht, um ja auch alles sofort mitzubekommen (hier wird die Zeit gemessen), ohne daß das System damit ausgebremst wird! Und wie die Datenübergabe an den ComThread funktioniert, ist auch in diesem Beispiel zu sehen.
    Der Monitorthread ist nicht nowendig, die Ereignisse und Daten vom seriellen Port könne auch anderwohin gesendet werden. ABER: die Verarbeitung der Daten sollte natürlich NICHT im ComThread (oder einer von ihm aufgerufenen Funktion/Klasse) erfolgen, sondern immer gleich (in eine Message-Queue) weggeschrieben und woanders verarbeitet werden.

    Code:
    /************************************************************
    ** CommThread      : Öffnet, schließt und liest den Port,
    **                   sendet die Zeiten per PostThreadMessage
    **                   an den MonitorThread
    ************************************************************/
    
    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    
    
    // Prototypes:
    DWORD WINAPI ComThread (LPVOID lpParam);
    DWORD WINAPI MonitorThread (LPVOID lpParam);
    HANDLE StartComThread (DWORD iPortNum, HWND hEdit);
    long queryPrecisionTime (void);
    long queryPrecisionTimeStamp (void);
    
    // Globals:
    HANDLE hCom = INVALID_HANDLE_VALUE;
    
    // global struc contains parameter for threads
    typedef struct
    {
    	volatile BOOL ThreadStoppen;
    	volatile int iComPortNum;
    	volatile DWORD  dwMonitorThreadId;
    } PARAMS, *PPARAMS;
    
    static HANDLE hEvent; 
    
    // Message types
    #define MSG_MIN_RANGE      0
    // Der Message-Type für PostThreadMessage setzt sich aus
    // QS_ALLPOSTMESSAGE (=256) und dem eigenem Message-Type 
    // (siehe MSG_xxxxxxx) zusammen.
    // Mit MSG_MIN_RANGE können verschiedene Gruppen bei 
    // Bedarf gebildet werden.
    #define MSG_TIME        MSG_MIN_RANGE + 1000 // vom ComThread
    #define MSG_TRIG        MSG_MIN_RANGE + 2000 // reserviert
    #define MSG_COMOPEN     MSG_TRIG + 4
    #define MSG_COMCLOSE    MSG_TRIG + 5
    
    #define QEVENT     "QueueEvent"
    
    
    //--------------------------------------------------------------------
    // COMThread
    //
    // erstellt eine Queue, setzt danach den Event ("Queue ist ready").
    // Schließt eine geöffneten COM-Port und öffnet den neuen (Nummer ist
    // in der Strukur, auf die lpParam zeigt).
    // liest die queue aus.
    //
    // Thread Funktion
    // Liest eventgesteuert den Status von CTS, DSR, ... ein und
    // sendet in dwEvtMask alle zum Event gehörenden Ereignisse
    // zum Monitor-Thread. 
    // 
    //--------------------------------------------------------------------
    DWORD WINAPI ComThread (LPVOID lpParam) 
    {
    	long lTime;
    	volatile PPARAMS pparams;                     // struct-Instanz
    	pparams = (PPARAMS) lpParam;                  // Zuweisung zu lpParam
    	int iPortNum = pparams->iComPortNum;          // ...
    	DWORD dwMonitorThreadId = pparams->dwMonitorThreadId; // ...
    	char szPort[15];
    	static OVERLAPPED o;
    	// Maske für SetCommMask, die bestimmt, welche Ereignisse auftreten können
    	DWORD dwEvtMaskIn = EV_CTS | EV_DSR | EV_BREAK | EV_RING | EV_RXCHAR | 
    											EV_RLSD | EV_ERR | EV_RXFLAG | EV_TXEMPTY;
    	DWORD dwEvtMask = 0;  // Maske, in die WaitCommEvent aktuelle Werte schreibt
    	BOOL bRet;
    
    	CloseHandle (hCom);       // "alten" COM-Port schließen
    
    	// Com Port öffnen
      wsprintf (szPort, "COM%d", iPortNum);
    	hCom = CreateFile (szPort, 
    		GENERIC_READ | GENERIC_WRITE,
        0,    // exclusive access 
        NULL, // no security attributes 
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL);
    
    	if (hCom == INVALID_HANDLE_VALUE)
    	{
    		LPVOID lpMsgBuf;
    		FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
    			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    			NULL, GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
    			(LPTSTR) &lpMsgBuf, 0, NULL);
    		MessageBox (NULL, (LPCTSTR)lpMsgBuf, TEXT("ComThread: error: CreateFile()"), 
    			MB_OK | MB_ICONINFORMATION);
    		LocalFree (lpMsgBuf);
    		pparams->ThreadStoppen = TRUE;
    	}
    	else
    	{
    		if (!SetCommMask (hCom, dwEvtMaskIn)) 
    			MessageBox (NULL, "SetCommMask fehlgeschlagen", "COM Port:", MB_OK | MB_ICONSTOP);
    
    		// Create an event object for use in WaitCommEvent. 
    		o.hEvent = CreateEvent (NULL,   // no security attributes 
    				FALSE,  // auto reset event 
    				FALSE,  // not signaled 
    				NULL);  // no name 
    	}
    
      // Setzt die Priorität "RealTime" für das Programm
      DWORD  dwProcessId;  // own process identifier
      HANDLE hProcess;                 // handle to the own process
      DWORD  dwDesiredAccess = PROCESS_SET_INFORMATION;  // access flag
      BOOL   bInheritHandle = TRUE;   // handle inheritance flag
      BOOL   bReturn;           // If the SetPriorityClass succeeds, then nonzero
      DWORD  dwPriorityClass = HIGH_PRIORITY_CLASS;
    
      dwProcessId = GetCurrentProcessId ();
      hProcess = OpenProcess (dwDesiredAccess, bInheritHandle, dwProcessId);
      bReturn = SetPriorityClass (hProcess, dwPriorityClass);
    
    	printf ("\r\nComThread: %s geöffnet, warte auf Events ...", szPort);
    
    	// eine message zum Monitor-Thread senden:
    	bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMOPEN), 
    			(WPARAM)iPortNum , (LPARAM)0);
    
    	// Auf Events warten:
    	while (!pparams->ThreadStoppen) // solange weitermachen bis TRUE
    	{
    		WaitCommEvent (hCom, &dwEvtMask, &o);  // EventMask "scharf machen"
    		// kommt der Event, ist auch die dwEvtMask geladen und es kann weitergehen
    		if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
    		{
    			lTime = queryPrecisionTimeStamp ();  // Zeit holen
    			// Message senden. In dwEvtMask können mehrere Ereignisse gesetzt sein
    			bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_TIME), 
    					(WPARAM)dwEvtMask , (LPARAM)lTime);
    		}    // end of: if (WAIT_OBJECT_0 == ...
    	}      // end of: while (...
    
    	CloseHandle (o.hEvent);
    	CloseHandle (hCom);          // COM-Port schließen
    
    	printf ("\r\nComThread: %s geschlossen", szPort);
    
    	bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMCLOSE), 
    			(WPARAM)iPortNum , (LPARAM)0);
    
    	return (0);
    }
    
    
    //----------------------------------------------------------------------------
    // MonitorThread
    //
    // erstellt eine Queue, setzt danach den Event und liest
    // die queue aus
    //----------------------------------------------------------------------------
    DWORD WINAPI MonitorThread (LPVOID lpParam) 
    { 
    	static char szMsg[255] = "";
    	static char szMsgTmp[30] = "";
    	int i = 0;
    	BOOL bRet;
    	MSG msg;
    	volatile PPARAMS pparams;                     // struct-Instanz
    	pparams = (PPARAMS) lpParam;                  // Zuweisung zu lpParam
    
    	DWORD COMStatus;
    
    
    	// create a queue for the thread
    	PeekMessage ((LPMSG)&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
    	// sent event after queue creation back to the threads creator
    	bRet = SetEvent (hEvent);
    	
    	printf ("\r\nMonitorThread: warte auf Events ...");
    
    	// get messages by message from threads local queue
    	while ((bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
    	{
    		if (bRet == -1)
    		{ // handle the error and possibly exit
    			MessageBox (NULL, "MonitorThread: GetMessage error", "COM Port:", MB_OK | MB_ICONSTOP);
    			return NULL;  // error!
    		}
    		else  
    		{ // a valid message is received
    			switch (msg.message)
    			{
    			case (QS_ALLPOSTMESSAGE + MSG_COMOPEN):
    				printf ("\r\nMonitorThread: MSG_COMOPEN: lParam=0x%08x wParam=0x%08x", 
    					msg.lParam, msg.wParam);
    				break;
    				
    			case (QS_ALLPOSTMESSAGE + MSG_COMCLOSE):
    				printf ("\r\nMonitorThread: MSG_COMCLOSE: lParam=0x%08x wParam=0x%08x", 
    					msg.lParam, msg.wParam);
    				break;
    				
    			case (QS_ALLPOSTMESSAGE + MSG_TIME):
    				// Time stamp message: lParam=time, wParam=dwEvtMask
    				szMsg[0] = '\0';
    
    				if (DWORD(msg.wParam) & EV_CTS)
    				{
    					GetCommModemStatus (hCom, &COMStatus);
    					if (COMStatus & MS_CTS_ON)
    					{ // CTS (Pin8) activated
    						wsprintf (szMsgTmp, "\r\nCTS_ON : %lu µs", msg.lParam);
    					}
    					else
    					{ // CTS (Pin8) deactivated
    						wsprintf (szMsgTmp, "\r\nCTS_OFF: %lu µs", msg.lParam);
    					}
    					strcat (szMsg, szMsgTmp);
    				}
    
    				if (DWORD(msg.wParam) & EV_DSR)
    				{
    					GetCommModemStatus (hCom, &COMStatus);
    					if (COMStatus & MS_DSR_ON)
    					{ // DSR (Pin6) activated
    						wsprintf (szMsgTmp, "\r\nDSR_ON : %lu µs", msg.lParam);
    					}
    					else
    					{ // DSR (Pin6) deactivated
    						wsprintf (szMsgTmp, "\r\nDSR_OFF: %lu µs", msg.lParam);
    					}
    					strcat (szMsg, szMsgTmp);
    				}
    
    				if (DWORD(msg.wParam) & EV_RLSD)
    				{
    					GetCommModemStatus (hCom, &COMStatus);
    					if (COMStatus & MS_RLSD_ON)
    					{ // DCD (Pin1) activated
    						wsprintf (szMsgTmp, "\r\nRLSD_ON: %lu µs", msg.lParam);
    					}
    					else
    					{ // DCD (Pin1) deactivated
    						wsprintf (szMsgTmp, "\r\nRLSD_OFF: %lu µs ", msg.lParam);
    					}
    					strcat (szMsg, szMsgTmp);
    				}
    
    				if (DWORD(msg.wParam) & EV_RING)
    				{
    					GetCommModemStatus (hCom, &COMStatus);
    					if ((COMStatus & MS_RING_ON))
    					{ // RI (Pin9) activated
    						wsprintf (szMsgTmp, "\r\nRING_ON: %lu µs", msg.lParam);
    					}
    					else
    					{ // RI (Pin9) deactivated
    						wsprintf (szMsgTmp, "\r\nRING_OFF: %lu µs", msg.lParam);
    					}
    					strcat (szMsg, szMsgTmp);
    				}
    
    				printf (szMsg);
    				break;
    				
    			default:
    				wsprintf (szMsg, "\r\nMonitorThread: default: lParam=0x%08x wParam=0x%08x message=0x%08x", 
    					msg.lParam, msg.wParam, msg.message);
    				MessageBox (NULL, (LPCTSTR)szMsg, "COM Port:", MB_OK | MB_ICONSTOP);
    				break;
    			}  // end of: switch (msg.message)
    		}    // end of: if (bRet == -1) else ...
    	}      // end of: while((bRet = GetMessage(...
    	
    	printf ("\r\nMonitorThread: beendet");
    	return 0; 
    } 
    
    
    // Globale Variablen
    // struct für Zeitmessung
    union ut_LargeInteger
    {
    	LARGE_INTEGER o_WinPart;
    	ULONGLONG       l_MyPart;
    };
    
    int i_ResetPrecisionTime = 0;
    ULONGLONG l_PerfFrequ;
    ut_LargeInteger uo_PerfCount;
    
    /************************************************************************
    Die Funktion queryPrecisionTimeStamp () liefert die seit dem Start des PC
    verstrichene Zeit in Mikrosekunden.
    ************************************************************************/
    long queryPrecisionTimeStamp (void)
    {
    	if (i_ResetPrecisionTime == 0)
    	{
    		i_ResetPrecisionTime = 1;
    		QueryPerformanceFrequency (&uo_PerfCount.o_WinPart);
    		l_PerfFrequ = uo_PerfCount.l_MyPart;
    	}
    	
    	ut_LargeInteger uo_perfCount;
    	QueryPerformanceCounter (&uo_perfCount.o_WinPart);
    	return (long) (uo_perfCount.l_MyPart * 1000000 / l_PerfFrequ);
    }
    
    // *********************************************************************
    int main (void)
    {
    	DWORD  dwMonThreadId;
    	DWORD  dwComThreadId;
    	HANDLE hMonThread;
    	HANDLE hComThread;
    	DWORD  dwState;
    	PARAMS p;
    
    	// MonitorThread erstellen:
    	// Erstellt den Event für die Thread Queue
    	hEvent = CreateEvent (NULL, false, true, QEVENT);
    	// Thread starten und uMonThreadID für ComThread merken
    	hMonThread = CreateThread (      // Handle des Threads
          NULL,                        // no security attributes 
          0,                           // use default stack size  
          MonitorThread,               // thread function 
          &p,                          // argument to thread function 
          0,                           // use default creation flags 
          &dwMonThreadId);             // returns the thread identifier 
    	
    	if (hMonThread == NULL) 
    		printf ("\r\nCreateThread (MonitorThread) fehlgeschlagen");
    
    	p.dwMonitorThreadId = dwMonThreadId;  // merken, für ComThread
    	
    	// wait for queue completition
    	dwState = WaitForSingleObject (hEvent, 100);
    	CloseHandle (hEvent);
    
    	// "alten" Thread stoppen  
    	p.ThreadStoppen = TRUE;
    	CloseHandle (hComThread); // "alten" Thread stoppen
    	p.iComPortNum = 1;
    	// ComThread: Starten und Parameterstruct übergeben
    	p.ThreadStoppen = FALSE;
    	hComThread = CreateThread (    // Handle des Threads
        NULL,                        // no security attributes 
        0,                           // use default stack size  
        ComThread,                   // thread function 
        &p,                          // argument to thread function 
        0,                           // use default creation flags 
        &dwComThreadId);             // returns the thread identifier 
    
    	if (hComThread == NULL) 
    		printf ("\r\nCreateThread (ComThread) fehlgeschlagen");
    
    	Sleep (30000); // nur so zum Test
    
    	CloseHandle (hMonThread);    // MonitorThread beenden
    	CloseHandle (hComThread);    // ComThread beenden
    
    	return (0);
    }
    Anpassen an die Borland-Sytax/Notation sollte nicht schwer sein.

    Blackbird

  4. #14
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    @Blackbrid

    Ich hätte mir den link angucken sollen wer pollt der bei der serialen.
    man dann verstehe ich das zu den verzögerungen kommt.

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  5. #15
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.07.2004
    Ort
    um Berlin
    Beiträge
    346
    Nicht nur beim Lesen der seriellen Schnittstelle sollte man nicht pollen, sondern auch beim Datei lesen. Geht genauso. Und beim Schreiben ebenfalls mit "overlapped" Funktionen arbeiten, damit nicht der Programmablauf in dieser Zeit blockiert ist. Ist besonders wichtig bei großen Datenmengen (seriell wie auch Datei) und vielen Schreib-Lese-Operationen. Das bringt richtig Speed!

    Blackbird

  6. #16
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    Datei lesen tut ich selten schon garnicht im robi.
    wenn ich daten holen dann meintesn eine DB.
    Und für die logs schreibe ich eh per thread.

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  7. #17
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.07.2004
    Ort
    um Berlin
    Beiträge
    346
    Der Fragesteller hat das Prog ja auch auf einen PC laufen, nicht im Bot. Würde im Bot ein Mainbord mit Windows laufen, gelten die Ausführungen dann aber auch dort.
    Dateien müssen nicht unbedingt auf einer HDD, CD oder Floppy liegen

    Blackbird

  8. #18
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    bei mir ist das so windows PC im bot *g*
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

  9. #19
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    06.07.2004
    Beiträge
    122
    OK. Ich hab vielleicht den Anfängerfehler gemacht und auf globale Variabeln, bzw. auf Elemente zugegriffen.
    Wie funktioniert denn das mit dem Synchronisieren?

  10. #20
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    31.01.2004
    Ort
    36399
    Alter
    50
    Beiträge
    1.562
    Code:
    procedureTMyThread.PushTheButton;
    
    begin
      Button1.Click;
    end;
    ...
    procedure TMyThread.Execute;
    begin
    ....
      Synchronize(PushTheButton);
    ...
    end;
    ist zwar ein deplhi beispiel aber im Borland C++ gibt es den meines wissens auch.

    Denke daber dran das den code auf hält bis sync erreicht.

    welche daten will du den vom Thread an das fenster schicken
    geht das nicht vielleicht besser mit PostMessage ?

    Gruß
    P: Meine Tochter (06.11.07) und https://www.carnine.de
    M: Träumen hat nix mit Dummheit zu tun es ist die Möglichkeit neues zu erdenken

Seite 2 von 5 ErsteErste 1234 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress