Timerproblem



  • Ich habe folgendes Problem:

    Ich steuere über den USB einen Schrittmotor an und verwende dazu einen Timer mit 10ms schritten. Klappt auch im prinzip wunderbar, aber der Motor verschluckt sich oft (schrittfehler). Erst wenn ich den Timer mit ca. 75-100ms laufen lasse funktioniert der Motor ohne Fehler (ist aber zu langsam). Wenn ich das ganze per Tastendruck (PreTranslateMsg) laufenlasse ist es das gleiche in grün. Wenn ich das aber über eine For-Schleife bediene, dann geht es FAST ohne fehler (unpraktikabel, da ich NIE weiß wie lange und wie oft ich was mache).

    Meine Frage(n):

    1. Woran könnte das liegen, dass der Timer / der Tastendruck nicht 100% funktionieren? (verdacht-> Windows-Msg zu langsam oder ähnliches?)
    2. Gibt es eine andere Möglichkeit oder einen anderen Timer, den ich verwenden könnte (Bsp. oder Hilfen wären nett).

    Danke schonmal



  • Ja, der Windows-Timer ist sehr ungenau.
    Stichwort sind hier Multimediatimer.
    Such mal nach QueryPerformanceCounter.



  • Was übergibts du denn der Schnittstelle? Ich habe bisher Schrittmotoren nur über externe Karten angesteuert und mit einer digitalen I/O-Karte den Takt generiert. Je nach dem wie die angeschlossene Treiberstufe die Taktwerte verarbeiten kann können auch Schrittfehler auftreten. Das passiert meist wenn die Triggerimpulse zu schmal sind (also die Schaltzeit zu kurz). Bei mir ging das allerdings bis ca. 5 ms problemlos. Dies erklärt aber noch nicht, warum es in der Schleife geht und mit dem Timer nicht. Ich kenn mich mit Timern nicht so gut aus aber ich könnte mir vorstellen das der Scheduler je nach Systemauslastung reinfunkt und der Timer mit einem gewissen Delay die WM_TIMER abgibt, wenn das System stärker belastet ist. Bei meinen Versuchen reichte es schon die Maus zu bewegen. Dann lief der Motor langsamer.



  • evtl. ne unendliche for/ while schleife, mit Abbruchbedingung bei tastendruck.

    Druch Aurruf des folgenden Codes, wird so die Messageloop bei jeder Schleifeninereation aufgerufen, und das system ist somit NIHCt gefroren.

    MSG msg;
        while (::PeekMessage(&msg, NULL, 
            NULL, NULL, PM_NOREMOVE)) {
            AfxGetThread()->PumpMessage();
        }
    


  • BorisDieKlinge schrieb:

    evtl. ne unendliche for/ while schleife, mit Abbruchbedingung bei tastendruck.

    Druch Aurruf des folgenden Codes, wird so die Messageloop bei jeder Schleifeninereation aufgerufen, und das system ist somit NIHCt gefroren.

    MSG msg;
        while (::PeekMessage(&msg, NULL, 
            NULL, NULL, PM_NOREMOVE)) {
            AfxGetThread()->PumpMessage();
        }
    

    Bei Schrittmotorensteuerungen braucht man schon ziemlich genaue Zeitabläufe. Dein Vorschlag wird das Problem nicht lösen bzw. noch vergrößern.



  • dann werden wohl Thread nötig sein...



  • Was übergibts du denn der Schnittstelle?

    Ich übergebe der schnittstelle 2 einfach Bytes, die ich in 2 Stufen sende.
    1. motor anwählen, hab 2 davon (0xFE z.B.)
    1.1 schreiben (Senden an USB)
    2. Richtung der Drehung (0xF7 z.B.)
    2.1 schreiben (s.o.)

    Ich hab auch erst gedacht, dass ich vielleicht die Daten zu schnell schicke und habe ein Sleep() eingebaut, aber das hat nichts gebracht. Wie gesagt es tritt erst ab einem Timer mit 75-100ms auf. Davor klappts wunderbar.
    Das das System bei Timer zwischenfunkt ab ich mir auch schon gedacht. Hab auch indiret eine bestätigung gerade bekommen, als ichs nochmal getestet habe und mein AntiVir meinte mal einen scan zu wagen 😉

    Das mit den Multimedia-Timer scheint mir interessant zu sein. Werd mir das mal anschauen und ausprobieren. Ein Freund von mir meinte ich soll mal einen Quicktime-Treiber und -Timer verwenden. Ich hab damit auber nichts anangen können ?!?

    Die Sache mit den Threads lass ich erstmal außen vor, da ich da noch nicht mit gearbeitet hab und das mein Problem auch nur umgeht.



  • ich ha mir jetzt mal QueryPerformanceCounter() angesehen und komm damit nicht so ganz weiter. Mein Problem ist nur, dass ich nicht genau weiß wo und wie ich den anspreche. die windiws.h hab ich eingebunden und diesen ode aus einem Thread hier:

    //MSG mssg;                // message from queue
    //LONGLONG cur_time;       // current time
    DWORD  time_count=5;    // ms per frame, default if no performance counter
    LONGLONG perf_cnt;       // performance timer frequency
    BOOL perf_flag=FALSE;    // flag determining which timer to use
    LONGLONG next_time=0;    // time to render next frame
    BOOL move_flag=TRUE;     // flag noting if we have moved yet
    
    // is there a performance counter available?
    
    	if (QueryPerformanceFrequency((LARGE_INTEGER *) &perf_cnt)) {
    
    	// yes, set time_count and timer choice flag
    
    		perf_flag = TRUE;
    		time_count = (DWORD) perf_cnt/25;        // calculate time per frame based on frequency
    		QueryPerformanceCounter((LARGE_INTEGER *) &next_time);
    	}
    

    Wohin damit?


Anmelden zum Antworten