Forum: Mikrocontroller und Digitale Elektronik Attiny85 PWM


von tinyy (Gast)


Lesenswert?

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?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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?

von c-hater (Gast)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Falls du da eine IR Fernbedienung basteln möchtest, schau dir zuerst mal 
bitte IRSND an, das kann eine Menge Arbeit ersparen:
https://www.mikrocontroller.net/articles/IRSND#top

von tinyy (Gast)


Lesenswert?

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
12
  sei(); // Global Interrupts aktivieren
13
  
14
    while (1) 
15
 {
16
      
17
 }
18
}
19
20
ISR( TIMER0_OVF_vect )       // Overflow Interrupt Vector
21
{
22
  static uint8_t swTeiler = 0;
23
24
  swTeiler++;
25
  if( swTeiler == 2 ) {    
26
    PORTB = PORTB ^ 0xFF;   
27
  }
28
}

von Tim (Gast)


Lesenswert?

tinyy schrieb:
> AM Pin B1 passiert nichts.
Nunja, am Timer 1 muß ja erstmal auch noch die PWM initialisiert werden.

von tinyy (Gast)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

>  TCCR0A = (1<<CS01); // Prescaler 8 CS02 und 00 für 1024
Da schreibst du ins falsche Register und der Timer wird nie gestartet.

: Bearbeitet durch User
von tinyy (Gast)


Lesenswert?

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

von c-hater (Gast)


Lesenswert?

tinyy schrieb:

> Laut Datenblatt ist es aber TCR0A

Nein, ist es nicht. Es ist TCCR0A.

Das Blöde ist halt nur, dass es darin keine CSxy-Bits gibt...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

: Bearbeitet durch User
von tinyy (Gast)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

: Bearbeitet durch User
von Holger L. (max5v)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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/

von tinyy (Gast)


Lesenswert?

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}

von Dieter F. (Gast)


Lesenswert?

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.

von Holger L. (max5v)


Lesenswert?

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?

von Dieter F. (Gast)


Lesenswert?

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

von Holger L. (max5v)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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
3
  TCCR0A |= ((1<<COM0B0) | (1<<COM0B1)); // inverting Mode. COM0b1=1 und COM0B0=0 Non-Inverting
4
  TCCR0B |= ((1<<CS02) | (1<<CS00)); // Prescaler: CS02 und CS00 =1 für 1024 f_pwm=f_clk/Prescale*256
5
  //OCR0A = 28;
6
  OCR0B = 10;
7
  DDRB  |=  ((1<<DDB0) | (1 << DDB1)); // Output

von S. Landolt (Gast)


Lesenswert?

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

von tinyy (Gast)


Lesenswert?

und was macht OCR0B? Wenn ich den OC0B Pin benutze dachte ich muss ich 
auch entsprechend in OCR0B den TOP-Wert einsetzen oder nicht?

von S. Landolt (Gast)


Lesenswert?

> und was macht OCR0B?
Bestimmt den Tastgrad der PWM.

von spess53 (Gast)


Lesenswert?

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

von tinyy (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

Mode7: OCR0A bestimmt die Frequenz der PWM, OCR0B den Tastgrad der PWM.
Sie wissen, was eine PWM (deutsch: Pulsbreitenmodulation) ist?

von Cyblord -. (cyblord)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von TM F. (p_richner)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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.

von Cyblord -. (cyblord)


Lesenswert?

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.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

: Bearbeitet durch User
von TM F. (p_richner)


Lesenswert?

Vielleicht eine Lösung in Textform. Die Implementierung müsstest du 
selber machen:
1
init_timer()
2
{
3
Prescaler setzen
4
Mode auf CTC setzen
5
Output Compare Register A und B setzen
6
Counter starten
7
}
8
9
ISR Wenn timer_counter = OCR0B
10
{
11
Ausgangspin auf 1 setzen
12
}
13
14
ISR Wenn timer_counter = OCR0A
15
{
16
Ausgangspin auf 0 setzen
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

von tinyy (Gast)


Lesenswert?

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?

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

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?

von S. Landolt (Gast)


Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

"ist" -> "ich" - ich geb's auf. Und tschüss.

von S. Landolt (Gast)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

Schon richtig - aber heute ginge beim Fuse-setzen sicher etwas schief.

von TM F. (p_richner)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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

von Dieter F. (Gast)


Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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

von Dieter F. (Gast)


Lesenswert?

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.

von Rainer V. (a_zip)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

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.

von Dieter F. (Gast)


Lesenswert?

Rainer V. schrieb:
> ausgibt, auf Eingang

Erkennst Du einen leichten Widerspruch?

von Dieter F. (Gast)


Lesenswert?

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.

von Rainer V. (a_zip)


Lesenswert?

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

Beitrag #5704632 wurde von einem Moderator gelöscht.
von tinyy (Gast)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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.

von Karl M. (Gast)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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.

von Karl M. (Gast)


Lesenswert?

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!

von tinyy (Gast)


Lesenswert?

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.

von Karl M. (Gast)


Lesenswert?

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!

von Tinyy (Gast)


Lesenswert?

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.

von TM F. (p_richner)


Lesenswert?

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

von TM F. (p_richner)


Lesenswert?

Nachtrag: Wenn du ein Pin toggeln möchtest, geht es am einfachsten mit
1
   PINxx = 1; // Kapitel 10.1

(Wenn Pin als Ausgang geschaltet ist.)

von Tinyy (Gast)


Lesenswert?

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.

von TM F. (p_richner)


Lesenswert?

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

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

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

von TM F. (p_richner)


Lesenswert?

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:
1
PINB |= (1<<DDB1);

von S. Landolt (Gast)


Lesenswert?

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.

von TM F. (p_richner)


Lesenswert?

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"

von S. Landolt (Gast)


Lesenswert?

Danke für den Hinweis. Als reiner Assemblerprogrammierer habe ich von C 
nicht allzuviel Ahnung.

von tinyy (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

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.

von tinyy (Gast)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

> ... dass der Tiny85 jetzt auf 8Mhz läuft ...
Kann ich mir nicht vorstellen, ich würde erstmal dem Rat "Double check 
connections" folgen.

von Einer K. (Gast)


Lesenswert?

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

von Tinyy (Gast)


Lesenswert?

es klappt aber weder mir noch ohne  -B..

von S. Landolt (Gast)


Lesenswert?

Klappt es mit einem anderen AVR8 (so denn einer, hoffentlich, vorhanden 
ist)?

von Einer K. (Gast)


Lesenswert?

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?

von S. Landolt (Gast)


Lesenswert?

Gestatten Sie mir den kleinen Seitenhieb:
> Da gibts nicht viel zu erläutern.....
Murphy lässt grüßen.
(Nichts für ungut)

von Einer K. (Gast)


Lesenswert?

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)

von TM F. (p_richner)


Lesenswert?

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

von tinyy (Gast)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> Alle kabel überprüft
Ist die Betriebsspannung vorhanden (direkt am ATtiny85 gemessen)?

von tinyy (Gast)


Lesenswert?

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

von Tim (Gast)


Lesenswert?

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?

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.