PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verzögerung mit sleep



outdoorgamer
21.06.2006, 17:33
Hallo. Ich hab mal eine Frage. Meinen Asuro hab ich noch nicht zusammengebaut aber ich programmiere shcon fleissig, da ich schon Vorkentnisse in C hab.

ich möchte eine Verzögerung haben. vor eine Wand fahren... dann 2-3 sek warten, dann zurückfahren.

Verzögerungen gehen ja mit sleep. Aber es sind nur Übergabeparameter bis 256 möglich. dann wartet er längstens einige Millisekunden..

Ist es zweckmäßig sleep in eine for-schleife zu in tegrieren und diese dann z.B. 50 mal laufen zu lassen - oder geht es noch eleganter ???

wanderer
21.06.2006, 18:02
Naja, du nimmst einfach die neue Asurolib von Wenk und co...
Da gibt es die Msleep(zeitangabe in millisekunden)...

kungfuman
21.06.2006, 19:47
du kannst aber auch eine eigene Methode schreiben wo du das umrechnest und dann kannst du deine eigene methode verwenden ;) ist ein tolles erfolgserlebnis wenns dann funktioniert ^^

ich hab das grad für mich geschrieben. ich zähle auch zu den anfängern aber solche programme bauen auf ^^
und die funktion Sleep funktioniert so :

Sleep(x) = x / 72kHz [sec.]

also wenn du Sleep(72) nimmst und das 1000 mal wiederholen lässt kriegst du genau eine sekunde raus ;)

outdoorgamer
23.06.2006, 18:36
hab schon ne Idee :

Funktion definieren (pause) :

int pause(void)
{
for(a=0;a<=1000;a++)
{
sleep(72);
}
}


Jetz muss ich einfach nur im Programm schreiben
pause() ;

und schon hab ich ne pause *gggg*

kann man auch gut zum blinken verwenden
blinken() ;
dann natürlich noch die backLED-Befehle rein..

wanderer
23.06.2006, 18:57
wäre es nicht schöner wenn du selbst sagen könntest wie lange er "sleepen" soll?

int pause(zeit)
{
for(a=0;a<=zeit;a++)
{
sleep(72);
}
}

wanderer
23.06.2006, 18:57
außerdem ist das ja unpraktisch wenn der immer wieder die schleife macht, errechne doch einfach den Sleep wert, dann hast du nicht die schleife...

outdoorgamer
23.06.2006, 19:00
ja, kann ich wohl errechnen.. aber
soweit ich weiß ist der höchste wert, den ich übergeben kann
sleep(255)

dann hab ich gerade mal 3 ms ;)
zu wenig

wanderer
23.06.2006, 19:26
stimmt, 255 ist das maximale...

plusminus
23.06.2006, 20:24
Bitteschön (In meiner C++ Umgebung läuft es, sollte auch in C laufen)


//Deklaration der Funktionen
void Schlafen(long milliseconds);
int d2i(double d); // Double --> Integer

void main()
{
Schlafen(1337); //Funktionsaufruf
}

void Schlafen(long milliseconds)
{
long i; //Wiederholungs-variable
long rest; //Was bei der Division übrig bleibt

i = d2i(milliseconds / 250);

rest = milliseconds - d2i(milliseconds / 250 )*250;

{
int a;
for(a=1;a<=i;a++)
{
sleep(250);
}
}
if(rest!=0){sleep(rest)};
}

int d2i(double d)
{
return d;
}

outdoorgamer
23.06.2006, 20:53
also ehrlich gesagt finde ich das hier besser


int pause(zeit)
{
for(a=0;a<=1000 zeit;a++)
{
sleep(72);
}
}


(funktion natürlich im kopf als Prototypen deklarieren)

plusminus
24.06.2006, 14:03
Ich weiß nicht, ob deine version so genau ist, da die schleife so oft aufgerufen wird, wie du millisekundne pausieren willst. Habe keine Ahnung, wie lange der Mikrochip braucht, aber ich denke meine ist besser (abgesehen davon, dass ich das mit den x/72 übersehen hatte)
Die beste Lösung (meiner Meinung wäre:)

//Deklaration der Funktionen
void Schlafen(long milliseconds);
int d2i(double d); // Double --> Integer

void main()
{
Schlafen(1337); //Funktionsaufruf
}

void Schlafen(long milliseconds)
{
long i; //Wiederholungs-variable
long rest; //Was bei der Division übrig bleibt

milliseconds *= 72 // Da Sleep(72); = 1ms

i = d2i(milliseconds / 255);

rest = milliseconds - d2i(milliseconds / 255 )*255;

{
int a;
for(a=1;a<=i;a++)
{
sleep(255);
}
}
if(rest!=0){sleep(rest)};
}

int d2i(double d)
{
return d;
}


In deiner Funktion ist ein fehler... müsste wohl heißen:


for(a=0;a<=zeit;a++)
// anstatt...
for(a=0;a<=1000 zeit;a++)
[/code]

outdoorgamer
24.06.2006, 16:43
hast Recht. war ein Fehler bei mir drin

plusminus
08.05.2007, 22:03
Das was ich da vor langer Zeit mal gecoded hatte funktioniert übrigens auch recht gut aufm AVR (ATMega-2560 @16MHz)

Test mit AVR-Simulator:
Aufruf: delayMilliSeconds(137);
Dauer: 138.950us = 138,95ms

macht knapp 2% Fehler

Ich vermute sehr stark, dass das einfach ein konstanter Faktor ist, den man mit einrechnen. Der Großteil wird wohl konstant innerhalb folgender Schleife verbraten:


for (currentCycle=0; currentCycle < totalCycles; currentCycle++){
_delay_ms(MAXIMUM_DELAY_MS);
}

Lässt sich vermutlich recht einfach rausrechnen (3-4 Werte ins EXCEL-Sheet...)

Wers selber probieren will...

"myUtil.h"

#include "myUtil.c"

void delayMilliSeconds(long totalMs);

"myUtil.c"

/**
* Converts an double value to an integer
*/
int doubleToInteger(double d);


/**
* AVRs cannot sleep more than the following per _delay_ms()-Call
* MAXIMUM_DELAY_MS = 262,2ms / F_CPU_in_MHz
*/
#ifdef F_CPU
#define MAXIMUM_DELAY_MS (262 / (F_CPU / 1000000))
#endif


void delayMilliSeconds(long totalMs){
long totalCycles; // Max-number of cycles
long rest; // Rest of the flolowing integer-division

// Calculate the total amount of cycles neccessary to reach the wanted delay
totalCycles = doubleToInteger(totalMs / MAXIMUM_DELAY_MS);

// Calculate the rest that has been lost due to integer-division
rest = totalMs - (totalCycles * MAXIMUM_DELAY_MS);

// Will hold the current Cycle
int currentCycle;

// Work out all full cycles
for (currentCycle=0; currentCycle < totalCycles; currentCycle++){
_delay_ms(MAXIMUM_DELAY_MS);
}

// Work out the rest if there is one
if(rest != 0){
_delay_ms(rest);
}

}

int doubleToInteger(double d){
return d;
}