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; } }
Kann es sein, dass Du nur die halbe Periode misst? ____________ _________ | | | ______| |______________|
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?
Ja das ist wie schon gesagt die bessere variante. Ich werde mal deise Variante ausprobieren ich hoffe ich bekomme hin. Danke
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
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 ist KT ? Willst du wirklich die Windgeschwindigkeit berechnen ?
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 ...
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
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)
völlig korrekt Karl Heinz. Ich denke das ist das Teil: http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=8337
es sieht jetz gut aus nach der formel von Karl heinz Buchegger. vielen dank.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.