Fehlersuche.bekomms echt nicht hin

OP #1100968
Lesenswert?

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
Gast #1100998
Lesenswert?

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
Gast #1101046
Lesenswert?

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.
Persönliche Seite #1101094
Lesenswert?

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 ;-)
OP #1101126
Lesenswert?

:-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
Persönliche Seite #1101142
Lesenswert?

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.
Persönliche Seite #1101163
Lesenswert?

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
Gast #1101291
Lesenswert?

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
Gast #1101521
Lesenswert?

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.
Persönliche Seite #1101764
Lesenswert?

@ 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.
OP #1102033
Lesenswert?

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
Gast #1102611
Lesenswert?

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?
Persönliche Seite #1102696
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren