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
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;
}
}
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.
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?
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.
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;
}
}
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.
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.
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
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;
}
}
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
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.
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.
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;
}
}
}
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.
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???
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
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)
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
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.
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
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....
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.
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
...
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)
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.
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)
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!
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.