Ich möchte eine PWM mit 38Khz erzeugen die dann jede ms ein und
ausgeschaltet soll.
Verstehe ich das richtig das ich erst einen Timer0 als PWM mit 38Khz
konfiguriere und den Timer1 so dass er jede Milisekunde in den ISR
springt und diesen PWM pin an/ausschaltet?
tinyy schrieb:> Verstehe ich das richtig das ich erst einen Timer0 als PWM mit 38Khz> konfiguriere und den Timer1 so dass er jede Milisekunde in den ISR> springt und diesen PWM pin an/ausschaltet?
Könnte man so machen. Einfacher ist es, die PWM einfach weiterlaufen zu
lassen und lediglich den Ausgangspin auf Eingang umzuschalten, um die
PWM zu unterdrücken.
Matthias S. schrieb:> Einfacher ist es, die PWM einfach weiterlaufen zu> lassen und lediglich den Ausgangspin auf Eingang umzuschalten, um die> PWM zu unterdrücken.
Aber auch über einen zweiten Timer der lediglich den Pinmode
(Eingang/Ausgang) toggelt?
tinyy schrieb:> Aber auch über einen zweiten Timer der lediglich den Pinmode> (Eingang/Ausgang) toggelt?
Kann man so machen, wenn genug Timer zur Verfügung stehen. Ansonsten
benutzt man eine ISR, die Ereignisse des PWM-Timers zählt.
Danke!
Leider geht der Timer überhaupt nicht. AM Pin B1 passiert nichts.. Als
würde er nicht in den ISR springen. Manueles eischalten in der main
klappt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main(void)
5
{
6
7
DDRB |= ((1<<DDB0) | (1 << DDB1)); // Output
8
9
// Timer Konfiguration
10
TIMSK = (1<<TOIE0); //When the TOIE0 bit is written to one, and the I-bit in the Status Register is set, the Timer/Counter0 Overflow inter-
11
TCCR0A = (1<<CS01); // Prescaler 8 CS02 und 00 für 1024
Tim schrieb:> Nunja, am Timer 1 muß ja erstmal auch noch die PWM initialisiert werden.
Unabhängig von PWM. Will einfach nur den Poinb1 ein und ausschalten,
hängt eine LED dran.
Laut Datenblatt ist es aber TCR0A. Hier meine neue Konfiguration mit
einem Prescaler von 1024.
DDRB |= ((1<<DDB0) | (1 << DDB1)); // Output
TCNT0 = 0;
count=0;
TCCR0 = ((1<<CS02) | (1<<CS00));
TIMSK = (1<<TOIE0); //When the TOIE0 bit is written to one, and the
I-bit in the
sei(); // Global Interrupts aktivieren
tinyy schrieb:> Laut Datenblatt ist es aber TCR0A
Erstens liest du anscheinend das falsche Datenblatt und zweitens gibt es
TCR0A in diesem MC nicht.
Verwende also TCCR0B und es wird klappen.
tinyy schrieb:> TCCR0 = ((1<<CS02) | (1<<CS00));
Es hat auch hier keinen Sinn, Register zu verwenden, die es gar nicht
gibt.
c-hater schrieb:> s ist TCCR0A.>> Das Blöde ist halt nur, dass es darin keine CSxy-Bits gibt...
Ja so steht es ja auch in meinem Code! aber funktioniert nicht.
Matthias S. schrieb:> Erstens liest du anscheinend das falsche Datenblatt und zweitens gibt es> TCR0A in diesem MC nicht.> Verwende also TCCR0B und es wird klappen.
Danke, aber woher weiss ich den ob es TCRR0A gibt oder nicht, wenn es ja
im Datenblatt aufgeführt ist?
Dieses Datenblatt lese ich:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
Und vlt eine doofe Frage, Wohre weiss ich mit welcher Frequenz der
Attiny läuft? In Atmel habe ich nur neues Projekt erstellt ohne irgendwo
spezifisch einzustellen.
tinyy schrieb:> Danke, aber woher weiss ich den ob es TCRR0A gibt oder nicht, wenn es ja> im Datenblatt aufgeführt ist?
Du hast das Register falsch geschrieben, falls du doch TCCR0A meinst.
Dss wird deswegen also nicht kompilieren und deswegen auch meine
Bemerkungen.
Die CSx Bits sind aber im Register TCCR0B und da hilft es nix, in TCCR0A
zu schreiben.
Abschnitt 11.9.3 in dem o.a. Datenblatt.
tinyy schrieb:> Wohre weiss ich mit welcher Frequenz der> Attiny läuft? In Atmel habe ich nur neues Projekt erstellt ohne irgendwo> spezifisch einzustellen.
Ebenfalls im DB steht der Auslieferzustand mit 8Mhz internem RC
Oszillator und gesetzter CKDIV8 Fuse.
tinyy schrieb:> Und vlt eine doofe Frage, Wohre weiss ich mit welcher Frequenz der> Attiny läuft? In Atmel habe ich nur neues Projekt erstellt ohne irgendwo> spezifisch einzustellen.
1 MHz, wenn an den Fuses nichts verändert oder im Code nichts anderes
eingestellt wurde.
tinyy schrieb:> Danke, aber woher weiss ich den ob es TCRR0A gibt oder nicht, wenn es ja> im Datenblatt aufgeführt ist?
Es gibt TCCR0A, das ist jedoch das falsche Register.
Das richtige wäre TCCR0B. In dem stehen die Clock select Bits
Seite 82 -> 11.9.3
tinyy schrieb:> In Atmel habe ich nur neues Projekt erstellt ohne irgendwo> spezifisch einzustellen.
Dann wird er bei 1MHz intern laufen.
Auslieferungszustand.
Grundeinstellung per Fuses, üblich:
1MHz, 8 MHz oder 16.5(?)MHz per PLL
Im Programm kannst du dann noch den Prescaler konfigurieren.
Kann ich aber nicht direkt durch die Konfiguration vom PWM eine
Trägerfrequenz von 38Khz erreichen und die dann mit einem khz
modulieren, also jede Milisekunde ein/ausschalten?
Hier sieht man an den Bildern, dass es wol möglich ist, oder verwechsele
ich gerade was?
http://maxembedded.com/2011/08/avr-timers-pwm-mode-part-i/
AN PB1 möchte ich PWM haben das ist mein Code es tut sich aber nichts:
[code]
DDRB |= ((1<<DDB0) | (1 << DDB1)); // Output
//TCNT0 = 125;
count=0;
// Timer Konfiguration
TCCR0B = ((1<<CS02) | (1<<CS00)); // Prescaler 8:CS02 und 101 für 1024
TIMSK = (1<<TOIE0); //When the TOIE0 bit is written to one, and the
I-bit in the Status Register is set, the Timer/Counter0 Overflow inter-
sei(); // Global Interrupts aktivieren
//PWM Phase correct Mode
TCCR0B =(1<<WGM02);
TCCR0A = ((1<<WGM00) | (0<<WGM01));
OCR0B = 12; // mit dem Wert wird TCNT0 verglichen (aktueller
Timerwert)
TCCR0A = (1<<COM0B0);[/code}
tinyy schrieb:> das ist mein Code es tut sich aber nichts
Überlege mal, worin der Unterschied zwischen
... = ... und
... |= ...
besteht.
Und dann frage Dich, was z. B. beim 2. Zugriff auf TCCR0B passiert.
TCCR0B =(1<<WGM02); mit dieser Zeile löscht du die vorher gemachten
Einstellungen in dem Register. Da es sich dabei um den prescaler handelt
läuft der Timer nicht mehr. TCCR0B |= (1<<WGM02); setzt lediglich das
gewünschte Bit. Lief denn wenigstens der normale Timer Modus bereits?
Holger L. schrieb:> TCCR0B =(1<<WGM02); mit dieser Zeile löscht du die vorher gemachten> Einstellungen in dem Register.
Brav - gibt ein Fleißkärtchen :-) Der TO sollte sich eines verdienen ...
Haha danke, ich werde es mit Stolz herumtragen:-) Ich hatte deinen
Beitrag nicht gesehen. Allerdings hat diese Art der Hilfestellung vorher
schon keine Früchte getragen und eher für Verwirrung gesorgt.
Ich habe mal komplett aufgeräumt und von neu alles gemacht. Ich möchte
auf Pin 6 PWM haben. Also muss der Timer0 Wert mit dem Wert im Register
OCR0B verglichen werden. Aber es funktioniert nur wenn ich etwas in
OCR0A schriebe, warum??
zweite Frage: Wenn ic hdiesen OCR0A auf 125 stellen würde müsste das
Signal genausolange an wie aus sein 125/256, oder nicht?
1
TCCR0A |= ((1<<WGM00) | (1<<WGM01)); //FAST PWM Seite 79...
2
TCCR0B |= (1<<WGM02); // ...diese 3 WGM-Bits setzen Fast PWM mit TOP-Wert in OCRA .Seite 79
> ... nur wenn ich etwas in OCR0A schriebe, warum??
Wie ja schon laut Kommentar richtig erkannt, steht bei Mode=7 in OCR0A
der TOP-Wert; nach einem Reset ist OCR0A=0.
Hi
>und was macht OCR0B? Wenn ich den OC0B Pin benutze dachte ich muss ich>auch entsprechend in OCR0B den TOP-Wert einsetzen oder nicht?
Wenn du einen PWM-Mode mit festem Top-Wert benutzt kannst du den Timer
mit zwei PWMs benutzen. Mit OCR0A als Top-Wert wird mit diesem die
Auflösung der PWM bestimmt und du hast nur noch OCR0B für die PWM zur
Verfügung.
MfG Spess
spess53 schrieb:> Mit OCR0A als Top-Wert wird mit diesem die> Auflösung der PWM bestimmt und du hast nur noch OCR0B für die PWM zur> Verfügung.
Also ich nehme den PWM Fast Mode WGM00,WGM01 und WGM02 auf 1 bedeutet
TOPWWERT:OCRA.
Was bedeutet das was ändert nun OCRA und und was OCRB. Und auf welchen
Pin am Attiny85 wirkt sich das aus? PB1 hat OC0b und PB0 hat OC0A.
Bin da sehr durcheinander.
tinyy schrieb:> und was macht OCR0B? Wenn ich den OC0B Pin benutze dachte ich muss ich> auch entsprechend in OCR0B den TOP-Wert einsetzen oder nicht?
Mein Gott, im Datenblatt steht da so viel Prosa dazu, das sollte man
halt auch mal lesen.
Dann muss man nicht raten was welches Register in welchem Modus macht.
tinyy schrieb:> Was bedeutet das was ändert nun OCRA und und was OCRB.
Wenn der Timer den Wert von OCRA (= TOP) erreicht, wird er auf 0
zurückgesetzt und fängt wieder an, ab 0 zu zählen.
Wenn OCRB kleiner als TOP ist, wird am korrespondierenden Pin eine PWM
ausgegeben. Ist OCRB grösser als TOP, passiert am PWM Pin nix, da der
Vergleichswert nie erreicht wird.
Beispiel: OCRA = 128 und OCRB = 64. Am Pin OC0B wird eine PWM mit 50%
Tastgrad ausgegeben.
OCRA = 128 und OCRB = 192: Am Pin OC0B passiert nichts, da der Wert 192
nie erreicht wird.
Hi
>Was bedeutet das was ändert nun OCRA und und was OCRB.
OCR0A bestimmt wie weit der Timer läuft bis er wieder bei Null anfängt.
Also die Frequenz der PWM.
OCR0B bestimmt das Tastverhältnis der PWM. Es gilt 0<= OCR0B <= OCR0A.
MfG Spess
Vielleicht eine andere Variante:
Mit CTC-Mode, wo TOP OCR0A ist und mit OCR0B die Impulsdauer einstellen
kannst. Dann kannst du IMHO die gewünschte Frequenz einfacher
einstellen.
Cyblord -. schrieb:> Mein Gott, im Datenblatt steht da so viel Prosa dazu, das sollte man> halt auch mal lesen.
Ich rate nicht im Datenblatt unter 11.9.5 (Seite 80) steht:
The Output Compare Register A contains an 8-bit value that is
continuously compared with the counter value
(TCNT0). A match can be used to generate an Output Compare interrupt, or
to generate a waveform output on the
OC0A pin.
Seite 81:
The Output Compare Register B contains an 8-bit value that is
continuously compared with the counter value
(TCNT0). A match can be used to generate an Output Compare interrupt, or
to generate a waveform output on the
OC0B pin.
Für mich bedeutet das, dass der Timerwert TCNT0 mit dem in OC0B und OC0A
verglichen wert, hier stehts NICHTS davon das OC0B den Tastgrad
darstellt. Also verate mir lieber was ich falsch verstehe oder wo ich
stattdessen lesen muss.
spess53 schrieb:> OCR0A bestimmt wie weit der Timer läuft bis er wieder bei Null anfängt.> Also die Frequenz der PWM.
Also wenn ich OCRA auf 26 stelle habe ich bei c_cpu und keinem Prescaler
eine Freqzuenz von 38Khz? 1e6/26 = 38.4Khz. Mein DMM zeigt 74 khz an.
Bei anderen werten hat die Rechnung mit dem DMM übereingestimmt.
Das nächste Problem ist, ich kann die LED nicht dimmen die am Pin hängt:
OCR0A = 26; wird vorher beim pwm init auf diesen wert gesetzt um 38khz
zu bekommen.
1
uint8_t wert;
2
while (1)
3
{
4
for (wert=0; wert<26; wert++)
5
{
6
// OCR0A = wert;
7
OCR0B = wert;
8
}
9
10
for (wert=26; wert>0; wert--)
11
{
12
// OCR0A = wert;
13
OCR0B = wert;
14
}
Danke an Matthias S. und den rest hat mir geholfen.
tinyy schrieb:> Für mich bedeutet das, dass der Timerwert TCNT0 mit dem in OC0B und OC0A> verglichen wert, hier stehts NICHTS davon das OC0B den Tastgrad> darstellt. Also verate mir lieber was ich falsch verstehe oder wo ich> stattdessen lesen muss.
Was denkst du wie der Tastgrad zustande kommt?
Wie erzeugt der Timer denn ein PWM?
Bevor du das nicht checkst brauchst du nicht weiter machen.
Also:
Er läuft hoch und schaltet den Ausgang irgendwann ab. Und dieser
Zeitpunkt bestimmt den Tastgrad. Dazu vergleicht er den Timerwert mit
dem OC0A Wert.
Darum ist der MODE des Timers wichtig. Man kann nämlich diese Compare
Mimik für alles mögliche verwenden. U.a. halt für PWM Erzeugung.
Ich verstehe aber nicht, was dein Eingangsproblem überhaupt mit PWM zu
tun hat. Du willst eine 38khz Trägerfrequenz. Meist will man da fix
einen Tastgrad von 50% aber der Tastgrad ist gar nicht so entscheidend.
Entscheidend für dich ist doch erstmal die korrekte Frequenz und das
abschalten alle 1ms. Mit PWM hat das nur sehr sehr am Rande was zu tun.
Nicht vergessen - dein Programm wird da mit 1 MHz Taktfrequenz
durchrannt und das ist so schnell, das du die einzelnen PWM Schritte
nicht mehr siehst.
Wenn du da was sehen willst, füge mal ein _delay_ms(100) oder so ein.
Also z.B. :
1
for(wert=0;wert<26;wert++)
2
{
3
// OCR0A = wert;
4
OCR0B=wert;
5
_delay_ms(100);
6
}
Dann wird jede 1/10tel Sekunde der Wert in OCR0B geändert, statt alle
paar µs. Im ursprünglichen Programm wird vermutlich sogar der Wert in
OCR0B schneller geändert, also die PWM überhaupt ist. 38kHz haben ja
eine Periodendauer von etwa 26µs.
Vielleicht eine Lösung in Textform. Die Implementierung müsstest du
selber machen:
1
init_timer()
2
{
3
Prescalersetzen
4
ModeaufCTCsetzen
5
OutputCompareRegisterAundBsetzen
6
Counterstarten
7
}
8
9
ISRWenntimer_counter=OCR0B
10
{
11
Ausgangspinauf1setzen
12
}
13
14
ISRWenntimer_counter=OCR0A
15
{
16
Ausgangspinauf0setzen
17
}
18
19
main()
20
{
21
22
Endlosschleife()
23
}
Mit OCR0A und dem Prescaler definierst du deine gewünschte Frequenz.
Mit OCR0B definierst du den Tastgrad.
Die Rechnung und Implementierung überlasse ich dir selber. Mit dieser
Vorlage sollte dies jedoch kein Problem mehr sein.
Sonst => Grundlagenaufarbeitung.
MfG
Wenn das PWM jetzt mit 38kHz läuft, kann ich wie besprochen dann auch
ein ISR aufrufen bei jedem Überlauf? Heißt die ISR Routine
TIMER0_COMPA_vect oder wie beim normalen Timer0 Interupt
TIMER0_OVF_vect?
Ich würde dann wenn 38mal ein Interrupt ausgeführt wird den Pin auf
eingang setzen, und damit die PWM unterbrechen und wieder nach 38mal,
also einer Milisekunde auf ein, usw. usf.
Passt das so?
1
ISR(TIMER0_COMPA_vect){
2
if(count == 38){
3
DDRB ^= (1 << DDB1);
4
}
5
else {
6
count++;
7
}
PS: wie kann ich den code im Forum als C-Code hervorheben?
1. Im Modus 7 sollte beides möglich sein, s. Tabelle (TOV-Flag).
2. Sollte gegen; nur muss count wohl noch zurückgesetzt werden.
3. ? - Hatten Sie nicht bereits mit "c" formatiert wie untenstehend?
4. Manchmal ist es sinnvoll, etwas einfach auszuprobieren.
Meine C-Kenntnisse sind nur rudimentär, aber noch eine mögliche
Stolperfalle: mit der Systemfrequenz von 1 MHz (Auslieferungszustand)
klappt es eventuell nicht, denn 1.0 MHz / 38 kHz = 26 Takte, und ob das
in C reicht für eine ISR?
Seh' ist jetzt erst, weiter oben:
> 2. Sollte gegen
muss heißen
2. Sollte gehen (bzw. passen)
Leider hat Erich Fried nichts zu "g" vs. "h" geschrieben:
Die Nebelkuh
im Nebelmeer
muht nebel mei-
nem Bahngleis her
nicht neben, denn
wo Nebel fällt,
wird auch das n
zum l entstellt.
S. Landolt schrieb:> mit der Systemfrequenz von 1 MHz (Auslieferungszustand)> klappt es eventuell nicht,
Zum Glück, kann man den Attiny85 bis auf 16MHz internen Takt
konfigurieren.
> Zum Glück, kann man den Attiny85 bis auf 16MHz> internen Takt konfigurieren.
Dies einem Anfänger zu erläutern, überlasse ich gerne Ihnen, Arduino
Fanboy; zumindest heute schaffe ich das nicht.
S. Landolt schrieb:> Dies einem Anfänger zu erläutern, überlasse ich gerne Ihnen
Da gibts nicht viel zu erläutern.....
Wer Programme auf einen leeren Tiny bekommt, der hat auch die
Infrastruktur um die Fuses zu setzen.
Und welche zu setzen sind steht im Datenblatt.
Alternativ: http://www.engbedded.com/fusecalc/
Beispiel: -U lfuse:w:0xf1:m -U hfuse:w:0xd5:m -U efuse:w:0xff:m
Arduino Fanboy D. schrieb:> Beispiel: -U lfuse:w:0xf1:m -U hfuse:w:0xd5:m -U efuse:w:0xff:m
Ich empfehle sehr stark, die Fuses mit dem Atmel Studio zu setzen, wo
das entsprechende Fuse-Bit auch genau erklärt ist.
Ich hatte sicher schon 5+ Stück 40 Pin uC ausgewechselt, nur weil ich
(damals noch in HEX-Format in CodeBlocks) die Fuse-Bits falsch gesetzt
habe...
Und dies einem Anfänger in C Programmierung zuzumuten ist sehr gewagt.
TM F. schrieb:> Ich empfehle sehr stark, die Fuses mit dem Atmel Studio zu setzen, wo> das entsprechende Fuse-Bit auch genau erklärt ist.
Das ist bei dem Fuserechner auf engbedded.com mindestens genauso gut
erklärt wie im Studio, eher noch besser. Noch besser ist nur das
Datenblatt selbst.
> Und dies einem Anfänger in C Programmierung zuzumuten ist sehr gewagt.
Was hat C damit zu schaffen? Wenn bei dieser Fuse-Geschichte irgendwas
an Sprachkenntnissen gefragt ist, dann ist es (Datenblatt-) Englisch,
nicht C.
tinyy schrieb:> Wenn das PWM jetzt mit 38kHz läuft, kann ich wie besprochen dann auch> ein ISR aufrufen bei jedem Überlauf? Heißt die ISR Routine> TIMER0_COMPA_vect oder wie beim normalen Timer0 Interupt> TIMER0_OVF_vect?
Du kannst theoretisch beides verwenden, praktisch ist es allerdings
sinnvoller, den Overflow-Interrupt zu benutzen. Wobei: in deiner
Anwendung spielt das, was dies normalerweise sinnvoller macht, nun doch
wieder keine Rolle, hier ist es also wirklich mal völlig Wurscht.
Es spielt aber eine Rolle, wenn du in den PWM-Modi dynamisch die
zeitbestimmenden Register ändern möchtest, also PWM tatsächlich als
solches benutzen möchtest. Und das liegt daran, dass du zwar zu einem
beliebigen Zeitpunkt während eines PWM-Zyklus die zeitbestimmenden
Register beschreiben kannst, aber dies in Wirklichkeit erstmal nur die
aus Programmierersicht unsichtbaren Pufferregister der Hardware
beschreibt. Tatsächlich in die zeitbestimmende Hardware übernommen
werden die geschriebenen Werte erst beim nächsten Overflow.
Wenn du nun den OC-Interrupt benutzt und dein OCRxn-Wert nahe am
Maximum-Wert (also dem Overflow-Wert) liegt, kann es passieren, dass
deine Änderung nicht beim nächsten, sondern erst beim übernächsten
Overflow tatsächlich wirksam wird. Das kann zumindest unschöne Effekte
produzieren, in bestimmten Anwendungen (Schaltregler z.B.) aber auch mal
eben Leistungshardware in Rauchwölkchen verwandeln. Also diesen
Sachverhalt immer hübsch im Hinterkopf behalten...
tinyy schrieb:> Also wenn ich OCRA auf 26 stelle habe ich bei c_cpu und keinem Prescaler> eine Freqzuenz von 38Khz? 1e6/26 = 38.4Khz. Mein DMM zeigt 74 khz an.> Bei anderen werten hat die Rechnung mit dem DMM übereingestimmt.>> Das nächste Problem ist, ich kann die LED nicht dimmen die am Pin hängt:> OCR0A = 26; wird vorher beim pwm init auf diesen wert gesetzt um 38khz> zu bekommen.
Schreib doch einfach mal, was genau Du machen willst. Jetzt kommt auf
einmal eine LED ins Spiel ...
c-hater schrieb:> Das kann zumindest unschöne Effekte> produzieren, in bestimmten Anwendungen (Schaltregler z.B.) aber auch mal> eben Leistungshardware in Rauchwölkchen verwandeln. Also diesen> Sachverhalt immer hübsch im Hinterkopf behalten...
Interessant für einen TO, der eine LED dimmen will :-)
Im Ernst - ISR muss man sich immer genau anschauen, oder man muss die
sich genau anschauen (wenn es in die Hose geht) :-)
Dieter F. schrieb:> Interessant für einen TO, der eine LED dimmen will :-)
Was hast du an:
>> hier ist es also wirklich mal völlig Wurscht.
nicht verstanden? Ich denke mal, das war so eindeutig, das es nicht nur
der TO, sondern sogar du verstehen können müsstest...
c-hater schrieb:> nicht verstanden? Ich denke mal, das war so eindeutig, das es nicht nur> der TO, sondern sogar du verstehen können müsstest..
Nö - liegt das an Deinem überlegenen Intellekt oder hat das andere
Ursachen?
c-hater schrieb:> Wobei: in deiner> Anwendung spielt das, was dies normalerweise sinnvoller macht,
Ja, was will er denn machen? Das hast Du sicher Messerscharf erkannt.
Kläre mich unbedarften und ggf. noch 0 bis x andere bitte auf.
Hallo, möchte mich hier mal kurz einklinken, weil ich mich gerade in PWR
einlese...ziehmlich am Anfang hier im Thread gab es den Tip, den Pin,
der die PWR ausgibt, auf Eingang umzuschalten, um die Ausgabe zu
"disablen". Ich frage mich, ob das ein gangbarer Weg ist oder ob das
völliger Blödsinn ist! Um bei dem simplen LED-Schalten zu bleiben...ich
käme doch erst mal nicht auf die Idee, den Pin, an dem die LED hängt,
auf "Eingang" zu schalten, damit sie ausgeht!! oder??
Gruß Rainer
Rainer V. schrieb:> ich> käme doch erst mal nicht auf die Idee, den Pin, an dem die LED hängt,> auf "Eingang" zu schalten, damit sie ausgeht!! oder??
Ich schon.
Denn einfacher kann man es sich nicht machen.
Rainer V. schrieb:> Um bei dem simplen LED-Schalten zu bleiben...ich> käme doch erst mal nicht auf die Idee, den Pin, an dem die LED hängt,> auf "Eingang" zu schalten, damit sie ausgeht!! oder??
Beim Nachlesen - gut gelinkt.
Zum einfachen ein- / ausschalten einer LED natürlich nicht (AVR). Da
manipuliert man den Pin.
Für die PWM - warum nicht, wenn man keine andere Lösung findet. Da
schaltet man den Ausgang halt stumm - in der Zeit, in der man ihn nicht
"hören" will.
Dieter F. schrieb:> Beim Nachlesen - gut gelinkt.
Na ja, aber es kommt mir erst mal wirklich komisch vor, einen Ausgang
dadurch zu disablen, dass man ihn zum Eingang macht! Mag bei einem
PWR-Ausgang vielleicht Sinn machen (obwohl ich ihn noch nicht erkennen
kann), aber dann auch vielleicht bei einem Analogeingang??? Habe dabei
kein gutes Gefühl...was natürlich gar nichts heisst...
Gruß Rainer
Um 38kHz PWM zu erhalten brauche ich einen OCR0A Wert von 26. OCR0B
stelle ich auf die Hälfte von OCR0A (50% Tastverhältnis).
umd das PWM Signal jede ms ein und auszuschalten habe ich den timer1
konfiguriert.
f=1Meghz/256 = 3906Hz
T=1/3906 = 0,256ms
0,256ms/1ms = 4 overflows.
1
ISR( TIMER1_OVF_vect )
2
if(count==4){
3
DDRB ^= (1 << DDB1);
4
PORTB ^= (1<<PB0);
5
count=0;
6
}
7
else{
8
count++;
9
}
Zusätzlich lasse ich Portb0 toggeln, wenn ich die Frequenz an Portb
messe bekomme ich durch eine Frequenz von 769Hz.
Und die PWM Frequenz 76.923khz. Warum das doppelte? Irgendwas muss da
doch falsche sein.
tinyy schrieb:> Um 38kHz PWM zu erhalten brauche ich einen OCR0A Wert von 26. OCR0B> stelle ich auf die Hälfte von OCR0A (50% Tastverhältnis).
F_pwm= f_clock/Prescaler*OCR0A
umgestellt nach OCR0A=1MegHz/1*38khz = 26
Also irgendwo ist noch der Hund begraben.
Hallo,
ich habe auch solch ein IR-Sender / Empfänger der auf 38kHz läuft.
Aber warum PWM?
Der erste Timer läuft im CTC Modus mit 2*38kHz und fertig.
Wenn deine Anforderung 1ms sind, gilt f= 1/t = 1000Hz
und dann lässt man den Preprocessor den Prescaler und den Perload
ausrechnen.
Es ist mir klar, dass das für Dich noch zu schwer ist, deshalb eine
Vereinfachung
Sei: F_CPU = 1MHz = 1*10^6Hz, Prescaler = 8, Freq = 1000Hz,
dann gilt:
Preload = long(1.0 * F_CPU/ Prescaler /Freq +0.5)
Preload = long(1.0 * 1*10^6Hz /Prescaler /1000Hz +0.5)
Preload = 125
Das geht ohne weiteres glatt auf.
Dann würde man in das zugehörige CTC-Register (Preload-1) laden und der
Prescaler auf 8 setzen, fertig.
Karl M. schrieb:> Der erste Timer läuft im CTC Modus mit 2*38kHz und fertig.
Warum zweimal? Danke für deinen Vorschlag, ich möchte aber gerne
verstehen was ich bei meiner PWM Geschichte falsch mache. Denn gerechnet
ist alles richtig und eingestellt wie es aussieht auch.
Den CTC-Modus müsste ich ja sowieso auch erstmal lesen und verstehen, da
ich grad am PWM bin und mitlerweile etwas verstehe ist es für mich auch
einfacher denke ich das über pwm zu realisieren.
Naja, nicht jeder Modi ist für jede Fragestellung einfach nutzbar.
Dann wird es Zeit den einfacheren Mode CTC, dir mal anzusehen.
Beachte, die unterschiedlichen Top Register!
Wo ist überhaupt der Unterschied zwischen dem CTC Mode und einem
Normalen Timer bei dem man den wert ab dem er zählt auch in TCNT0
vorschreiben kann? Hier ist es doch genauso nur sagt man die Obergrenze.
Und pwm mode ist doch auch das selbe da schreibt man in den OCR0A den
Wert bis wohin er zählen soll.
Ein Timer0 im Mode "Normal" läuft der Zähler immer von 0 bis 255,
Bei einem Überlauf 255 -> 256 mod 256 = 0,wird dieser als Überlauf
bezeichnet.
Durch den Überlauf wird das "Timer0 Overflow Interrupt Request" erzeugt,
der dann eine ISR anstoßen kann.
Setzt man den Zähler auf einen Wert >0, so wird dieser beim nächsten
Durchlauf wieder bei 0 starten.
Bei Timer0 im Modus CTC ist der Modus nur einmalig auf einen maximalen
Wert einzustellen OCR0A.
Danach läuft er nur von 0 bis (OCR0A-1), der Wert OCR0A mod Max-Wert =
0, und dies erzeugt dann zwei unterschiedliche "Timer0 xxx Interrupt
Request".
Also Timer0 in Modus CTC, mit OCR0A = 125-1 läuft dann immer im 1000Hz
Rhythmus!
Karl M. schrieb:> Durch den Überlauf wird das "Timer0 Overflow Interrupt Request" erzeugt,> der dann eine ISR anstoßen kann.
Oder man schreibt den Wert wieder in die ISR rein. Gibts dann überhaupt
einen Unterschied dieser beiden modis?
Karl M. schrieb:> Also Timer0 in Modus CTC, mit OCR0A = 125-1 läuft dann immer im 1000Hz> Rhythmus!
Ich brauche ja noch ein 38khz signal. Dieses soll mit 1khz an und
ausgeschaltet werden.
Tinyy schrieb:> Ich brauche ja noch ein 38khz signal. Dieses soll mit 1khz an und> ausgeschaltet werden.
Warum benötigst du für deine LED ein 38kHz Signal, wenn du sie jede
Milisekunde (1kHz) an- / ausschalten möchtest? Deine LED flackert auch
mit 1 kHz nicht.
Meiner Meinung nach kannst du mit CTC die gewünschten Frequenzen besser
einstellen, muss allerdings auch besser wissen, was du genau möchtest.
Ein weiterer Tipp: Bei 38kHz würde ich unbedingt die uC-Taktfrequenz auf
8MHz erhöhen. Sonst läufst du sehr schnell Gefahr, dass der übrige
Programmteil nicht mehr korrekt funktioniert
=> 28 Taktzyklen minus deine ISR = schätzungsweise 5 - 10 Taktzyklen für
dein Main-Programm bis die nächste ISR kommt.
Kannst ja mal deine ASM-Befehle zählen und mit diesen deine
Programmdauer berechnen.
MfG
TM F. schrieb:> Warum benötigst du für deine LED ein 38kHz Signal, wenn du sie jede> Milisekunde (1kHz) an- / ausschalten möchtest? Deine LED flackert auch> mit 1 kHz nicht.
Ich will ein 38khz Trägersignal jede ms ein und ausschalten, also mit
1khz.
Tinyy schrieb:> Ich will ein 38khz Trägersignal jede ms ein und ausschalten, also mit> 1khz.
Ok.
Mit den oben genannten Tipps dürftest du keine Probleme mehr haben.
Rein aus Interesse: Wie hast du die Variable "count" in der ISR
initialisiert?
Ich tippe auf globale Variable (= nicht schön und mit diesem Namen auch
gefährlich)
MfG
> ... dürftest du keine Probleme mehr haben.
Falls doch, und das fürchte ich, mag vielleicht eine fertige Lösung,
wenn auch nur als Muster, weiterhelfen.
S. Landolt schrieb:> Falls doch, und das fürchte ich, mag vielleicht eine fertige Lösung,> wenn auch nur als Muster, weiterhelfen.
Der Ausgang wird nirgends geschalten.
In der Initialisierung muss noch ein
1
PORTB|=(1<<DDB1);
sein.
Damit du den Ausgang nicht auf Eingang wechselst und wieder zurück, hier
die andere Möglichkeit:
Das vorgestellte 'Muster' läuft hier.
Der erste Einwand ist mir völlig unklar, und beim zweiten verstehe ich
nicht, wie sich das mit der eingeschalteten PWM verträgt.
S. Landolt schrieb:> Das vorgestellte 'Muster' läuft hier.> Der erste Einwand ist mir völlig unklar, und beim zweiten verstehe ich> nicht, wie sich das mit der eingeschalteten PWM verträgt.
Ich bin wohl zu fest im CTC-Mode.
Bei diesem müsstest du dies machen.
Btw: Versuche deine Variablen lokal zu definieren und nicht global.
Stichwort "static"
S. Landolt schrieb:> Falls doch, und das fürchte ich, mag vielleicht eine fertige Lösung,> wenn auch nur als Muster, weiterhelfen.
Es funktioniert tatsächlich wie es soll..
Bin den Code durchgegangen, du benutzt den inverting mode (TCCR0A |=
((1<<COM0B0) | (1<<COM0B1));), ich den non-inverting. Hat das eine
Auswirkung, ist ja eigentlich egal, oder nicht?
Dann hast du auf 8Mhz getaktet mit clock_prescale_set(0);. Geht das also
doch ganz einfach mit einem Befehl ohne die Fuse's zu setzen.
Dannach verstehe ich deine Rechnung nicht, eigentlich müsste das doch so
lauten:
f=8Meghz/256 = 31250Hz
T=1/31250Hz= 32µS
0,032ms/1ms = 0,032 overflows.
Vorab: es ist "eine fertige Lösung", sicher nicht die beste, vielleicht
nicht einmal eine besonders gute; aber ich wollte, dass es hier endlich
vorangeht:
Der Worte sind genug gewechselt,
Laßt mich auch endlich Taten sehn!
Indes ihr Komplimente drechselt,
Kann etwas Nützliches geschehn.
Um die maximale interne Frequenz von 16 MHz zu erreichen, muss man, wie
von Arduino Fanboy beschrieben, vorgehen; 8 MHz sind per Programm
möglich.
Woher kommen die "/256"? TOP-Wert ist OCR0A.
S. Landolt schrieb:> Woher kommen die "/256"? TOP-Wert ist OCR0A.
Macht Sinn. Müsste mal schauen, mein code müsste ja eigentlich auch
laufen, kriege aber den Tiny85 nicht mehr geflasht:
1
avrdude.exe: warning: cannot set sck period. please check for usbasp firmware update.
2
avrdude.exe: error: program enable: target doesn't answer. 1
3
avrdude.exe: initialization failed, rc=-1
4
Double check connections and try again, or use -F to override
5
this check.
6
avrdude.exe done. Thank you.
Ich glaube das liegt damit zusammen, dass der Tiny85 jetzt auf 8Mhz
läuft. Habe mit dem -B paramter schon einiges probiert aber wird nicht
erkannt. Eigenlich müsste es bei 8Mhz laufen nur bei langsamen Clock
sollte man ja den USBASP langsamer stellen mit dem -B paramter.
So sieht mein avrdude Befehl aus:
1
-p t85 -c usbasp -P usb -U flash:w:"$(ProjectDir)Debug\$(TargetName).hex":i
> warning: cannot set sck period.
Eigentlich kein erstes Problem.
Aber in Verbindung mit:
> Habe mit dem -B paramter
Dann doch.
Der Parameter wirkt mit der alten Software nicht, sondern nur mit der
frischen Software.
Merke: Das sagt doch auch schon die Meldung
Tipp:
Meldungen mögen unberechtigt, oder auch berechtigt sein...
Aber verstehend lesen, sollte man sie auf jeden Fall.
Also:
Wenn du weiterhin die alte USBasp Firmware nutzen möchtest, musst du, um
einen niedrigen Takt zu erreichen, den SlowClock Jumper auf dem USBasp
Board setzen.
---
Wie hast du die Fuses gesetzt?
Tinyy schrieb:> es klappt aber weder mir noch ohne -B..
Dann nochmal klarer:
-B hat bei deinem Programmer keine Wirkung.
Wir müssen also nicht mehr über den Parameter -B reden.
Sondern:
Du musst einen Jumper auf dem USBasp setzen.
----
Wie hast du die Fuses gesetzt?
Leider sagt ihm das nicht, ob es schon die Fuses geändert hat.
Ich glaube ja nicht.
Wie auch immer:
Ein HVSP Programmer kann es wieder richten!
> (Nichts für ungut)
Möglicherweise hast du in den Fuses gesetzt, dass der Controller über
ISP nicht mehr programmier bar ist.
=> Lösung: Auswechseln :)
Deshalb sei sicher, wie du die Fuses programmierst
S. Landolt schrieb:> Klappt es mit einem anderen AVR8 (so denn einer, hoffentlich, vorhanden> ist)?
Neuen attiny rein klappt auch nicht, selbe Fehlermeldung.
S. Landolt schrieb:> Kann ich mir nicht vorstellen, ich würde erstmal dem Rat "Double check> connections" folgen.
Alle kabel überprüft und neu gesteckt.
Auch den USBASB Windows Treiber neuinstalliert. Das ist doch ziemlich
suspekt.
Den Slow clock-Jumper JP3 gesetzt bringt auch nichts. Also bleibt nur
noch firmware update, dann brauche ich aber einen arduino...
tinyy schrieb:> Den Slow clock-Jumper JP3 gesetzt bringt auch nichts. Also bleibt nur> noch firmware update, dann brauche ich aber einen arduino...
Wenn du den Jumper gesetzt hast, kann der USPasp einen mit
1MHz(Auslieferungszustand) laufenden Attiny85 beschreiben.
Ein Firmwareupdate ist nicht nötig.
Arduino Fanboy D. schrieb:> Wenn du den Jumper gesetzt hast, kann der USPasp einen mit> 1MHz(Auslieferungszustand) laufenden Attiny85 beschreiben.
Neun rein der 1Mhz läuft, klappt nicht.
S. Landolt schrieb:> Ist die Betriebsspannung vorhanden (direkt am ATtiny85 gemessen)?
Ja das Programm was ich vohrin draufgemcaht habe läuft ja auch, led
leuchtet..
tinyy schrieb:> Neun rein der 1Mhz läuft, klappt nicht.>> S. Landolt schrieb:>> Ist die Betriebsspannung vorhanden (direkt am ATtiny85 gemessen)?>> Ja das Programm was ich vohrin draufgemcaht habe läuft ja auch, led> leuchtet..
Kannst Du uns evtl. ein Foto von Deinem Aufbau zeigen?