PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Impulszähler zur drehzahlbestimmung in Basom



stevensen
01.03.2004, 14:43
Hallo zusammen,

hab ein Timingproblem mit dem avr s2313 und Bascom. Für meinen Roboter möchte ich per Gabellichtschranke die Impulse eines Rades über 1 Sekunde zählen. Die Taktfrequenz des 2313 ist 4096000 Hz. Wenn ich nun prescale für den Timer1 auf 1024 stelle und das reload auf 4000, dann zählt er 1 sekunde lang. Der Int0 zählt andauernd die Impulse am Rad. Wenn Timer1 startet übernimmt er den Zählerstand vom Int0, und löscht den Zähler, wenn er nach ner Sekunde wieder reinschaut, sind dann wieder die Impulse entsrechend angehäuft worden. Das müßte doch so gehen oder? Wenn ich das Programm laufen lasse scheint es zu gehen, wenn ich aber die Print ausgabe im Int0 weglasse kommen viel zu hohe Zahlen (siehe Listing). Und das ist mein Problem!! Außerdem braucht die Schaltung einige Sekunden bis der Timer1 richtig läuft!! Also irgendwas ist faul im listing. Hoffentlich hatt einer ne Idee.

Frank
01.03.2004, 17:52
Hi Stevensen,

so kurze Beispielprogramme am besten direkt in den Beitrag posten und mit CODE markieren. Dadurch kann man schneller reinschaun und helfen.
Bist du wirklich sicher das die Werte ohne PRINT zu hoch sind? Könnte es nicht vielmehr sein das die Werte mit dem Print zu klein sind? Der Print Befehl über RS232 ist ja relativ langsam, dadurch könnten Impulse verloren gehen.
Überprüf das doch nochmal genau und poste auch mal die Ergebnisse/Zahlen!

Gruß Frank



$regfile = "2313def.dat"
$crystal = 4000000
$baud = 9600
Const Reload = 4000

Dim Zaehler As Word
Dim Halbe As Byte
Dim Umdrehungen As Word
Config Portd = Output
Config Timer1 = Timer, Prescale = 1024


Config Int0 = Falling 'Low Level oder Falling

Portd 0.2 = 1
Portd 0.6 = 1

On Timer1 Timer1_isr
On Int0 Onrts

Umdrehungen = 0
Zaehler = 0

Enable Int0

Enable Timer1

Enable Interrupts

Print "los gehts"
Do

Print Umdrehungen

Loop

End


Timer1_isr:
Load Timer1, Reload

Portd.5 = Not Portd.5 ' Led togglet

If Portd.5 = 1 Then
Umdrehungen = Zaehler

'Print Umdrehungen
Zaehler = 0

End If
Return

Onrts:
Incr Halbe

If Halbe = 4 Then
Halbe = 0
Portd.6 = Not Portd.6
Incr Zaehler
Print Zaehler ' !!!!! Wenn diese Print Ausgabe vorhanden ist scheint es zu gehen, wenn sie fehlt kommen zu große Zahlen.

End If
'Int0-Routine
Return

Red Dragon
04.05.2004, 20:13
hallo,
ich möchte gerne mit meinem s4433 (4mhz)die daten meines futaba ppm empfängers auswerten.
dazu möchte ich jeweils die highzeiten messen, da diese variiren.
das was aus dem empänger rauskommt ist ein signal für servos welches ja bekanntlich eine lowzeit von etwa 20 ms hat und einer high-zeit im bereich von 1,1 bis 2,1 ms. leider durchschaue ich den obigen code nicht, sodass ich ihn auch nicht auf meine bedürfnisse umschreiben kann

Gottfreak
04.05.2004, 21:25
@stevensen: Das Programm sieht so aus, als könnte es höchstens mal Impulse "verpassen" (besonders mit dem Print im Interupt). Wenn tatsächlich zu viele 'rauskommen, könntest du höchstens noch extrem kurze(bis hinunter zur Größenordnung der Taktfrequenz) Störungen auf der Interuptleitung haben, die dann als Impulse verstanden werden (je nachdem, wie lange deine Impulse dauern, kannst du es ja mal mit 'nem geeigneten Kondensator probieren.). Wäre aber seltsam, wenn die sich mit den Verlusten durch Print ausgleichen würden. Hast du bei deinem Fehler bei jeder Geschwindigkeit gleich viele Impulse zu viel oder sind es um einen bestimmten Faktor zu viele?

