Nabend zusammen, Eigentlich sehr leicht das Programm aber ich bekomm es nicht zum Laufen $regfile = "m32def.dat" $framesize = 128 $swstack = 128 $hwstack = 128 $crystal = 8000000 $baud = 9600 $lib "glcdKS108.lib" Config Timer1 = Timer , Prescale = 8 Enable Timer1 On Timer1 Auswertung Timer1 = 55535 Enable Interrupts Config Int2 = Falling Enable Int2 On Int2 Check Dim Cnt As Integer , Cntalt As Integer Dim Umfang as Integer, Ms as Integer Umfang = 1850 Do Ms=Umfang/cntalt Lcdat 5,20,Ms wait 1 Loop End Check: Cntalt = Cnt Cnt = 0 Return Auswertung: Timer1 = 55535 Cnt = Cnt + 1 Return Ich bekomme als Displayausgabe immer "0" angezeigt. Sobald ich cntalt durch cnt ersetze, bekomme ich das richtige ergebnis. Was ist falsch? Mfg
Hi Was hängt den an deinem INT2. Falls das ein Schalter ist, besteht die Möglichkeit, das dein cntalt überschrieben wird, bevor es die Ausgabe erreicht. MfG Spess
Da hängt ein Tacho- Impulsgeber dran der, sobald der Magnet dran vorbeigeht einmal schaltet,also warscheinlich nix anderes als ein Schalter
Hi Wenn das Teil prellt, also mehrmals kurz hintereinander schaltet wird jedes mal 'Check' aufgerufen. Beim ersten mal wird cnt=0. Das bekommt beim zweiten Mal dein 'cntalt' und ist Null. MfG Spess
Hmm das könnte sein aber warum geht es dann wunderbar, wenn ich statt cntalt cnt verwende? das müsste doch die selben Werte annehmen
Hi
> das müsste doch die selben Werte annehmen
Gute Frage. Aber kurz nach dem Prellen schlägt dein Timerinterrupt
wieder zu. Ich bin nicht sehr firm in BASCOM und der Zweck deines
Programms entzieht sich mir auch etwas. Aber wenn ich davon ausgehe, das
dein Timerinterrupt der Overflowinterrupt mit einem Preload von 55535
ist, sollte der alle 10ms kommen. Wenn der Abstand der INT2-Auslösung >>
10ms ist, wirst du durchaus logische Werte bekommen.
MfG Spess
P.S. '>>' als 'gross gegen ' interpretieren.
Unterscheidet BASCOM Gross- und kleinschreibung bei den Variablen? Bei den Line Labels tut es das nicht, bei den Variablen finde ich keine Angabe im Manual. Nur wegen diesem Punkt: > Dim Cnt As Integer , Cntalt As Integer > Ms = Umfang / *cntalt* Ich versuche mal zu verstehen, was das Programm macht: Auswertung: Timer1 Overflow tritt alle 10ms auf. Die Zahl der Overflows wird in Cnt gezählt. Check: Bei einer fallenden Flanke soll INT2 ausgelöst werden. Beim INT2 wird die Anzahl der Overflows in Cntalt gesichert und Anzahl der Overflows zurück gesetzt. Wenn dein INT2 nicht funktioniert (Initialisierung OK? Hardware OK? Eine Debug-LED im INT2 toggeln wäre jetzt schlau!), dann bleibt Cntalt immer 0... Hauptprogramm: Ms = 1850 / (Anzahl Overflows von fallender Flanke zu fallender Flanke). Wenn nur ein Geber an dem Rad ist, entspricht die Zeit zwischen 2 INT2 einer Radumdrehung. Die Zeit zwischen zwei INTs ist die Anzahl Ticks der 10ms Uhr (cntalt). Wenn die Wegstrecke einer Radumdrehung bekannt ist (Umfang 1850) ergibt sich die Geschwindigkeit durch Umfang dividiert durch Anzahl der 10ms Ticks. Das Messverfahren ist so nur möglich, wenn eine geradzahlige Anzahl von INT2 gemessen wurden ("von Flanke zu Flanke"). In der Zeit vor der ersten Flanke ist Cntalt = 0, d.h. Division durch Null bei Ms=... Die Auswertung ist sinnlos. In der Zeit zwischen erster Flanke und zweiter Flanke ist Cntalt die zufällige Anzahl der Overflows bis zur ersten Flanke. Die Auswertung ist sinnlos. In der Zeit nach der zweiten Flanke vor der dritten Flanke, kann die Geschwindigkeit zur Zeit der vorherigen Umdrehung sinnvoll berechnet werden... Die Genauigkeit kann gesteigert werden, wenn zusätzlich der Zählerstand in TCNT1 berücksichtigt wird. Derzeit kann der Startwert und der Endwert der Zeitmessung je maximal 10ms daneben liegen. In Summe also Maximalfehler 20ms bzw. zwei Ticks. Rein aus Neugier - Mit welchen wahnsinnigen Geschwinigkeiten gehst du da um? Vmax: 1850/1 => 1 Umdrehung/(1*10ms) => 1850 m/s => 6660 km/h Vmin (Grenze ist Überlauf in den Integervariablen Cnt und Cntalt): 1 Umdrehung/(32767*10ms) => 1 Umdrehung / ca. 5,5 Min. => 20,3 km/h Für's Fahrrad wäre das anspruchsvoll: Beim Testen musst du ordentlich in die Pedale treten ;-)
Stefan B. wrote: > Vmin (Grenze ist Überlauf in den Integervariablen Cnt und Cntalt): 1 > Umdrehung/(32767*10ms) => 1 Umdrehung / ca. 5,5 Min. => 20,3 km/h Korrektur: Wenn deine Formel genommen wird gilt Vmin = 1850/32767 => 0,2 km/h Der Messbereich wäre so OK. Entwarnung du brauchst nicht so stark zu strampeln!!!
spess53 wrote: > Was macht 'wait 1'? ca. 1 Sekunde in Software d.h. ohne Timer warten. Quasi ein _delay_ms(1000). *BASCOM AVR Manual* http://avrhelp.mcselec.com/index.html
:-D nich schlecht nich schlecht=) Nein die geschwindigkeit sollte eig. im Bereich von 0-200 Km/h liegen und das soll ein Tacho für mein Motorrad werden. Das problem wa sih vorher hatte war, dass ich den Cnt nie richtig auswerten konnte, da dieser erst immer nach einer Sekunde ausgewertet wurde (Wait 1 in der Main). Daher konnte der Cnt auch rein zufällig grade wieder "0" sein, und die Auswertung sinnlos. Deshalb wollte ich den letzt hövhsten Wert speichern (cntalt) und das ergebnis mit diesem Auswerten. ALso hab ich mir obrigen Programmcode ausgedacht, der leider nicht das tat was er tuen sollte=). Im Normalfalle sollte der cnt nicht den Wert 1 erreichen, sodass keine Km/h von 6600 möglich ist. Das Programm ist leider noch nicht ausgereicft, da ich noch vor den "Stadartproblemen" stehe, Für Anregungen bin ich dankbar=). Das Wait 1 soll mir einfach nur das Display nach einer Sek aktualisieren. TCNT1 sagt mir nix sorry. Aber warum kann das Ergebnis nur stimmen, wenn eine grade Anzahl von INT2s vorhanden ist? INT2 soll doch nur die Zeit für eine Radumdrehung ermitteln. ALso ist INT2 doch immer "1" oder nicht? Mfg
@Stephan B. Werden die Interrupts nich TROTZ wait eingeleitet? Wenn nich dann sry (weis es nicht besser, meine das nur so verstanden zu haben:))
Doch doch. Das WAIT ist "schwächer" als der Timer1. Der Timer1 und der INT2 unterbrechen WAIT, wenn es sein muss. Daher ist WAIT nicht genau. Das ist hier aber egal. TCNT1 ist der Timer1 Zähler, der bei dir von 55535 bis 65535 hochgezählt wird und dann den Overflow auslöst. Im Extremfall sind das ja auch noch 10000 Takte Messzeit. Der Name steht auch so im Datenblatt des AVRs. 1. KEIN INT2 aufgetreten: In der Zeit vor der ersten Flanke ist Cntalt im Programm 0, d.h. Division durch Null bei Ms=... Die Auswertung ist sinnlos. 2. EIN INT2 aufgetreten: In der Zeit zwischen erster Flanke und zweiter Flanke ist Cntalt die zufällige Anzahl der Overflows bis zur ersten Flanke. Die Auswertung ist sinnlos. 3. ZWEI INT2 aufgetreten: In der Zeit nach der zweiten Flanke vor der dritten Flanke, kann die Geschwindigkeit zur Zeit der vorherigen Umdrehung sinnvoll berechnet werden... 4. DREI (und folgende) INT2 aufgetreten: Hast Recht! Sorry. Unschön ist das Verhalten beim Stehenbleiben. Die Anzeige geht nicht auf 0 zurück. Bau dir unbedingt zum Debuggen was ein, das dir anzeigt, ob die INT2 auch wirklich kommen. Meine erste Idee war eine LED toggeln. Du kannst auch eine Variable in Check hochzählen, auf dem LCD anzeigen und die Zahl mit den manuellen Radumdrehungen vergleichen. Dann siehst du, ob Prellen stattfindet und ob du was dagegen machen musst. Später, solltest du dir mal den Artikel Drehgeber ansehen und welche Haken bei der "billigen" Auswertung mit Flankenerkennung auftreten können.
M. G. wrote: Diese Abfolge gefällt mir noch nicht: > Config Timer1 = Timer , Prescale = 8 > Enable Timer1 > On Timer1 Auswertung > Timer1 = 55535 > Enable Interrupts > > Config Int2 = Falling > Enable Int2 > On Int2 Check Logischer ist alles vorzubereiten und dann erst die Interrupts einzuschalten. Config Timer1 = Timer , Prescale = 8 On Timer1 Auswertung Timer1 = 55535 Enable Timer1 Config Int2 = Falling On Int2 Check Enable Int2 Enable Interrupts ' ab hier laufen Timer1 und Int2 tatsächlich
Ja dass die Anzeige noch nicht zurückgeht hat mich auch schon beschäftigt aber da werd ich mir schon noch was ausdenken=). Der INT2 kommt auf jeden fall bei jeder Umdrehung das hab ich schon alles ausprobiert. Werd mich später mal mit dem Drehgeber beschäftigen. Erst mal vielen Dank vllt bekomm ichs ja noch ans Laufen. Sonst meld ich mich noch mal Mfg
Ach folgendes: Wenn ich einen 10ms Interrupt nehme habe ich bei hohen Geschwindigkeiten riesen Sprünge richtig? Hab mal nachgerechnet bei 30ms fahre ich 222km/h, bei 40ms jedoch nur 166.5 km/h! Also wäre doch eine Teilung von 10ms viel zu wenig oder? Mit 1ms habe ich bei hohen Geschwindigkeiten aber auch Sprünge von ca. 8 km/h (33ms = 201 km/h, 32ms = 208 km/h). Also sollte ich mir was komplett neues ausdenken richtig? Meine Maschine schafft zwar keine 200km/h aber kleinere Sprünge sind ja auch unter 200 km/h vorhanden.
> Also sollte ich mir was komplett neues ausdenken richtig?
Wie wäre es, die Zeit zwischen zwei Tacho-Impulsen mit einem 16
Bit-Timer (also Hardware) zu messen?
1. Impuls --> Timer auf 0 setzen und starten
2. Impuls --> Timerwert auslesen und weiterverarbeiten
3. Impuls siehe 1. Impuls
Dann müsste ich nur ermitteln was für eine Zeit dem Zählerwert entspricht richtig? Bzw. bei 8Mhz Quarz weis ich doch dass der Timer 8Mhz Takte in der Sekunde rausgibt und kann das danach auswerten
@ M.G.
Stimmt.
Radumfang: 1,85 m
Radradius: 0,294 m (= 1,85m/(2*Pi))
Tatsächliche Geschwindigkeit:
200 km/h = 55,6 m/s
1,85 m / 55,6 m/s = 0,0333 s => 33,3 ms pro Radumdrehung
Gemessene Geschwindigkeit:
33,3ms liefert 3 Ticks (10ms Overflows). 3,3ms werden durch das
Messverfahren der Oberflows alleine nicht berücksichtigt. Sie stecken
aber auslesbar im Timer1 Register!
1,85m / 0,03s = 61,7 m/s = 222 km/h
Werte unbedingt in Check nicht nur die Zahl der Overflows sindern auch
noch den Stand in Timer1 aus! Im Detail brauchst du die Zahl der im
Timer1 bereits abgeleisteten Takte seit der letzten Initialisierung auf
55535
, also (Timer1Istwert-55535). Die komplette Formel sieht dann so aus:
Ms = 1,85 / ((0,01 * Cntalt) + ((Timer1Istwert-55535) * 0,01/10000))
BTW: Ist eigentliche Problem schon gelöst?
> Ich bekomme als Displayausgabe immer "0" angezeigt.
Hey super schon mal vielen Dank für die Rechnung=). Nein das mit der Displayausgabe ist leider immer noch nicht weg :/
So hab grad festgestellt dass ich schonmal bei einem INT2 Interrupt zwei mal in die Check schleife komme. Der Interrupt wird also beim vorbeiführen des magneten zwei mal ausgelöst, was schon mal blöd ist. Daher ist cntalt auch "0", da er direkt mit dem zweiten Interrupt überschrieben wird, welcher "0" ist
Also wenn ich mit Integer rechne (Also alles as Integer definiert) hab ich keine Probleme mit der Anzeige. Sobald ich aber die Variablen als Single definiere, bekomme ich immer probleme bei der Displayausgabe. Liegt das an den langen Rechenzeiten mit Single?
Ja, die lange Rechenzeit wird in den Interruptroutinen Check und Auswertung kritisch sein. Wie sieht es aus, wenn du nur Ms als Single definierst? In dem Hauptprogramm ist die Rechenzeit fast egal (zur Not WAIT durch WAITMS ersetzen und dabei Wartezeit verkürzen).
1 | Dim Ms as Single |
2 | Dim Umfang as Integer |
3 | Umfang = 1850 |
4 | |
5 | ' ### Hauptprogramm ### |
6 | Do |
7 | Ms = Umfang |
8 | Ms = Ms / Cntalt |
9 | Lcdat 5, 20, Ms |
10 | Wait 1 |
11 | Loop |
12 | End |
Werd ich nachhher mal ausprobieren. Dachte es ist egal, wo ich die Daten für Ms ausrechne...hab die bis jetzt immer in den Interrupts ausgerechnet. Mal schauen vllt gehts ja mit der Hauptschleife=)
So klappt alles wunderbar vielen Dank für eure Hilfe Leute, vorallem @ Stefan B. :)
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.