Forum: Mikrocontroller und Digitale Elektronik habe noch problem mit der berechnung Windgeschwindigkeit


von wagner (Gast)


Lesenswert?

Hallo

Ich benutze einen 8bit Timer der die Zeit zwischen zwei impulsen zählen 
soll.

Ich bekomme aber am ende einen um 50% niedrigeren wert errechnet.

In einigen foren lese ich das man es über den ext interrupt machen soll.

Wie geht das???

Schließe mein reedkontackt an einen Pin INT0 an und löse einen 
Inmterrupt bei fallender oder steigender flanke aus.

Aber wie bekomme ich dann die zeitdifferenz???

Kann mir einer mal ein code schnipsel zukommen lassen wie ich die zeit 
zwischen den interrupts berehne????

Ich nutze einen Mega 8 mit 8Mhz.

So siehts bis jetzt aus mit meinem Code


void timer0_init(void)
{

TCNT0=0;
TCCR0=(1<<CS00); // Timer 1 ist normaler Timer

TIMSK = (1<<TOIE0);

}


SIGNAL( TIMER0_OVF_vect )
{

if(!(PIND & (1<<3)) && start==0)
{
start=1;
}

if((PIND & (1<<3)) && start==1)
{
plow=1;
}



if(!(PIND & (1<<3)) && start==1 && plow==1)
{
plow=0;
char buffer[20];

float v=2.0*3.14159265 *0.065 * (1.0/((float)zi*1.0/31250.0))*3600.0;
 v=v/1.85;
 g=(int)v;
sprintf(buffer,"v=%d kt/h\r",g/1000);
send_UART(&buffer[0]);
start=0;
zi=0;
}
}


Danke

von Mario T. (Firma: keine) (mariot)


Lesenswert?

Ich kenne deinen Controller nicht aber ein Tipp: Vielleicht hat er eine 
Capture/Compare Einheit - mit der lassen sich solche Messungen in der 
Regel am besten lösen. Ansonsten würde ich den Interrupt auf z.B. die 
fallende Flanke triggern, beim Interrupt einen Timer auf 0 setzen, beim 
nächsten Interrupt den Timer Wert auswerten. Ich kenne die AVRs nicht, 
deshalb ist exaktes ein Code Snippet nicht möglich, aber auf die 
Schnelle in etwa so:

unsigned char OvlwsOccured;

void TimerInterrupt() interrupt X
{ Timer IntFlag loeschen wenn dies von Software gelöscht werden muss (?)
  if(OvlwsCount < 0xFF)  OvlwsCount++;
}


void ExternalInterrupt() interrupt Y
{ static boolean MeasurementStarted = 0;

  if(!MeasurementStarted)
  { Timer auf 0 setzen;
    Timer IntFlag loeschen
    OvlswCount = 0;
    Timer starten;
    MeasurementStarted = 1;
  }
  else
  { Timer stoppen;
    if(OvlwsCount == 0xFF)
      "Frequenz zu niedrig"
    else
      VerstricheneZeit = (OvlwsCount * 0xFF + Timerwert) * t;

    MeasurementStarted = 0;
  }
}

von Mario T. (Firma: keine) (mariot)


Lesenswert?

Kann es sein, dass Du nur die halbe Periode misst?

       ____________                _________
      |             |              |
______|             |______________|
                   

von wagner (Gast)


Lesenswert?

Wie die halbe periode??

Wie kann cih die ganze periode messen???


Ist dies nicht wenn ich start bis stop messe???

Danke


Wenn es baer so sein mag dann kommt es mit dem 50 % hin.

von Mario T. (Firma: keine) (mariot)


Lesenswert?

Ich verstehe deinen Code grundsätzlich nicht.

" SIGNAL( TIMER0_OVF_vect ) "

sieht aus wie wenn es sich um die Timer Isr handelt, die wird dann nur 
alle z.B. ms aufgerufen.

Warum verwendest Du nicht einen externen Interrupt und triggerst auf 
jede pos oder neg Flanke. Beim ersten Interrupt den Timer 0 setzen und 
starten, beim nächsten Interrupt den Timerwert speichern, dann hast Du 
genau die Periodendauer.

was passiert mit der Variable zi?

von wagner (Gast)


Lesenswert?

Ja das ist wie schon gesagt die bessere variante.


Ich werde mal deise Variante ausprobieren ich hoffe ich bekomme hin.

Danke

von wagner (Gast)


Lesenswert?

Ich habe jetz mal folgendes Probiert

Externer Interrupt auf INT1