@Red Dragon: Ein Programm zum "Verstehen" von Servosignalen hab' ich auch mal geschrieben (wenn dir das ASM-Programm hilft, kann ich es ja mal posten.).
Was verstehst du denn an dem Beispiel genau nicht?

Red Dragon
06.05.2004, 10:22
ASM hilft mir ledier noch weniger. Da ich ein basic autodidakt bin, bin ich froh das ich soweit basic kann. Doch die ganze sache mit den interrupts hab ich noch garnicht verstanden. Auch die bascomhilfe und google haben mich beim verstehen nicht wirklich weiter gebracht. welches interrupt für welchen port? wie den timer auswerten? bis jetzt war ich halt immer nur bei "normalem" AN/AUS-code um serielle oder paralelle signale auszuwerten oder mototren zu steuern.
habt ihr vielleicht ne internetseite zur einführung?

Gottfreak
06.05.2004, 11:51
@Red Dragon: Unter "ENABLE" und "ON" findest du in der Bascom-Hilfe, wie du Interupts verwendest (du bist bestimmt nicht der erste, der das nicht findet. Die Stichpunkte sind, wenn man nicht schon vorher weis, wie der Befehl heist, nicht gerade naheliegend.).
Welcher davon welchem Port/Pin entspricht, steht im Datenblatt zum AVR (Pinbelegung).


wie den timer auswerten?

"Config Timer0 = Timer" und
"Start Timer1" (oder Timer0) macht den jeweiligen Timer an.
"Timer1=0" setzt ihn zurück
"Variable=Timer1" liest den Wert in eine andere Variable ein.
In der Hilfe zum Timer steht, welcher Zeit das dann entspricht.

Eine nette Seite dazu kannte ich mal, aber die hab' ich jetzt nicht gefunden.

06.05.2004, 17:40
ich hab mir jetzt mal aus allem was ich gefunden habe was zusammengesucht. gefunzt hat es leider nicht :(



Config Timer1 = Counter , Edge = Rising
On Timer1 Timer1over
Enable Timer1
Enable Interrupts
Timer1 = 0
Dim Zeit As Integer
Do
Lcd Zeit
Loop


Timer1over:
Zeit = Timer1


bitte um hilfe und verbessreung

Michael
06.05.2004, 17:46
Hallo Gast,
was grundsätzliches:
1.Du musst den Timer auch starten (vgl.Gottfreak's Posting)
2.Ein Sprung in eine (Unter-)Routine braucht ein Return.
Gruss, Michael

06.05.2004, 18:23
aber auch so


Config Timer1 = Counter , Edge = Rising
On Timer1 Timer1over
Enable Timer1
Enable Interrupts
Start Timer1
Timer1 = 0
Dim Zeit As Integer
Do
Lcd Zeit
Loop


Timer1over:
Zeit = Timer1
return
klappt es nicht. ich bin halt noch nicht so erfahren in bascom und mit den avrs wie manch anderer hier.

Michael
06.05.2004, 18:38
Hallo Gast,
das funktioniert schon, leider wissen wir nicht, was du mit dem Interrupt machen willst.Und deinem Programm hast du es auch nicht gesagt...
Ausserdem fällt es mir beim Namen 'Gast' nicht leicht, die Beiträge zuzuordnen :( (Du könntest sowohl stevensen als auch Red Dragon sein. Beide benutzen z.B.verschiedene Controller...)
Gruss, Michael

Gottfreak
06.05.2004, 19:12
Nach was, Gast:
Du schreibst:
Config Timer1 = Counter , Edge = Rising
Du willst aber doch sicher einen selbstlaufenden Timer und keinen Counter, der steigende Flanken an einem Pin deines AVR zählt. Also:
Config Timer1 = TIMER, prescale = 64
Der prescale-Wert sagt dem Timer, dass er nicht jeden Takt (also bei 4MHZ 4mio mal je Sekunde) sondern nur jeden 64sten hochzählen soll, was genau genug ist.
Dein Interupt löst übrigens immer dann aus, wenn der Timer überläuft. Also gerade dann, wenn er wieder bei 0 ist(oder vielleicht schon bei 1 oder 2). Das ist der denkbar schlechteste Zeitpunkt um seinen Wert abzufragen (überhaupt brauchst du zum Verstehen von Servosignalen den Timer-Interupt garnicht, weil die Pulse so kurz sind, dass der Timer, wenn du ihn bei deren Beginn zurücksetzt garnicht überläuft, bis sie vorbei sind.).

Red Dragon
06.05.2004, 19:13
sry war unter andrem browser drinne.
Also ich möchte das der timer mir über die comschnittstelle die zeit des highsignals mitteilt.
Ich weiß nur nicht in welche stelle des programms/interrupts ich es stellen muss damit eine vernünftige zahl herrauskommt (im momentk ommt ja garkeine herraus)

Gottfreak
06.05.2004, 19:23
Hier mal eine Variante, die dir die Zeit zwischen dem Ansteigen und dem Fallen eines Signals ausgibt. Das Ausrechnen, durch was du teilen musst um auf 'ne sinnvolle Zeiteinheit zu kommen, überlasse ich mal dir.


$regfile = "4433def.dat"
$crystal = 4000000
$baud = 9600
Config Timer1 = Timer , Prescale = 8
Start Timer1
On Int0 C1rise : On Int1 C1fall
Enable Int0 Rising : Enable Int1 Falling
Enable Interrupts
do
loop 'Endlosschleife
C1rise: 'Bei Beginn den Timer zurücksetzen
timer1=0
return
C1fall: 'Am Ende steht in timer1 drin, wie lange das Signal an war.
print timer1
return

PS: Ich hab' keine Ahnung, wie lange die Print-Befehl von Bascom braucht.

Red Dragon
07.05.2004, 17:18
vielen dank schonmal.
mit dem obigen code (allesdings mit nosave) kommt soetwas an:

65042
3
2
42679
2
2
2
2
2
2
2
55647
2
2
3
2
2
3
2
64746
3
24588
2
2
2
2
3
2
56860
3
24437
3
24543
2
43786
(nur ein auszug)
ich habe mir gedacht das der print befehl vielleicht zu langsam sein könnte. also habe ich mit eine led geschnapp und den code soweit verändert.

$regfile = "4433def.dat"
$crystal = 4000000
$baud = 9600
Config Timer1 = Timer , Prescale = 8
Start Timer1
On Int0 C1rise Nosave : On Int1 C1fall Nosave
Enable Int0 Rising : Enable Int1 Falling
Enable Interrupts
Dim Zeit As Integer

Config Portd = Output


Do
Loop 'Endlosschleife
C1rise: 'Bei Beginn den Timer zurücksetzen
Timer1 = 0
Return
C1fall:
Zeit = Timer1
If Zeit > 750 Then
Portd.2 = 1
Else
Portd.2 = 0
end if
Return

ich habe mich gewundert warum denn die LED nicht leuchtet. Sie tat es doch, nur gaaanz wenig. Daraufhin habe ich mich im internet einmal nach einer osciloscopimprovisierung für den pc umgesehen. Für die soundkarte habe ich dann auch etwas gefunden. also erstmal das unbearbeitete servosignal angeschaut. Dann das des pins für die LED.
Und siehe da die LED bekommt jedesmal wenn das servosignal high ist eine flanke genausolang wie die highphase.

Ausgerechnet habe ich das bei einem prescale von 8 (einer auflösung von 2 µS) und einer signallänge von 1 - 2 ms eine zahl von 500 - 1000 im timer stehen müsste. (daher die zahl 750) Ich dachte also die LED müsste auf halben vollausschlag umspringen. Leider war dem nicht so. bitte helft mir den denkfehler zu finden