Hoge resolutie timer event

Status
Niet open voor verdere reacties.

gast0152

Nieuwe gebruiker
Lid geworden
28 apr 2009
Berichten
4
Geachte lezer,

Ik ben op zoek naar een hoge resolutie timer die na een ingestelde tijd naar een loop springt. Ik weet van de standaard timer van visual studio maar deze heeft een maximale resolutie van 1ms. Ik wil resolutie in de orde grootte van 1us. Ik heb veel gevonden over de stopwatch class maar ik weet niet hoe ik de stopwatch class zodanig kan gebruiken dat er na een ingestelde tijd naar een functie wordt gesprongen(zoals dat wel met de 1ms timer class kan).

De reden waarvoor ik het nodig heb is de volgende:

Ik wil op de parallele poort een PWM signaal genereren. Daarvoor heb ik een stabiele en gedefinieerde klok nodig. Waarom wil ik het dan met events? Omdat ik met een FORM wil werken en geen zin heb in multithreading.

Dus kortom: wie kan mij vertellen hoe ik een hoge resolutie timer kan maken die elke 1us naar een loopje springt?

Bedankt alvast,
Gr Bas Kapteijn
 
De standaard timer heeft naast een beperkte resolutie ook een niet acceptabele afwijking en dient zeker niet gebruikt te worden voor synchronisatie.

De stopwatch is gebaseerd op de ticksnelheid van de cpu. Deze ticksnelheid bepaalt maw de resolutie van je timer. Deze kan je ophalen door middel van de statische

Code:
System.Diagnostics.Stopwatch.Frequeny

eigenschap. Deze eigenschap geeft een 64-bits integer (of long) terug in de orde grootte van miljoen. Maw een frequentie van 20 000 000 geeft een resolutie van 1 cputick per 50 nanoseconden.
De stopwatch kent ook geen events waardoor het moeilijk is om op een bepaalde tijd naar een functie te springen. Wat je wel kan doen is de afgelopen tijd meten en op basis hiervan een bepaalde functie oproepen. Helaas zal het uitvoeren van een functie tijd in beslag nemen waardoor je synchronisatie nooit correct zal zijn tenzij je met threads wil werken. Neem hierbij ook in acht dat je een extra vertraging hebt bij het omzetten van de bytecode van .net in native code door de JustInTimle compiler. Mag ik hier ook nog aan toevoegen dat het misschien logischer zou zijn om het aansturen van de hardware via C of C++ code te doen en deze dan in de vorm van een dll aan te spreken via interop zodat je je .net UI kan behouden.

Ik zou graag een voorbeeld bijvoegen maar ik werk momenteel onder linux. Excuses.

Succes
 
De standaard timer heeft naast een beperkte resolutie ook een niet acceptabele afwijking en dient zeker niet gebruikt te worden voor synchronisatie.

De stopwatch is gebaseerd op de ticksnelheid van de cpu. Deze ticksnelheid bepaalt maw de resolutie van je timer. Deze kan je ophalen door middel van de statische

Code:
System.Diagnostics.Stopwatch.Frequeny

eigenschap. Deze eigenschap geeft een 64-bits integer (of long) terug in de orde grootte van miljoen. Maw een frequentie van 20 000 000 geeft een resolutie van 1 cputick per 50 nanoseconden.
De stopwatch kent ook geen events waardoor het moeilijk is om op een bepaalde tijd naar een functie te springen. Wat je wel kan doen is de afgelopen tijd meten en op basis hiervan een bepaalde functie oproepen. Helaas zal het uitvoeren van een functie tijd in beslag nemen waardoor je synchronisatie nooit correct zal zijn tenzij je met threads wil werken. Neem hierbij ook in acht dat je een extra vertraging hebt bij het omzetten van de bytecode van .net in native code door de JustInTimle compiler. Mag ik hier ook nog aan toevoegen dat het misschien logischer zou zijn om het aansturen van de hardware via C of C++ code te doen en deze dan in de vorm van een dll aan te spreken via interop zodat je je .net UI kan behouden.

Ik zou graag een voorbeeld bijvoegen maar ik werk momenteel onder linux. Excuses.

Succes

Beste Ginanity,

Allereerst hartelijk dank voor de nuttige reactie. Ik heb gisterenavond een mogelijke stap genomen in de goede richting. Ik heb een threat aangemaakt naast de form thread, waarin ik in een while(true) lus data naar de parallele poort stuur. Door de dutycycle te varieeren heb ik mooie PWM gekregen aan de uitgang van mijn parallele poort.