Timer1 16Bit

void extint_enable(void)
{
MCUCR = (1<<ISC11);
GICR = (1<<INT1);
GIFR = (1<<INTF1);

}

SIGNAL(INT1_vect)
{
if(start==0)
{
TCNT1=0; //counter auf 0
start=1;
}
else
{
char buffer[20];
unsigned int zdiff=TCNT1; //auslesen des Zählers
sprintf(buffer,"Zeit=%x \r",zdiff);
send_UART(&buffer[0]);
start=0;
}


den Timer 1 habe ich so definiert

void timer1_init(void)
{
TCCR1A=0;
TCCR1B=  (1<<CS10); //Presca =1;
TIMSK = (1<<TOIE0);
}


den Timer starte ich am anfang.

als ergebniss bekomme ich

Zeit=5388
Zeit=e14
Zeit=16e
Zeit=16e
Zeit=16a
Zeit=16e
Zeit=170
Zeit=6ece
Zeit=de8a
Zeit=508a
Zeit=cc3a
Zeit=6daa
Zeit=f3b4

diese werte

das stimmt doch nicht???

danke

von mario (Gast)


Lesenswert?

Ich kann Dir nicht weiter helfen da ich die AVRs überhaupt nicht kenne. 
Ich würde schauen wie schnell der Timer inkrementiert und ob deine 
Interrupts so auslösen wie geplant (und vielleicht ob der 16 Bit Timer 
nicht überläuft, wenn er alle us inkrementiert dann sind es nur 65ms bis 
zum Überlauf. Du schreibst Prescaler = 1 - vielleicht ist die 
Periodendauer länger, keine Ahnung wieviele Impulse das Windrad pro 
Umdrehung ausgibt. Einfach mal mittels Simulator oder Emulator testen.

von mario (Gast)


Lesenswert?

Vielleicht prellt dein Signal? Wenn Du ein Oszi hast, dann solltest Du 
das Signal man ansehen.

Du koenntest versuchen:

SIGNAL(INT1_vect)
{
if(start==0)
{
TCNT1=0; //counter auf 0
start=1;
}
else
{
  if(TCNT1 < bestimmterWert)   // z.B. 2ms
  { nichts tun
  }
  else
  { char buffer[20];
    unsigned int zdiff=TCNT1; //auslesen des Zählers
    sprintf(buffer,"Zeit=%x \r",zdiff);
    send_UART(&buffer[0]);
    start=0;
  }
}

von mario (Gast)


Lesenswert?

Meder gibt für seine MK3 Reedkontage eine Schaltzeit von 0,5ms inklusive 
Prellzeit an, vielleicht solltest Du bis zu einer Millisekunde die 
Interrupts nicht verwerten.

von wagner (Gast)


Lesenswert?

Also

Ich habe nun mal nach Interrupt Rising Edge und mal gedreht nun wird nur 
noch ein Interrupt pro umdrehung ausgelößt.

Aber im Register TCNT1 steht nur müll

z=5787
z=-31767
z=-24423
z=-27489
z=-2013
z=-27043
z=16129
z=-27965
z=-23121
z=-8505
z=17845
z=-13229
z=4917
z=19319
z=-5943
z=15409
z=28791
z=-22979
z=-8475
z=11209
z=32613
z=-13301
z=-5851
z=941



Wie sollte man den Timer konfigurieren????

Oder ist es besser die umdrehungen pro sekunde zu ermitteln und dann zu 
rechnen.

Ich komme einfach nicht weiter.

von wagner (Gast)


Lesenswert?

Leider musste ich festellen das der reed doch prellt und ich bekomme 
manchmal pro umdrehung zwei interrupts und natürlich eine falsche 
messung.


die messung sieht jetzt besser aus preescaler auf 265.

messwerte von ca 900 - 24000.


wie kann ich den reed entprellen.

Danke

von mario (Gast)


Lesenswert?

Ich würde es so versuchen wie ich es Dir bereits nahe gelegt habe, 
nämlich nach dem Starten des Timers für z.B. eine Millisekunde die 
Interrupts ignorieren.

Wenn der Prescaler auf 256 ist nehme ich an, dass der Timer alle
(4 / 8 Mhz) * 256 = 128us eins hochzaehlt, d.h. Du hast einen Bereich 
von 0 bis 65536*128u = 0 bis ca. 8 Sekunden.

Wenn sich Dein Windrad extrem schnell dreht, vielleicht mit 100 
Umdrehungen pro Sekunde, dann kommt alle 10ms ein Impuls. Viel schneller 
wird das Rad nicht laufen. Impulse mit 1ms treten demnach nicht auf, 
d.h. Du kannst nach dem Starten des Timers alle Interrupts für eine 
gewisse Zeit ignorieren, z.B für eine Millisekunde (länger als die 
Prelldauer des Kontakts!).  (die 4/8Mhz sind nur geschätzt, wie der 
Timer im AVR zählt musst Du im Datenblatt nachsehen).

SIGNAL(INT1_vect)
{
if(start==0)
{
TCNT1=0; //counter auf 0
start=1;
}
else
{
  if(TCNT1 < 10)   // die ersten 10x128us Interrupts nicht auswerten
  { nichts tun
  }
  else
  { char buffer[20];
    unsigned int zdiff=TCNT1; //auslesen des Zählers
    sprintf(buffer,"Zeit=%x \r",zdiff);
    send_UART(&buffer[0]);
    start=0;
  }
}

von wagner (Gast)


Lesenswert?

Also alles trugschlüsse


So komme ich nicht weiter


ich habe jetzt meine alte variante ein bisschen mofifiziert


in der main While

mach ich jetzt folgendes


ich frage ab ob der pin(reed kontackt) high ist und ob er wieder auf low 
geht.

wenn er high ist starte ich den timer wenn er low ist weiß ich er dreht 
sich und wenn er wieder high ist dann lese ich das TCNT1 aus.

so siehts jetzt aus

z=1742
z=3262
z=3126
z=2181
z=3944
z=3861
z=4144
z=4454
z=4796
z=5161
z=5572
z=4007
z=6904
z=7185
z=7857
z=8530
z=9222
z=9963
z=10834


von schnell drehend bis auslaufend.

nur was soll der wert zwischen 5572 und 6904 wie kommt der zu stande???

Danke

von mario (Gast)


Lesenswert?

Wenn alles Trugschlüsse sind dann gebe ich meinen Senf nicht mehr dazu. 
Auf Deine Weise kann Dein Programm nicht viel mehr tun als dieses Signal 
auszuwerten, wenn die Messung genau werden soll dann kann eigentlich in 
main nur diese eine Aufgabe verarbeitet werden. Im Prinzip ist es eine 
sehr einfache Aufgabe, am meisten wirst Du lernen wenn Du Dich selbst 
durchkämpfst.

von mario (Gast)


Lesenswert?

Weshalb löst Du das Problem nicht mit der Capture Unit - die AVRs haben 
bestimmt so ein Teil integriert. In der Hauptschleife immer warten bis 
Impulse kommen ist Kinderkram.

von wagner (Gast)


Lesenswert?

Sorry mit Trugschlüssen meinte ich mein Impulszählen ich schrieb ja er 
zählt ein impuls pro Umdrehung nach weiteren test musste ich aber 
feststellen das es nicht so ist er zählt max 2 Impulse pro Umdrehung 
manchmal aber nur einen denke es liegt am reed.


Ich habe wieder auf Ext interrupt gestellt.

und bekomme zwischendurch immer einen falschen wert

z=2579
z=1932
z=1309
z=415  //hier
z=2292
z=2380
z=2544
z=2721
z=2915
z=2028 // hier
z=745  //hier
z=3417
z=2348  //hier
z=892   //hier
z=3921



wie kommt sowas zustande.

SIGNAL(INT1_vect)
{

if(start==0)
{
TCNT1=0;
start=1;
}
else
{
if(TCNT1<20)
{

}
else
{

zdiff=TCNT1;

sprintf(buffer,"z=%d\r",(int)zdiff);
send_UART(&buffer[0]);
//calculate_speed(zdiff);
TCNT1=0;
}
}


}

von mario (Gast)


Lesenswert?

Wenn du ein Oszi hast dann einfach mal die Impulse festhalten und 
ausmessen. Wenn beim Polling in main und mit Isr diese "komischen" Werte 
kommen dann gibt das Rad vielleicht wirklich solche Impulse aus, oder Du 
hast ganz kurze Störimpulse, diese könntest Du wie folgt verhindern wenn 
Du auf die fallende Flanke triggerst:

SIGNAL(INT1_vect)
{
  // durch den Interruptaufruf sind schon ein paar us verstrichen, 
besser
  // hier noch ein paar us warten

  WaitUs(50);      // z.B. 50us warten

  if(!PortPin)     // dann pruefen ob PortPin wirklich low
  { if(start==0)
    { TCNT1=0;
      start=1;
    }
    else
    { if(TCNT1>20)
      { zdiff=TCNT1;

        sprintf(buffer,"z=%d\r",(int)zdiff);
        send_UART(&buffer[0]);
        //calculate_speed(zdiff);
        TCNT1=0;
      }
    }
  }
}

sonst habe ich keine Ideen mehr.

von wagner (Gast)


Lesenswert?

So  das sieht ja gut aus

z=2193
z=2299
z=2435
z=2583
z=2748
z=2917
z=3101
z=3293
z=3498
z=3723
z=3954
z=4199
z=4460
z=4740
z=5040
z=5361
z=5714
z=6085
z=6471
z=6825
z=7255
z=7851



nur noch ne kleine frage wie errechne ich

den zeitabstand oder umdrehungsfrequenz

8Mhz und prescaler 256 und 16Bit timer???

von Michael K. (mmike)


Lesenswert?

Bei 8 MHZ ist die "Tick - time" Deines Controllers bei

1 / 8e6 = 125ns

dann noch den Prescaler rein da jeder Tick ja nur bei jedem 256. ten mal 
ausgelöst wird:

1 TimerTick = 125ns * 256 = 32µs

Bei einem Timerwert von 2748 ergibt sich die Zeitdifferenz zu:

2748 * 32µs = 87936 µs = 87,936 ms

Ich gehe jetzt mal davon aus, dass pro Umdrehung ein Impuls ausgelöst 
wird somit mach Dein Teil XX Umdrehungen in der Sekunde:

1s / 87,936ms = 11,3719

das Ganze mal 60 für die U/min:

11,3719 * 60 = 682,3... U/min

von mario (Gast)


Lesenswert?

laut Datenblatt ist clkI/O gleich Systemtakt

bei 8MHz = 125ns

mit Prescaler 256 -> 32us

d.h. alle 32us inkrementiert Dein Timerwert

d.h. 2193 = 2193 * 32us = 70ms Periode = 14 Hz

(keine Garantie, aber muesste so stimmen, wie gesagt, die Atmel 
Controller kenne ich nicht)

von wagner (Gast)


Lesenswert?

Vielen Dank

float w=(float)TCNT1*32/1000L;
w=1000L/w;
w=w*60;
v=0.0006*40.841*(int)w;
v=v/1.852;

V in Kt

Leider das gleiche wie vorher ca 50% zu wenig.

was sit da los???

Danke

von Michael K. (mmike)


Lesenswert?

Oskar mal drangehabt ?

von mario (Gast)


Lesenswert?

Keine Ahnung wie Du auf Deine Rechnung kommst, es wäre leichter wenn Du 
Deine Rechenschritte kommentieren würdest.
Und stelle fest, wieviele Impulse pro Umdrehung aus dem Windmesser 
kommen, mit Durchangsprüfer und einmal drehen.

von Michael K. (mmike)


Lesenswert?

abo

von wagner (Gast)


Lesenswert?

Hallo


Die berechnung bis zur Drehzahl habe ich von Michael K genommen.

float w=(float)TCNT1*32/1000L;
w=1000L/w;
w=w*60;


Da bekomme ich umdrehung / min.


nach der Formel
v=radumfang(40.841)*n(U/min)*60/100000(in km/h)
v=0.0006*40.841*(int)w;
v=v/1.852;//umrechnung in KT


Danke

Aslo die Impulse stimmen jetzt er bringt im TCNT1 Register richtige 
werte.

z=2193
z=2299
z=2435
z=2583
z=2748
z=2917
z=3101
z=3293
z=3498
z=3723
z=3954
z=4199
z=4460
z=4740
z=5040
z=5361
z=5714
z=6085
z=6471
z=6825
z=7255
z=7851

von Michael K. (mmike)


Lesenswert?

Was ist KT ?
Willst du wirklich die Windgeschwindigkeit berechnen ?

von wagner (Gast)


Lesenswert?

ja kt = knoten

von Michael K. (mmike)


Lesenswert?

Was mir nicht klar ist wozu Du den Radumfang brauchst .....
Wenn du nen Propeller da dran hängen hast interessiert eher die Steigung 
des Props. Beschreib mal den Aufbau bzw. mach nen Bild....

von wagner (Gast)


Lesenswert?

Der Windmesser ist ein umgebauter Ws2500 von ELV.

Innenleben raus und nur noch der reedkontakt und das Poti ist drin 
Platine ist dem Orginal (von der dimension her ) nachempfunden.

von Michael K. (Gast)


Lesenswert?

Achso ....

alles klar. Die Geschwindigkeit eines Punktes auf einem rotierenden 
Gegenstand berechnet sich folgendermassen:

phi: Winkelgeschwindigkeit (in rad!)
r: Radius

Damit sollte es dann einfach sein, da Du die Winkelgeschwindigkeit ja 
direkt hast ! Danach rechnest Du einfach in die Einheit die Du willst 
...

von wagner (Gast)


Lesenswert?

Nach dieser Formel habe ich es berechnet.

V=2*pi*r(für umfang) * f

V= 2*pi*6,5cm * (2193==14Hz) *0,006(cm-Km/h)
V=3,36km/h


ist viel zu wenig

von Karl H. (kbuchegg)


Lesenswert?

0,006(cm-Km/h)

Diese Umrechnungskonstante kommt mir aus dem Bauch heraus
etwas wenig vor bzw. sieht überhaupt falsch aus.

Um m/s auf km/h umzurechnen multipliziert man mit 3.6.
Du hast nicht Meter sondern Zentimeter (was für ein Schwachfug
in einer klassischen Physikaufgabe in cm zu rechnen, anstatt
in der SI Einheit Meter. Wegen sowas (ähnlichem) sind der NASA
schon Sonden abhanden gekommen). Da muessen also mindestens die
Ziffern 3 und 6 in einer Umrechnungskonstante vorkommen.

(Die Details der Ableitung der Konstanten überlasse ich
dem geneigten Leser)

von Fred (Gast)


Lesenswert?

Hallo,
habe auch gerade ein Windmesser gebaut - muss ihn noch ausmessen und 
programmieren (Atmel).

Werde die Messung aber folgendermassen machen:
Eine Minute lang (od. eine halbe) die Impulse (ext. Interrupt) zählen.
Ich denke man braucht nicht im ms Takt einen Wert bei einer Windmessung.

Auf diese Weise bekomme ich aber auch Werte, wenn nur ganz wenig Wind 
ist und das Rad sich nur ab und zu mal dreht. Auch spare ich mir die 
Timer. (Sekundentakt habe ich schon).

Habe diesen Thread nicht komplett gelesen, wollte das nur mal als 
Alternative dazwischenwerfen.

von Karl H. (kbuchegg)


Lesenswert?

Dein Windrad hat also einen Radius von 6.5 cm oder 0.065 Meter.
Du hast 14 Umdrehungen in der Sekunde festgestellt.

D.h. eine Schale hat bei einer Umdrehung einen Weg von
 2  pi  0.065 = 0.40840 Meter zurückgelegt.
Nach 14 Umdrehungen also einen Weg von 14 * 0.40840 = 5.71769 Meter

Da du mal davon ausgehst, dass sich die Schalen genauso schnell
bewegen wie der Wind, heist das die Schale bewegt sich mit einer
linearisierten Geschwindigkeit von 5.71 m/s oder mal 3.6 = 20.58 km/h


(Das ist doch ein Schalenanemometer oder nicht? Mit der Angabe
"ws2500 elv" konnte ich das per Googlel nicht feststellen)

von Michael K. (mmike) (Gast)


Lesenswert?

völlig korrekt Karl Heinz.

Ich denke das ist das Teil:

http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=8337

von wagner (Gast)


Lesenswert?

es sieht jetz gut aus nach der formel von Karl heinz Buchegger.


vielen dank.

von Peter (Gast)


Lesenswert?

Ist wohl ein Witz, dass Du zuerst von einigen Leuten stundenlang Rat 
erhältst und dann bemerkst, dass Deine Formel nicht stimmt. Die Formel 
hast Du erst zum Schluss gepostet. Außerdem bin ich der Ansicht, dass so 
banale Fragen wie z.B. wie oft sich der Timer erhöht nicht beantwortet 
werden sollten - die Leute sind zu faul für einen Blicks ins Datenblatt 
- unglaublich!

von Karl H. (kbuchegg)


Lesenswert?

Peter wrote:
> erhältst und dann bemerkst, dass Deine Formel nicht stimmt. Die Formel
> hast Du erst zum Schluss gepostet. Außerdem bin ich der Ansicht, dass so
> banale Fragen wie z.B. wie oft sich der Timer erhöht nicht beantwortet
> werden sollten - die Leute sind zu faul für einen Blicks ins Datenblatt

Nein. Die Leute sind zu faul zum Rechnen geworden.
Q: 12 Prozent von 100?
A: Keine Ahnung, in Mathe war ich schon in der Schule schlecht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.