Forum: Mikrocontroller und Digitale Elektronik Fehlersuche.bekomms echt nicht hin


von M. G. (sirmel)


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

von spess53 (Gast)


Lesenswert?

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

von M. G. (sirmel)


Lesenswert?

Da hängt ein Tacho- Impulsgeber dran der, sobald der Magnet dran 
vorbeigeht einmal schaltet,also warscheinlich nix anderes als ein 
Schalter

von spess53 (Gast)


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

von M. G. (sirmel)


Lesenswert?

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

von spess53 (Gast)


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.

von Stefan B. (stefan) Benutzerseite


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 ;-)

von spess53 (Gast)


Lesenswert?

Hi

Was macht 'wait 1'?

MfG Spess

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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!!!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

von M. G. (sirmel)


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

von M. G. (sirmel)


Lesenswert?

@Stephan B.

Werden die Interrupts nich TROTZ wait eingeleitet? Wenn nich dann sry 
(weis es nicht besser, meine das nur so verstanden zu haben:))

von Stefan B. (stefan) Benutzerseite


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.

von Stefan B. (stefan) Benutzerseite


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

von M.G (Gast)


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

von M.G (Gast)


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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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

von M.G (Gast)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


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.

von M. G. (sirmel)


Lesenswert?

Hey super schon mal vielen Dank für die Rechnung=). Nein das mit der 
Displayausgabe ist leider immer noch nicht weg :/

von M. G. (sirmel)


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

von M.G (Gast)


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?

von Stefan B. (stefan) Benutzerseite


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

von M.G (Gast)


Lesenswert?

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=)

von M. G. (sirmel)


Lesenswert?

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
Noch kein Account? Hier anmelden.