PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ?? Falsche Taktfrequenz vorgaukeln bei ATMega8 ??



Powell
03.07.2007, 20:10
Hallo,

es geht um folgendes: Ich habe eine Anwendung mit Display und schnell wechselnden Werten.
In der Hauptschleife befindet sich ein gosub befehl über den in jedem Programmdurchlauf ein mal das Sub zur aktualisierung der Displaywerte aufgerufen wird.

Wenn das Programm läuft werden die Displaywerte aber für diese Verhältnisse sehr langsam aktualisiert (ich schätze mal so alle 10-50ms), jedenfalls ist ein ganz leichtes flackern beim überschreiben zu sehen, wenn sich ein Wert schnell ändert (man dreht z.B. schnell ein Poti) dann scheint er zu springen. Das ist sehr unschön und auch die Tasterabfrage läuft so schlecht, dass gern mal ein Tastendruck der per debounce in der Hauptschleife einfach "übersehen" wird.

Wenn ich nun den $crystal auf 1.600.000 statt 16.000.000 stelle, funktioniert alles wunderbar so wie ich das möchte.

Jetzt bin ich etwas irritiert: Ich dachte bisher immer, dass pro Takt ein kompletter Programmdurchlauf stattfindet. Nach dieser Feststellung wäre das aber widerlegt.

Kann mir jemand genauer erklären was es mit dem Verhältnis von Taktfrequenz und Programmabarbeitung auf sich hat?
Und wie kann ich dann errechnen wie lange ein Programmdurchlauf dauert? (bei mir scheint es im Moment im Millisekundenbereich zu sein was ich für höchst unglaubwürdig halte)
Und vor allem: Wer hat eine Idee wie ich mein Problem lösen kann ohne dem Controller einen falschen Takt vorgaukeln zu müssen?

Edit: Ja ich habe einen 16Mhz externen Quarz auf dem Board, Ich habe auch das Fusebit in Bascom geändert (1111: External XTAL)

shaun
03.07.2007, 21:15
Ohoh, massive Fehlinformiertheit. Ein Taktzyklus führt bei den AVRs idR einen Maschinen(!!!)befehl aus, einer Deiner Basic-Befehle kann zu einigen zehn Maschinenbefehlen führen, Du bist da ziemlich komplett dem Compiler ausgeliefert. Mit C sieht's etwas besser aus, aber wirklich ausrechnen kann man das nur im Maschinencode. Millisekunden ist aber durchaus denkbar.

Powell
03.07.2007, 21:18
und wäre es dann legitim mein Problem mit dem vorgaukeln einer geringerer Taktfrequenz zu lösen? Ich verstehe dann aber immer noch nicht wie er das Programm dann schneller abarbeitet, bleibt doch die Anzahl der Befehle und die tatsächliche Taktfrequenz die gleiche

BlooD
03.07.2007, 21:25
Also mit Bascom kenne ich mich nicht aus, aber es wird definitiv nicht mit jedem Takt das Programm einmal durchlaufen! Das kann ja auch nicht sein, weil ein großes Programm (in der Regel) viel länger braucht.

Jeder Befehl braucht einige Takte zeit, genau weiß ich auch nicht wieviel...
Noch als Hinweis: Beim AVRStudio kann man die Takte und die benötigte Zeit ablesen, die benötigt werden in der Simulation. Geht vielleicht bei Bascom auch?

Und noch was:
Der Schwindel mit der Frequenz könnte sich auf Pausenzeiten auswirken, hast du welche drin, dann mach die mal kürzer?!

Powell
03.07.2007, 21:44
Hi,

also ich poste euch mal meinen code. ich habe einen waitms befehl drin und einen pulsein befehl. Allerdings ändert sich an der Tatsache auch nichts wenn ich die beiden befehle aus dem Programm nehme, habe ich eben ausprobiert.


'************************************************* ******************************
'* PROGRAMM: RPM-ControllerV1.0BETA DATUM: 02.07.2007 *
'************************************************* ******************************

'================================================= ==============================
' Hardware:
'
' RN-Minicontrol Controllerboard mit Mega8
'
' RPM-Controllermodul V1.0, Anschluss an JP5 von RN-Minicontrol
'
' RN-LCD-Adaptermodul, Anschluss an 10-pol Wannenbuchse CTRL, Anschluss der
' LCD Bedientaster: T1 an JP6/1, T2 an JP6/2, GND an JP6/4, T3 an JP1/1
'
' Potentiometer an JP3
'
'
'
'================================================= ==============================



'================================================= ==============================
' Compiler
'================================================= ==============================
$regfile = "m168def.dat" 'Mega8
$crystal = 16000000 '16Mhz Quarz
'$baud = 9600
'-------------------------------------------------------------------------------


'================================================= ==============================
' Ein- und Ausgänge:
'
' PD4: Ausgang, Ansteuerung von ZU-Relais
' PB4: Eingang, Rechtecksignal der Zündspannung
' PC1: ADC1 Eingang, Potentiometer von JP4 zur Drehzahleinstellung
' PD5: Eingang, LCD Taster 1
' PB2: Eingang, LCD Taster 2
' PD2: Eingang, LCD Taster 3
'
'
'================================================= ==============================

Config Pind.4 = Output 'ZU-Relais
Config Pinb.4 = Input 'Zündspannung
Config Pinc.1 = Input 'Poti
Config Pind.5 = Input
Portd.5 = 1 'Taster1
Config Pinb.2 = Input
Portb.2 = 1 'Taster2
Config Pind.2 = Input
Portd.2 = 1 'Taster3
'-------------------------------------------------------------------------------

'================================================= ==============================
' ADC-Kanäle
'================================================= ==============================
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc

Config Debounce = 5
'-------------------------------------------------------------------------------

'================================================= ==============================
' Variablen
'================================================= ==============================
Dim Signal_in As Word 'eingangsimpulse in 1x10µs
Dim Rpm_ist As Long 'Istwert Drehzahl
Dim Adc1 As Word 'Eingangswert Poti 0-1023
Dim Rpm_soll As Word 'Sollwert Drehzahlbegrenzung
Dim Faktor As Byte 'Drehzahlfaktor
Dim Unterbrecherdauer As Byte 'Einschaltdauer Unterbrecher
Dim Unterbrecherfrequenz As Byte 'Zuschaltfrequenz Unterbrecher
Dim Timerunterbrecher As Byte 'Timing für Unterbrecher
Dim Rpm_dif As Word 'Differenz Soll und Ist
'-------------------------------------------------------------------------------

'================================================= ==============================
' Variablenvoreinstellung bei Programmstart
'================================================= ==============================
Faktor = 1
Unterbrecherdauer = 10
Unterbrecherfrequenz = 200
'-------------------------------------------------------------------------------


'================================================= ==============================
' Subs
'================================================= ==============================
Declare Sub Displayaktualisierung
Declare Sub Faktoreinstellung
Declare Sub Unterbrecherdauer
Declare Sub Unterbrecherfrequenz
Declare Sub Unterbrecher
'-------------------------------------------------------------------------------

'================================================= ==============================
' LCD Parametrieren
'-------------------------------------------------------------------------------

Config Lcd = 20 * 4a , Chipset = Ks077
Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.0 , Db6 = Portd.7 , Db7 = Portd.6 , E = Portb.3 , Rs = Portc.2
Config Lcdbus = 4

Initlcd

Config Pind.3 = Output 'R/W = 0 -> Schreiben
Portd.3 = 0

Config Pinc.3 = Output 'Portc.3 = 0 -> Beleuchtung aus
Portc.3 = 0

Waitms 200

Initlcd

Locate 1 , 1
Cls
Locate 2 , 1
Cls
Locate 3 , 1
Cls
Locate 4 , 1
Cls

'************************************************* ******************************
'* HAUPTPROGRAMM *
'************************************************* ******************************

Do


'================================================= ==============================
' Datenerfassung Drehzahl
'-------------------------------------------------------------------------------

'Pulsein Signal_in , Pinb , 4 , 0

Rpm_ist = 1500000 / Signal_in

Rpm_ist = Rpm_ist * Faktor

'-------------------------------------------------------------------------------

'================================================= ==============================
' Aufruf Displayaktualisierung
'-------------------------------------------------------------------------------


Gosub Displayaktualisierung


'-------------------------------------------------------------------------------

'================================================= ==============================
' Counter für Zündunterbrechung
'-------------------------------------------------------------------------------

Incr Timerunterbrecher

If Timerunterbrecher = Unterbrecherfrequenz Then
Gosub Unterbrecher

End If

'-------------------------------------------------------------------------------

'================================================= ==============================
' Abfrage Tastereingabe
'-------------------------------------------------------------------------------

Debounce Pind.2 , 0 , Faktoreinstellung , Sub

Debounce Pind.5 , 0 , Unterbrecherdauer , Sub

Debounce Pinb.2 , 0 , Unterbrecherfrequenz , Sub

'-------------------------------------------------------------------------------

Loop


'-------------------------------------------------------------------------------

'************************************************* ******************************
'* SUBS *
'************************************************* ******************************


'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Sub Displayaktualisierung
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

'================================================= ==============================
' Zeile 1: Anzeigen der Ist-Drehzahl
'-------------------------------------------------------------------------------
If Rpm_ist < 5000 Then

Locate 1 , 6
Lcd " "

Locate 1 , 1
Lcd "RPM= " ; Rpm_ist
Locate 1 , 10
Lcd "U/min"




End If
'-------------------------------------------------------------------------------


'================================================= ==============================
' Zeile 1: Bargraph-Animation
'-------------------------------------------------------------------------------

Rpm_dif = Rpm_soll - Rpm_ist

Locate 1 , 16
Lcd " "

If Rpm_dif < 2000 Then
Locate 1 , 16
Lcd "> "
End If

If Rpm_dif < 1600 Then
Locate 1 , 16
Lcd ">> "
End If

If Rpm_dif < 1200 Then
Locate 1 , 16
Lcd ">>> "
End If

If Rpm_dif < 800 Then
Locate 1 , 16
Lcd ">>>> "
End If

If Rpm_dif < 400 Then
Locate 1 , 16
Lcd ">>>>>"
End If


'-------------------------------------------------------------------------------


'================================================= ==============================
' Zeile 2: Anzeige Soll-Drehzahl
'-------------------------------------------------------------------------------

Locate 2 , 11
Lcd " "

Adc1 = Getadc(1)
Rpm_soll = Adc1 * 15

Locate 2 , 1
Lcd "RPM-Limit=" ; Rpm_soll
Locate 2 , 16
Lcd "U/min"

'-------------------------------------------------------------------------------


'================================================= ==============================
' Zeile 3: Anzeige Drehzahlfaktor
'-------------------------------------------------------------------------------

Locate 3 , 16
Lcd " "

Locate 3 , 1
Lcd "Drehzahlfaktor " ; Faktor

'-------------------------------------------------------------------------------


'================================================= ==============================
' Zeile 4: Anzeige Unterbrecherdauer und -Frequenz
'-------------------------------------------------------------------------------

Locate 4 , 7
Lcd " "
Locate 4 , 18
Lcd " "

Locate 4 , 1
Lcd "Dauer=" ; Unterbrecherdauer
Locate 4 , 10
Lcd "ms"
Locate 4 , 13
Lcd "Freq=" ; Unterbrecherfrequenz


'-------------------------------------------------------------------------------


End Sub
'================================================= ==============================



'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Sub Faktoreinstellung
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

If Faktor = 1 Then

Faktor = 2
Return

End If


If Faktor = 2 Then

Faktor = 4
Return

End If


If Faktor = 4 Then

Faktor = 1
Return

End If



End Sub
'================================================= ==============================


'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Sub Unterbrecherdauer
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

Unterbrecherdauer = Unterbrecherdauer + 10

If Unterbrecherdauer > 150 Then
Unterbrecherdauer = 10
End If



End Sub
'================================================= ==============================


'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Sub Unterbrecherfrequenz
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

Unterbrecherfrequenz = Unterbrecherfrequenz + 10

If Unterbrecherfrequenz > 240 Then
Unterbrecherfrequenz = 50
End If

End Sub
'================================================= ==============================


'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Sub Unterbrecher
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

If Rpm_ist > Rpm_soll Then
Portd.4 = 1
'Waitus Unterbrecherdauer
Portd.4 = 0
End If

End Sub
'================================================= ==============================


'===
End
'===

Powell
03.07.2007, 22:36
Hmm... mein Verdacht fällt immer mehr auf die Fusebits...

Dort kann man mehrere Ext. Crystals auswählen aber von 16 Mhz ist da nie die Rede. Auch im Datenblatt steht was von "For resonators, the maximum frequency is 8 MHz with CKOPT unprogrammed and
16 MHz with CKOPT programmed."
Was bitte ist jetzt CKOPT, und was bedeutet CKOPT programmed?

JanB
04.07.2007, 06:37
Hallo,
einige Zeilen höher im Datenblatt ist auch die Funktion der CKOPT Fuse
beschrieben:

"The CKOPT Fuse selects between two different Oscillator amplifier modes.
When CKOPT is programmed, the Oscillator output will oscillate a full
rail-to-rail swing on the output. This mode is suitable when operating
in a very noisy environment or when the output from XTAL2 drives
a second clock buffer. This mode has a wide frequency range.
When CKOPT is unprogrammed, the Oscillator has a smaller output swing.
This reduces power consumption considerably. This mode has a limited
frequency range and it cannot be used to drive other clock buffers."

Gruß Jan

Powell
04.07.2007, 08:24
Hi,

ja, das habe ich mir auch durchgelesen, bloß finde ich im Bascom programmer weit und breit nichts vom CKOPT :(

Ich müsste nur wissen wie man in Bascom einstellt dass man einen externen Quarz verwendet, dann wäre ich schon glücklich.

zumgwadrad
04.07.2007, 08:35
Hi,
ich stelle mir meine Fuses immer mit PonyProg ein! Ist schön buntes Microsoft Prinzip!
Da klickst du einfach auf das Schlosssymbol dann erscheint eine Tafel mit allen FuseBits die dein Controller hat, dann klickst du auf read, dann zeigts dir an was wie gesetzt ist, Häckchen bedeuted unprogrammed! Dann machst du Häckchen dazu oder weg und klickst auf write!
Fertig, ist Super einfach!!
Achja und wie ich die setzen muss schau ich hier nach:http://palmavr.sourceforge.net/cgi-bin/fc.cgi
Viel Erfolg

chr-mt
04.07.2007, 08:38
Hi,

Ich verstehe dann aber immer noch nicht wie er das Programm dann schneller abarbeitet, bleibt doch die Anzahl der Befehle und die tatsächliche Taktfrequenz die gleiche
Bascom berechnet die Wartezeiten für's Display aus deiner Angabe der Taktfrequenz. Wenn du keine extra Library verwendest, muss RW auf GND liegen. Dadurch kannst du aber das Busy Flag des Displays nicht auslesen.
Um sicherzugehen, daß das Display bereit für neue Daten ist, legt Bascom eben eine kleine Pause ein.
Diese ist allerdings so lange gewählt, daß es 100%ig auch immer mit jedem Display geht.
Die meisten Displays sind aber schneller mit dem Verarbeiten der Daten fertig.
Wenn du Bascom jetzt eine niedrigere Quarzfrequenz vorlügst, macht der Compiler die Wartezeiten eben kürzer.
Bei den Displays, die ich so verwende, geht's bis auf ein viertel der Wartezeit einwandfrei.
Wenn du also eine niedrigere Taktfrequenz angibst, werden auch die Wartezeiten kürzer.
Das daß natürlich keine saubere Lösung ist, ist klar.
Es ändern sich ja auch alle anderen Zeiten.
Der Uart läuft dann auch anderer Datenrate, alle wait Befehle stimmen dann nicht mehr etc.
Man muss da schon höllisch aufpassen ;)

Beispiel:
$crystal = 4000000 ' Bei Quarz 16 MHz
Baud = 4800 'Baudrate ist 19200 BPS
waitms = 400 'Wartezeit ist 100ms

Besser wäre es, das Busy Flag abzufragen zb. mit der lcd4busy.lib.
Damit sollte die Displayausgabe schneller gehen.

Gruß
Christopher