Er zijn hier echter twee problemen:

1) Ik belast de cpu 50% (dual core, dus 1 cpu volledig belast)
2) De frequentie is ongedefinieerd

Punt twee is op te lossen door, zoals jij zelf zei, een of andere hoge resolutie timer te starten (zoals stopwatch) en continue te kijken of de tijd voorbij een ingestelde grens is gelopen. Hierna kan er naar een functie worden gesprongen. Voila een vaste frequentie(nagenoeg).

Punt één is de meest vervelende. Hoe kan ik ervoor zorgen dat ik wel een thread gebruik om naar tijd te kijken maar toch niet mijn cpu onnodig belast? Dit is in feite weer hetzelfde probleem als ik oorspronkelijk had alleen werkt mijn interface nu wel doordat ik die in een andere thread gebruik ;).

Met vriendelijke groet,
Bas Kapteijn
 
Wel het belasten van je cpu is nogal afhankelijk van de structuur en efficientie van je broncode. Het is niet zo (al wordt dat wel ooit beweerd) dat multithreading per definitie een hogere cpu belasting betekent. Wat je eigenlijk doet is op een sequentiele manier (of op basis van beslissings algoritmen) de beschikbare cputijd verdelen aan de lopende threads. De enige extra belasting die ik kan bedenken is het gebruik van metaforen of andere synchronisatie methoden, maar deze zullen nooit dergelijke belasting veroorzaken. Verder zijn er wel wat regels en standaarden rond efficiënt programmeren maar ik vermoed dat je daar wel al van gehoord hebt. Kan je misschien een stukje voorbeeldcode posten?
 
Wel het belasten van je cpu is nogal afhankelijk van de structuur en efficientie van je broncode. Het is niet zo (al wordt dat wel ooit beweerd) dat multithreading per definitie een hogere cpu belasting betekent. Wat je eigenlijk doet is op een sequentiele manier (of op basis van beslissings algoritmen) de beschikbare cputijd verdelen aan de lopende threads. De enige extra belasting die ik kan bedenken is het gebruik van metaforen of andere synchronisatie methoden, maar deze zullen nooit dergelijke belasting veroorzaken. Verder zijn er wel wat regels en standaarden rond efficiënt programmeren maar ik vermoed dat je daar wel al van gehoord hebt. Kan je misschien een stukje voorbeeldcode posten?

VOORBEELDCODE:

void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
long procfreq = Stopwatch.Frequency;
long pwmfreq = 20000;
long divider = (procfreq / pwmfreq) / steps;

textBox2.Text = Convert.ToString(procfreq / 1000000) + " MHz";
textBox3.Text = Convert.ToString(pwmfreq) + " Hz";

while(true)
{
time.Reset();
time.Start();

while (time.ElapsedTicks < divider) ;

if (i < lowtime && i < (steps - 1))
{
PortAccess.Output(0x378, 0);
i += 1;
}
else if (i >= lowtime && i < (steps - 1))
{
PortAccess.Output(0x378, 255);
i += 1;
}
else if (i == (steps - 1))
{
i = 0;
}
}
}
 
Ik vrees dat er weinig aan te doen is. De frequentie van de I/O actie is dermate hoog dat cpu tijd zowiezo gaat oplopen. Wat je eventueel nog kan proberen is zelf een theadmanager te maken ipv de BackgroundWorker te gebruiken. Deze laatste is namelijk een wrapper rond de threadpool. Voordeel hiervan is dat meest ingewikkelde multithread structuren reeds geimplementeerd zijn. Het nadeel is dat een threadpool slechts 25 thread heeft waardoor thread verplicht zijn te wachten op het einde van een andere thread.
 
Hallo,

In principe ben ik van plan de frequentie van de PWM op slechts 100Hz te laten lopen(inplaats van de nu in het voorbeeld ingestelde 20kHz). Op die manier kan ik de I/O belasting terugbrengen(mits ik niet oneindig snel controleer in een while loop!). Wat ik eigenlijk gewoon wil is dat ik windows kan zeggen:

Geef mij een seintje (doormiddel van het springen naar een loop) wanneer er een bepaald aantal ticks voorbij is gegaan. In plaats van het wachten in een oneindige loop.

Als dit kan zou dat echt super zijn(zo kan ik in de tussentijd andere dingen doen en de cpubelasting tot bijna 0% terugbrengen), dat moet haast wel kunnen zou ik zeggen.

Bedankt tot zover.
Met vriendelijke groet,
Bas Kapteijn
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan