PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Tiny13(A), PWM, $crystal: Komisches Verhalten



M_I_B
16.09.2012, 11:58
Hallo ihr Lieben,

ich bin gerade auf ein merkwürdiges Verhalten gestossen, welches ich mir nicht erklären kann. Da hatte ich in der Vergangenheit noch nie drauf geachtet, weil ich noch nie versucht hatte, den PWM- Takt zu erhöhen ...

Quelltext für den Test zum Nachvollziehen:

$crystal = 4000000
Config Pinb.0 = Output

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Prescale = 1
Start Timer0
Dim Z As Byte : Dim T As Bit
Z = 0 : T = 0

Do
If T = 0 Then
Incr Z
If Z = 127 Then T = 1
Else
Decr Z
If Z = 0 Then T = 0
End If
Waitms 1
Pwm0a = Z
Loop

Verwendete Werte für den Takt: 1MHz, 8MHz, 10MHz, 20MHz

Unabhängig vom Takt erhalte ich am Ausgang immer etwa 2,2kHz. Ändere ich aber den Takt, ändert sich auch die Geschwindigkeit des Rauf- und Runterlaufens, und das nicht wie erwartet schneller werdend bei höherem Systemtakt, sondern mir unverständlich langsamer werdend! Der Systemtakt beeinflusst also nicht den PWM, wohl aber die schnöde Zählschleife, und das annährend unerwartet umgekehrt proportional?!?

Also... Nutze ich einen Systemtakt von 1MHz, dann dauert ein Zyklus (Do ... Loop) etwa 1/5 Sekunde. Setze ich den Takt auf 20MHz, dann dauert ein Zyklus etwa 4 Sekunden, bei 10MHz etwa 1,5 Sekunden ...

Hmmmm...
Mache ich da irgend wie einen doofen Denkfehler? Hab ich'n Knoten im Hirn? Kapier ich nicht *grummel*


Könnte mir mal bitte wer freundlicher Weise auf die Sprünge helfen?


BTW: Gibt es eine Möglichkeit, den Ausgangstakt des PWM zu erhöhen, also auf z.B. umzu 10kHz? Ich benötige letztlich nur ein Hochlaufen von 0-50% Puls/Pause (und wieder zurück; Dimmen eines EL- Converters)

Searcher
16.09.2012, 12:50
Hmmmm...
Mache ich da irgend wie einen doofen Denkfehler? Hab ich'n Knoten im Hirn? Kapier ich nicht *grummel*
:)

Hi, der Systemtakt des Tiny ist nicht von der $CRYSTAL Einstellung abhängig, sondern von den Fuseeinstellungen bzw eventuell vorandenem Quarz.

Die $CRYSTAL Einstellung benutzt BASCOM um den entsprechenden Maschinencode für zB WAITMS zu erstellen. Setzt Du die Einstellung hoch, macht BASCOM mehr Schleifen daraus; höherer Takt - mehr Schleifen um auf die gleiche Wartezeit (zB 1ms) wie bei niedrigem Takt zu kommen. Der tatsächliche Takt hat sich aber nicht geändert, bedeutet, die vielen Schleifen brauchen länger und somit wird dein Zyklus länger.

Gruß
Searcher

Sauerbruch
16.09.2012, 14:42
2,2 KHz kommt auch gut hin: Der ATTiny13A läuft werksseitig mit 9,6 MHz und einem Takt-Vorteiler von 8, also auf 1,2 MHz. Teilt man das durch 512 (256 Takte raufzählen und 256 runter), kommt man auf präzise 2343 Hz.

Wenn Du das Fusebit CKDIV8 löschst, fällt die Vorteilung durch 8 weg, und dann bist Du schon bei 18,7 kHz.
Weißt Du, wie man Fusebits verstellt?

Und wie ja schon gesagt wurde: Die $Crystal-Anweisung beeinflusst den Takt NICHT! Wenn die Frequenzangabe dort aber vom tatsächlichen Takt abweicht, sind die Pausen bei wait-Befehlen auch fehlerhaft!

M_I_B
16.09.2012, 16:29
... au mann *VorDieStirnPatsch* ^^

Na klar, ihr habt ja vollkommen wahr! Manchmal sieht man halt den Wald vor lauter Bäumen nicht...

Ok, mal davon abgesehen, das so was natürlich doof ist, das Bascom nicht gleich den echten Takt über die Fuses setzt resp. umgekehrt aus den Fuses bezieht, ist die Einstellung in Bascom auch etwas eingeschränkt. Denn über den Progger kommt man nicht über 9,6MHz. Vermutlich muss man dort dann direkt das Register ändern; muss ich mal suchen, wie das denn geht ...

Nachtrag:
Das ist natürlich eine ziemliche Frickelei, wenn man versuchen muss, in etwa die Resonanzfrequenz des Wandlers zu treffen. Gibt es da nicht irgend ein Hilfsmittel / Trick 17, um mal z.B. gleitend die Taktfrequenzen durchzugehen?
Quatsch mit Sosse :( Kann der ja gar nicht intern... Thema durch... Muss ich die Resonanzfrequens eben am Übertrager anpassen...

Kampi
16.09.2012, 16:31
Über 9,6Mhz kannst du nicht kommen bzw. wenn du den Controller schneller betreibst kann es passieren das der Controller nicht richtig arbeitet.

M_I_B
16.09.2012, 16:40
... das bezieht sich aber nur auf intern generierten Takt, oder? Denn lt. Datenblatt schafft der 13er 20MHz ...

Kampi
16.09.2012, 16:51
Genau.
Intern kann er nur 9,6MHz erzeugen. Die 20MHz musst du extern erzeugen und du kannst sie auch nur dann verwenden wenn du den Controller mit mind. 4,5V betreibst.

M_I_B
16.09.2012, 16:59
... ok, danke euch erstmal für die Hinweise.

Ich habe jetzt mal geschaut, was wo bei rauskommt:
Vorteiler immer aus. Bei 9,6 MHz komme ich auf umzu 17,5 kHz, bei 4,8 MHz umzu 9,2 kHz. Da sollte sich mit ein paar C's am Übertrager irgendwo eine Resonanz auf der Grundwelle oder einer der Oberwellen finden lassen.
Ich werde den ganzen Trum mal zusammenstecken und schauen, ob ich da was wuppen kann ... Ich werde berichten ... Hat zwar nicht direkt was mit Robotik zu tun, wohl aber mit RC ...

Kampi
16.09.2012, 17:13
... ok, danke euch erstmal für die Hinweise.

Ich habe jetzt mal geschaut, was wo bei rauskommt:
Vorteiler immer aus. Bei 9,6 MHz komme ich auf umzu 17,5 kHz, bei 4,8 MHz umzu 9,2 kHz. Da sollte sich mit ein paar C's am Übertrager irgendwo eine Resonanz auf der Grundwelle oder einer der Oberwellen finden lassen.
Ich werde den ganzen Trum mal zusammenstecken und schauen, ob ich da was wuppen kann ... Ich werde berichten ... Hat zwar nicht direkt was mit Robotik zu tun, wohl aber mit RC ...

Wer sagt den das es immer direkt was mit Robotik zu tun haben muss ;)

M_I_B
16.09.2012, 19:31
... niemand sacht das, aber ich bin schon so lange in Foren unterwegs (da gab es das WWW noch gar nicht), das ich da vorsichtig geworden bin ;)

Sodele... Software ist fertig und tut, was sie soll. Anbei der Quellcode zur allgemeinen Verwendung, falls es wer braucht.

PB0 befeuert direkt einen kleinen FET (3A- Typ aus der Grabbelkiste), der wiederum einen 1:10 Übertrager mit umzu 6V befeuert, der wiederum auf der Sekundärseite eine EL- Folie zum leuchten bringt.
Der Teil ist erst im Kopf fertig und wird wohl morgen zusammen gesteckt.

PB1 kümmert sich um Änderungen bei Druck auf das Wählrad, PB2 und PB3 um Statusänderungen beim Drehen des Rades... Welches Rad fragt ihr? Wählrad RC Sender Spektrum DX- Serie... Und nu ist wohl auch klar, das ich nicht nur schnöde das Display beleuchten möchte, sondern das auch schön haben will :cool:


$regfile = "attiny13.dat"
$crystal = 4800000

'$prog &HFF , &H72 , &HFF , &H00 ' 9,6 MHz, Vorteiler aus
$prog &HFF , &H75 , &HFF , &H00 ' 4,8 MHz, Vorteiler aus

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Prescale = 1 'PWM im Schnellgang

Dim Z As Byte , T As Bit , L As Byte ' Z= Zähler P-Breite, T= dunkel/hell, PWM Startwert
Dim M As Bit , N As Bit , W As Byte , D As Byte ' Merker für Rollen Eingänge, Geschwindigkeit Dimmer, AN- Zeit
L = 8 : W = 10 : D = 10 ' Vorbelegen

Config Pinb.0 = Output ' PWM Ausgabe
Config Pinb.1 = Input ' INT0 Eingang (Klicktaste)
Config Pinb.2 = Input ' Eingang Rollen links
Config Pinb.3 = Input ' Eingang rollen rechts
Portb.1 = 1 ' Pullup einschalten
Portb.2 = 1 ' Pullup einschalten
Portb.3 = 1 ' Pullup einschalten

On Int0 Isr_display ' Sprungziel bei Auslöung
Config Int0 = Change ' Jeden Pegelwechsel nutzen
Enable Int0 ' INT0 einschalten

Gosub Isr_display ' Erstmal beim EInschalten Licht machen

Do ' Start Hauptschleife
While T = 1 ' Licht ist an, also Ausdimmen
Decr Z
Pwm0a = Z
If Z = L Then T = 0 ' Ende, wenn Startwert erreicht
Waitms W ' Geschindigkeit des Dimmens
Wend

If Pinb.2 = M Then ' Start Abfrage der Rollen- Eingänge
M = 1 : Gosub Isr_display ' und Sprung, wenn sich was geändert hat
End If
If Pinb.2 = M Then
M = 0 : Gosub Isr_display
End If
If Pinb.3 = N Then
N = 1 : Gosub Isr_display
End If
If Pinb.3 = N Then
N = 0 : Gosub Isr_display
End If ' Fertig mit der Auswertung
Loop


Isr_display: ' INT- und Sprungziel
Disable Int0 ' Erstmal für Ruhe sorgen
While T = 0
Incr Z
Pwm0a = Z
If Z = 128 Then T = 1 ' Bis 50% Puls/Pause hochzählen
Waitms W
Wend

Wait D ' Display für D Sekunden an lassen

Enable Int0 ' Ab jetzt wieder horchen
Return ' und zurück zum Hauptprogramm


End

Sauerbruch
16.09.2012, 21:02
Schön dass es klappt!
Aber es wäre gar nicht nötig gewesen die Resonanzfrequenz des Übertragers anzupassen - denn man kann die PWM-Frequenz auch nahezu stufenlos variieren. Das geht im sogenannten "CTC"-Modus. CTC heißt "Clear Timer on Compare". Der Timer zählt in diesem Modus von 0 aufwärts, und wenn er den Wert des OCR-Registers erreicht, toggelt er einen Ausgang und wird sofort auf 0 gesetzt, um wieder von vorne zu beginnen. Heißt also, dass der Ausgang umso öfter getoggelt wird, je niedriger der Wert im OCR-Register ist - und den kann man ja in 256 Schritten variieren. In den Datenblättern sind sehr schöne, aufschlussreiche Grafiken hierzu abgebildet. Auch wenn´s jetzt auch schon mit der "festen" Frequenz funktioniert - aber vielleicht brauchst Du ja irgendwann noch mal eine variable Frequenz :-)

M_I_B
16.09.2012, 22:33
... hu? Da ich sowieso noch nicht fertig bin, lass mich mal wissen, wie man dieses Register in Bascom setzen kann? Ich finde da nix zu (oder ich sehe es einfach nicht). Einfach ein compare0a=x klappt ja so nicht ...

BTW:
Nach einigem Rumspielen habe ich mal eine andere Merkwürdigkeit entdeckt...
Wenn man die Wait- Statements mit den vorbelegten Variablen W und D besetzt, schmiert der Tiny irgendwann ab, wenn man abwechselnd einen INT und eine der beiden anderen Eingänge triggert. Wenn man aber die Wait's mit fixen Werten setzt, dann passiert das nicht

Kampi
16.09.2012, 22:44
Der Interrupt bringt wahrscheinlich die Waitschleife durcheinander.
Wenn ein Interrupt ausgelöst wird, müssen bestimme Registerinhalte gesichert werden. Eventuell macht dir das Schwierigkeiten.

M_I_B
16.09.2012, 22:58
... das kann natürlich sein, ist natürlich doof, wenn dem so sein sollte *hmmmm*


BTW: Meine Nachbildung der "Change" Funktion für die anderen beiden Engänge funktioniert nicht korrekt; ich rätsel noch... oder geh ins Bett ...

Sauerbruch
16.09.2012, 23:23
Da ich sowieso noch nicht fertig bin, lass mich mal wissen, wie man dieses Register in Bascom (http://www.rn-wissen.de/index.php/Bascom) setzen kann?

Also, ich setzte bei PWM-Anwendungen die beiden relevanten Register immer direkt. Wenn man sich da einmal reingedacht hat, ist es eigentlich ziemlich einfach. Eine gute Beschreibung des CTC-Modus findest Du auf Seite 63 im Datenblatt des Tiny13.

Falls Du es aber ohne viel Kopfzerbrechen testen möchtest, probier mal folgendes:




DDRB.0=1 'OC0A als Ausgang konfigurieren
TCCR0A = &B01000010
TCCR0B = &B00000001



Wenn Du diesen Code vor die Do-Loop-Schleife stellst, müsste am Port B.0 ein Rechtecksignal anliegen, dessen Frequenz zwischen CLK/2 (wenn OCR0A = 0) und CLK/512 (wenn OCR0A = 255) liegt.

Rone
17.09.2012, 07:59
BTW:
Nach einigem Rumspielen habe ich mal eine andere Merkwürdigkeit entdeckt...
Wenn man die Wait- Statements mit den vorbelegten Variablen W und D besetzt, schmiert der Tiny irgendwann ab


Wen Du keine Stackwerte definierst, ist das weiter nicht verwunderlich.

MfG
Rone

M_I_B
17.09.2012, 15:26
@Rone: Wo du Recht hast ^^

@Sauerbruch: Ok, so weit, so gut. Aber wie verändere ich das jetzt?

@all: der obige Code ist Murks, da einige Unschönheiten. Ich habe es mal ganz anders gemacht und die Unschönheiten (bis auf die PWM- Frequenz) sind w.e.c.h. ...
Die Dokuentation habe ich erstmal weg gelassen, da mich dieser eingebaute Editor echt elendig genervt hat; kann man da nicht irgendwie Notepad++ integrieren?!? *grrr*


$regfile = "attiny13.dat"
$crystal = 4800000
$hwstack = 16
$swstack = 16
$framesize = 16
'$prog &HFF , &H72 , &HFF , &H00 ' 9,6 MHz, Vorteiler aus
$prog &HFF , &H75 , &HFF , &H00 ' 4,8 MHz, Vorteiler aus



Config Timer0 = Pwm , Compare A Pwm = Clear Down , Prescale = 1 'PWM im Schnellgang
'Ddrb.0 = 1 'OC0A als Ausgang konfigurieren
'Tccr0a = &B01000010
'Tccr0b = &B00000001

Dim Z As Byte , T As Byte , L As Byte
Dim Du As Integer , Dd As Integer , Ot As Integer
L = 8 : Du = 2000 : Dd = 2000 : Ot = 1500

Config Pinb.0 = Output
Config Pinb.1 = Input : I1 Alias Pinb.1 : Portb.1 = 1
Config Pinb.2 = Input : I2 Alias Pinb.2 : Portb.2 = 1
Config Pinb.3 = Input : I3 Alias Pinb.3 : Portb.3 = 1



Enable Pcint0
Enable Interrupts
Pcmsk = &B001110
On Pcint0 An



Hell:

While T = 0
Incr Z
Pwm0a = Z
If Z = 128 Then T = 1
Waitus Du
Wend

If T = 1 Then
Waitms Ot
Else
Z = 127 : Goto Hell
End If

While T = 1
Decr Z
Pwm0a = Z
If Z = L Then T = 2
Waitus Dd
Wend

While T = 2
nop
Wend
Goto Hell

End


An:
T = 0
If Z > 125 Then Z = 127
Return

M_I_B
17.09.2012, 20:04
... ich hätte da noch eine Frage *duck...*

Wie kann ich während der Laufzeit den als PWM laufenden Timer anhalten resp. das AUsgangssignal auf LOW setzen (und später wieder einschalten)??

Ich habe es jetzt versucht mit Disable Timer0, pinb.0=0, portb.0=0. Nichts funktioniert :(

Hat sich erledigt: Einfach Pwm0a = 0 und anschliessend ein Config Powermode = Powerdown funktioniert perfekt ;)

Sauerbruch
17.09.2012, 21:23
Wie kann ich während der Laufzeit den als PWM laufenden Timer anhalten resp. das AUsgangssignal auf LOW setzen (und später wieder einschalten)??

Auch wenn´s mit PWM0A = 0 klappt, gibt´s noch zwei einfachere Methoden (die dem Verständnis im allgemeinen und speziellen auch förderlich sein könnten):

"disable timer0" wird oft anfangs fälschlicherweise so verstanden, dass man damit den Timer anhält. Dem ist aber nicht so, sondern mit diesem Befehl wird lediglich der Interrupt deaktiviert, der beim Überlaufen des Timers ausgelöst würde (entsprechend aktiviert man diesen Interrupt mit "enable timer0")

Der Befehl den Du suchst lautet ganz einfach "stop timer0" bzw. "start timer0", wenn er weiterlaufen soll.

Nur diese Frage habe ich nicht ganz verstanden:

Aber wie verändere ich das jetzt?
WAS willst Du denn verändern??

Und den PWM-Pin kannst Du über das Data-Direction-Register als Eingang konfigurieren. Dann führt er weder High noch Low, sondern ist einfach nur ein hochohmiger Eingang:
DDRB.0=0

Mit DDRB.0=1 wird er dann wieder zum Ausgang!

M_I_B
17.09.2012, 21:41
Nur diese Frage habe ich nicht ganz verstanden:
Also... (luft hol'):

Du hattest mir ja den Trick und Code mit dem CTC- Mode verraten. Wie du siehst, steht das auch auskommentiert in meinem Quelltext. Sobald ich das aber aktiviere, erhalte ich zwar ein symetrisches Rechteck, aber das ändert sich dann in der Frequenz und nicht mehr in der Pulsbreite.

Am Geschicktesten wäre m.E. eine kleine Unterroutine, die sich selbst auf die optimale Frequenz einstellt. Also Messung der Ausgangsspannung des Konverters via ADC, langsames Durchfahren des Frequenzbandes und ermitteln der optimalen Schaltfrequenz bei verschiedenen Tastverhältnissen (z.B. im 10% Raster). Das wäre deshalb sinnig, da zum einen eine zugeschnittene EL- Folie die Resonanzfrequenz verändert und zu alle dem auch noch ihre Kapazität mit der Helligkeit ändert, mal ganz abgesehen von Alterungserscheinungen solcher Folien. Mit so einer Routine könnte man nach dem Einbau z.B. bei jedem Systemstart die Werte neu ermitteln und hätte damit auch gleich eine "... bin gleich soweit..." Meldung.

Aber erst mal wäre mir damit gedient, wenn ich erstmal in die Lage komme, die Frequenz zu fixieren/einzustellen. Wenn ich dann im Nachgang durch Rumfrickeln und deiner/eurer Hilfe auch noch verstehe, was du mir da an Code an die Hand gegeben hast, dann hätte ich schon einen weiten Sprung nach vorn gemacht...

Sauerbruch
18.09.2012, 10:13
Na ja, vielleicht kriegt der Controller beim letzten Befehl dieser Sequenz ja auch einfach nur Angst...


While T = 2
nop
Wend
Goto Hell


(was natürlich nur´n Spaß... :-) )

Ich habe zwar keinen blassen Schimmer was eine EL-Folie ist und was sie benötigt - aber zum Thema PWM kann man sicher folgendes sagen:
Entweder kannst Du die Frequenz (nahezu) stufenlos einstellen; dies geschieht im CTC-Modus, der aber ein festes Impuls-Pausenverhältnis von 1:1 liefert. Oder aber Du generierst im "normalen" PWM-Modus ein Signal, dessen Impuls-Pausenverhältnis sehr fein justierbar ist - dann kannst Du aber nur ganz bestimmte, definierte Frequenzen erzeugen (in Abhängigkeit des Prozessortaktes, des Prescalers sowie der Bitbreite des verwendeten Timers.

M_I_B
18.09.2012, 10:19
... macht nix ;) Ich habe schon so einiges an Silizium in die Hölle geschickt; da kann der Tiny schon gerne mal bibbern vor Angst ;)

Ok, also geht entweder nur Frequenz oder nur PWM... Das erklärt einiges und ist ziemlich doof; wäre ja zu schön gewesen *grummel*

Kann denn ggf. ein Tiny 44, 45, 2313 o.ä. beides gleichzeitig, also Frequenz und PWM steuerbar?