PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : zeitmessung



kurm_de
25-08-2005, 11:45
hi,

ich hab mir ein kleines Windrad gebaut und an den Parallelport angeschlossen.
An dem Windrad ist ein Reed-Kontakt. Bei jeder umdrehung werden zwei Pins am Port geschlossen. Jetzt wollte ich den Parallelport auslesen und messen wieviele Kontakte pro Sekunde zustande kommen.
Das Auslesen des Parallelports ist kein Problem:


#include <stdio.h>
#include <asm/io.h>

int main(int argc, char *argv[])
{
int wdat;
int halten;

if(iopl(3) !=0)
{
perror("Can't set I/O permissions");
return(1);
}
wdat=0;
outb(255,0x378);
while(1)
{
if((inb(0x379) & 64)==0)
{
if(halten==0)
{
printf("piep\n");
wdat++;
}
halten=1;
}
if((inb(0x379) & 64)!=0) halten=0;
}
outb(0,0x378);
return(0);
}

aber wie kann ich nun messen wieviele Kontakte pro Sekunde zustande kommen?
Damit ich dann die Windgeschwindigkeit ausrechnen kann.

Gruß kurm_de

anda_skoa
25-08-2005, 13:21
Zeit auslesen
man gettimeofday

dann X messungen machen
dann wieder Zeit auslesen
dann X / vergangene Zeit

Ciao,
_

almoeli
26-08-2005, 10:38
Hi,

ich würde das mit einem Timer und dem SIGALRM lösen. Dazu benötigt man dann noch zwei globale Variablen in denen der aktuelle Counter deines Reed Kontaktes und die aktuelle Geschwindigkeit abgelegt wird.

Der Signalhandler macht folgendes:
Er berechnet die Geschwindigkeit und speichert sie in der globalen Variable. Danach setzt er den Counter für den Reed Kontakt wieder auf 0.

Das Hauptprogramm:
Mit der Funktion sigaction definiert man einen Signalhandler für das Signal SIGALARM.
Mit Funktion setitimer zieht man den timer auf. Dazu die den Struktureintrag it_intervall.tv_sec auf 1 setzen, damit es ein alle 1s wiederkehrender Timer wird.
Danach kommt deine normale Hauptschlife die den Zähler deines Reed-Kontktes hochzählt.
Sollte Das Programm einen sauberen Weg zum Verlassen bekommen, so mußt du den Timer mit setitimer wieder auf auf 0 Sekunden setzen und damit entschärfen.

Damit erhälst du einen sauberen Weg alle Sekunde die Geschwindigkeit zu berechnen.
Bei der lösung von anda_skoa wird das Messintervall bei langsamen Geschwindigkeiten länger, weil du auf eine feste Anzahl X an Messwerten wartest die bei langsamer Geschwingigkeit natürlich auch länger brauchen. Du bekommst dann auch nur ein Mittel der Geschwindigkeit über diesen langen Zeitraum.

Hoffe das war nicht zu verwirrend und hilft dir weiter.

Gruß

almoeli

kurm_de
29-08-2005, 09:11
ich glaub ich komm da nicht ganz mit :)

ich brauche doch eigentlich nur in eine Variable(zeit1) die Zeit zu schreiben.
dann mach ich eine Schleife:
in der Schleife wird dann die aktuelle Zeit in eine andere Variable(zeit2) geschrieben und die anzahl Kontakte hochgezählt z.b. über die Variable count.
Die Schleife verlasse ich, wenn zeit2 +1 >zeit1 ist.
Nun hab ich doch die Anzahl Kontakte pro Sekunde und kann die Geschwindigkeit ausrechnen.

ich glaub mein Problem ist das ich nicht weis wie man die Zeit in eine Variable bekommt.

gruß kurm_de

sixfriends
30-08-2005, 14:42
rtfm (http://mirbsd.mirsolutions.de/cman/man2/gettimeofday.htm)

sixfriends

kurm_de
30-08-2005, 21:07
ich hab jetzt mal was zusammen gebastelt:


#include <stdio.h>
#include <asm/io.h>
#include <sys/perm.h>
#include <sys/time.h>

int main()
{
struct timeval start,end;
int halten,wdat,difftime;

ioperm(0x378,3,1); //Port(LPT1) öffnen

gettimeofday(&start,NULL); //Anfangszeit in 'start' speichern
difftime=0;
wdat=0;
outb(255,0x378); //Strom an allen Pins an
while(1)
{
gettimeofday(&end,NULL); //Endzeit in 'end' speichern

if((inb(0x379) & 64)==0) //wenn zwichen Pin 10 und Masse->Kontakt wdat->hochzählen
{
if(halten==0)
{
wdat++;
}
halten=1;
}

if((inb(0x379) & 64)!=0) halten=0; //wenn zwichen Pin 10 und Masse-> kein Kontakt mehr dann nächsten Kontakt registrieren

difftime = end.tv_sec - start.tv_sec; //Differenz zwichen Anfangszeit und Endzeit ausrechenen
if(difftime>=1) //nach einer 1er Sek. ...
{
system("clear"); //Bildschirm löschen:)
printf("wdat: %i\n",wdat); //wdat auf Bildschirm schreiben
gettimeofday( &start,NULL); //Anfangszeit erneut in 'start' speichern
wdat=0; //wdat leer machen für neue messung
}
}
outb(0,0x378); //Strom an allen Pins aus
ioperm(0x378,3,0); //Port(LPT1) schliessen
}

soweit funktioniert alles, ihr könnt ja mal schreiben was ihr davon haltet.

gruß kurm_de

24dan
01-09-2005, 13:04
Zeit:


typedef struct
{
int d;
int mo;
int y;
int h;
int mi;
int s;
}TIME;


int inVariablenSchreiben(TIME *active)
{
struct timeval wt;
struct tm gtime;
// int stime;
gettimeofday (&wt,NULL);
gtime = *gmtime (&(wt.tv_sec));
active->d = gtime.tm_mday;
active->mo = ++gtime.tm_mon;
active->y = 1900+gtime.tm_year;
active->h = gtime.tm_hour;
active->mi= gtime.tm_min;
active->s = gtime.tm_sec;
return(0);
}


:D

nobody0
05-09-2005, 19:56
Zuverlässig funktionieren kann sowas nur bei niedrigen Frequenzen und nicht allzu hoher Rechner-Auslastung.
Zuverlässiger ist es einen Interrupt-Handler dafür zu nehmen und besser noch harte Echtzeit wie z. B. den RTAI-Patch, www.rtai.org .

Hier mal ein Programm dazu:

http://www.mikrocontroller.net/forum/read-4-195781.html#new