Forum: Mikrocontroller und Digitale Elektronik tiny2313 SW-PWM


von Christian S. (hunner)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich versuche schon seit einiger Zeit eine SW-PWM mit einem Attiny2313 zu 
erzeugen.
Ich möchte damit RGB-Leds ansteuern. Leider hat dieser Mc nur zwei 
16-Bit-Timer, wesshalb ich das ganze in Software umsetzen möchte. Ich 
denke aber, dass ich bei der Initialisierung einen Fehler gemacht habe.
Sobald ich die Zeile "init_pwm();" hinzufüge, werden die Variablen in 
der main-Funktion nicht mehr initialisiert ( egal ob volantile oder 
nicht).
Ich kann einfach den Fehler nicht finden.

Könnt ihr mir dabei bitte helfen?

hier noch der gesammte Code
1
/*
2
    ATtiny2313 @ 8 MHz
3
*/
4
5
// Defines an den Controller und die Anwendung anpassen
6
7
//#define F_CPU 8000000L                  // Systemtakt in Hz
8
9
#define PWM_STEPS 1024                   // PWM-Schritte pro Zyklus(1..256)
10
#define PWM_PORT PORTB                  // Port für PWM
11
#define PWM_DDR DDRB                    // Datenrichtungsregister für PWM
12
13
// includes
14
15
#include <stdint.h>
16
#include <string.h>
17
#include <avr/io.h>
18
#include <avr/interrupt.h>
19
#include <avr/wdt.h>
20
21
// globale Variablen
22
23
volatile uint16_t pwm_setting[3];                    // Einstellungen für die einzelnen PWM-Kanäle
24
volatile uint16_t pwm_R = 0;                  // Einstellungen für die einzelnen PWM-Kanäle
25
volatile uint8_t pwm_cnt=0;
26
volatile uint8_t tmp = 0;
27
volatile uint8_t j = 0;
28
                  
29
// Timer 1 Output COMPARE A Interrupt
30
31
ISR(TIMER1_COMPB_vect) {
32
  
33
    tmp = 0;
34
    if (pwm_setting[0] < pwm_cnt) tmp |= (1<<0);
35
    if (pwm_setting[1] < pwm_cnt) tmp |= (1<<1);
36
    if (pwm_setting[2] < pwm_cnt) tmp |= (1<<2);
37
38
    PWM_PORT = tmp;                         // PWMs aktualisieren
39
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
40
        pwm_cnt=0;
41
    else
42
        pwm_cnt++;
43
}
44
45
void init_pwm() {
46
    // PWM einstellen
47
  // Timer 1 OCRA1, als variablem Timer nutzen
48
  //Berechnung
49
  //F_CPU = 8000000Hz->125ns; F_PWM = 100Hz->10ms; PWM-STEPS = 1024 Schritte
50
  //->in 5ms 1024 Schritte; pro 125ns um 1 höher
51
  //-> 5ms/(125ns * 1024) -> 78
52
  
53
    TCCR1B |= (1 << CS10);    // Timer läuft mit vollem Systemtakt
54
  TCCR1A = 0x00;  //Register zuruecksetzen
55
  TCCR1B |= (1<<WGM12); //Auto-Zuruecksetzen des Counters aktivieren
56
57
  uint16_t vglB = 78; //Vergleichswert A
58
  OCR1AH = (vglB>>8);
59
  OCR1AL = (vglB & 0x00FF);
60
61
  TIMSK |= (1<<OCIE1B); //Interrupt an Kanal A aktivieren  
62
    sei();                  // Interrupts global einschalten
63
}
64
65
int main(void) {
66
  volatile int i = 10;      //i, j und k für Test  
67
  int k = 1;
68
69
    PWM_DDR = 0xFF;         // Port als Ausgang für PWM
70
    //init_pwm();
71
72
  while(1){
73
  j = j + 1;
74
if ( j > 10)
75
{
76
  i = i + 1;
77
  if ( i == 52)
78
  {
79
    i = 0;
80
  }
81
  j = 0;
82
}
83
  }
84
85
    return 0;
86
}

: Verschoben durch Moderator
von Karl M. (Gast)


Lesenswert?

Hallo Christian,

was passiert, wenn pwm_cnt = (PWM_STEPS-1) ist ?

von Christian S. (hunner)


Lesenswert?

Hallo Karl,

PWM_STEPS ist ganz oben definiert mit 1024 ( 10 Bit)
wenn pwm_cnt (wird bei jedem Aufruf der ISR um eins hochgezählt) = 
PWM_STEPS (1024), also bei "Überlauf"->pwm_cnt=0

von c-hater (Gast)


Lesenswert?

Christian S. schrieb:

> ich versuche schon seit einiger Zeit eine SW-PWM mit einem Attiny2313 zu
> erzeugen.
> Ich möchte damit RGB-Leds ansteuern. Leider hat dieser Mc nur zwei
> 16-Bit-Timer

Hat er nicht. Er hat nur einen 16Bit-Timer. Allerdings besitzt dieser 
zwei PWM-Kanäle...

> wesshalb ich das ganze in Software umsetzen möchte.

Das ist ein sinnvoller Ausweg.

> Ich kann einfach den Fehler nicht finden.

Vielleicht einfach mal den Simulator benutzen?

von chris (Gast)


Lesenswert?

mmhhh mit dem Ty2313 schafft man es zumindest alle 3 farben einer RGB 
Led anzusteuern mit Timer2 = 1x8bit Kanal und Timer 1 = 2x16Bit Kanäle. 
Wenn du noch verrätst wie du die LED's ansteuern willst könnte man 
weiter helfen

von chris (Gast)


Lesenswert?

chris schrieb:
> Wenn du noch verrätst wie du die LED's ansteuern willst könnte man
> weiter helfen

Korrektur WIEVIELE ist die Frage

von Christian S. (hunner)


Lesenswert?

c-hater schrieb:
>> ich versuche schon seit einiger Zeit eine SW-PWM mit einem Attiny2313 zu
>> erzeugen.
>> Ich möchte damit RGB-Leds ansteuern. Leider hat dieser Mc nur zwei
>> 16-Bit-Timer
>
> Hat er nicht. Er hat nur einen 16Bit-Timer. Allerdings besitzt dieser
> zwei PWM-Kanäle...

Stimmt, mein Fehler, aber das ist genau das, was ich meinte,
mir geht ein dritter 16-Bit-pwm-Kanal ab.

>> wesshalb ich das ganze in Software umsetzen möchte.
>
> Das ist ein sinnvoller Ausweg.

Da sonst nicht viel laufen sollte und ich ein paar von den Controllern 
rumliegen habe, denk ich, passt das schon

>> Ich kann einfach den Fehler nicht finden.
>
> Vielleicht einfach mal den Simulator benutzen?

Ja, ich habe den Protheus Professional 8 noch verwendet...Hab aber 
leider keine weiteren Erkenntnisse rausgefunden, ausser dass eben, wenn 
ich den Interrupt aktiviere, die Variablen in der main nicht 
initialisieren kann (siehe Bild vom ersten Beitrag).

von Christian S. (hunner)


Lesenswert?

chris schrieb:
> mmhhh mit dem Ty2313 schafft man es zumindest alle 3 farben einer RGB
> Led anzusteuern mit Timer2 = 1x8bit Kanal und Timer 1 = 2x16Bit Kanäle.
> Wenn du noch verrätst wie du die LED's ansteuern willst könnte man
> weiter helfen

Ja genau, aber 8 Bit sind etwas zu wenig...( ergibt max 255 Abstufungen 
und das ergibt eine nicht so schöne Abstufung)
Hab zum Ansteuern BC547 (oder so) Transistoren, jeweils für eine Farbe) 
verwendet.
Also der Mc wird nicht damit belastet.
Die Ansteuerung läuft in der Realität. Das hab ich schon getestet.
Mein Problem ist, dass wenn ich die PWM initialisieren möchte, keine 
Variablen mehr beschrieben werden.

Leider kann ich mir keinen Reim daraus machen, wieso das so ist.

von chris (Gast)


Lesenswert?

Christian S. schrieb:
> Ja genau, aber 8 Bit sind etwas zu wenig...( ergibt max 255 Abstufungen
> und das ergibt eine nicht so schöne Abstufung)

HÄääää aber habe selber was mit RGBs vor kurzem gebaut und mit 8bit 
kommste schon recht weit. Die Frage ist welche Grundfrequenz du zu 
Grunde legst ? Mir fiel mir auf das man die Abstufung deutlicher wahr 
nimmt wenn man die Grundfrequenz unter einen bestimmten Wert hat/nimmt. 
Zusätzlich musst du beachten das ab einer gewissen Abstufung das Auge 
keine Farbänderung mehr wahr nimmt. ;)

> Hab zum Ansteuern BC547 (oder so) Transistoren, jeweils für eine Farbe)
> verwendet.

Wie lautet der Name deiner RGB LED?


> Die Ansteuerung läuft in der Realität. Das hab ich schon getestet.

gut

> Mein Problem ist, dass wenn ich die PWM initialisieren möchte, keine
> Variablen mehr beschrieben werden.

Moment, von welcher Variablen reden wir die im SRAM angelegt sind oder 
die OCRxy Register ???

Damit OCRxy kann zu jeder Zeit beschrieben werden aber wann der Wert 
wirklich als Referenz genutzt wird hängt vom Timermode ab.

Komme vom ASM aber

> uint16_t vglB = 78; //Vergleichswert A
>  OCR1AH = (vglB>>8);
>  OCR1AL = (vglB & 0x00FF);

Warum Vergleich von 78 im OCR1AH ? Bzw was macht diese Sache hier ?
Sollte der Vergleich nicht auf dem OCR1AL passieren ??

Christian S. schrieb:
> PWM_DDR = 0xFF;         // Port als Ausgang für PWM
>     //init_pwm();

Tut nicht notwendig weil der MOde die volle Funktion der/des Pins 
übernimmt.

von Christian S. (hunner)


Lesenswert?

chris schrieb:
> Christian S. schrieb:
>> Ja genau, aber 8 Bit sind etwas zu wenig...( ergibt max 255 Abstufungen
>> und das ergibt eine nicht so schöne Abstufung)
>
> HÄääää aber habe selber was mit RGBs vor kurzem gebaut und mit 8bit
> kommste schon recht weit. Die Frage ist welche Grundfrequenz du zu
> Grunde legst ? Mir fiel mir auf das man die Abstufung deutlicher wahr
> nimmt wenn man die Grundfrequenz unter einen bestimmten Wert hat/nimmt.
> Zusätzlich musst du beachten das ab einer gewissen Abstufung das Auge
> keine Farbänderung mehr wahr nimmt. ;)

Ja, du hast zum Teil recht.
Die Farbänderung wird wohl nicht so wahrgenommen, aber die Helligkeit 
schon.
Es wirkt ruhiger, wenn die Zeit einer kompletten PWM langsammer ist. Da 
die Helligkeit einer LED aber eine logarithmischen Funktion beschreibt, 
ist es von Vorteil, die Abstufung größer zu machen (für den Bereich nahe 
um 0 [die 16-Bit-PWM kann mit einer Auflösung von 10-Bit -> 1024 
betrieben werden]).

>> Hab zum Ansteuern BC547 (oder so) Transistoren, jeweils für eine Farbe)
>> verwendet.
>
> Wie lautet der Name deiner RGB LED?

Weiß ich nicht genau, es ist eine kleine LED-Leiste von M3. Es besas 
eine
Steuerung für mehrere Farben und wurde am USB-Port betrieben.

>> Die Ansteuerung läuft in der Realität. Das hab ich schon getestet.
>
> gut
>
>> Mein Problem ist, dass wenn ich die PWM initialisieren möchte, keine
>> Variablen mehr beschrieben werden.
>
> Moment, von welcher Variablen reden wir die im SRAM angelegt sind oder
> die OCRxy Register ???

Es geht um alle Variablen im SRAM (aufgefallen ist es mir bei i, j und
volatile uint16_t pwm_setting[3];                    // Einstellungen 
für die einzelnen PWM-Kanäle)

> Damit OCRxy kann zu jeder Zeit beschrieben werden aber wann der Wert
> wirklich als Referenz genutzt wird hängt vom Timermode ab.

Ja, weiß ich.

> Komme vom ASM aber
>
>> uint16_t vglB = 78; //Vergleichswert A
>>  OCR1AH = (vglB>>8);
>>  OCR1AL = (vglB & 0x00FF);
>
> Warum Vergleich von 78 im OCR1AH ? Bzw was macht diese Sache hier ?
> Sollte der Vergleich nicht auf dem OCR1AL passieren ??

Ja, du hast recht.
Hierbei handelt es sich aber nicht um einen Vergleich.
Zur Erklährung: Zuerst wird eine 2x8Bit-Variable geschrieben (vglB)
in der nächsten Zeile wird vglB um 8 Positionen nach rechts geshiftet 
und an OCR1AH.
In der letzten Zeile werden die unteren 8 Bit von vglB an OCR1AL 
übergeben.

> Christian S. schrieb:
>> PWM_DDR = 0xFF;         // Port als Ausgang für PWM
>>     //init_pwm();
>
> Tut nicht notwendig weil der MOde die volle Funktion der/des Pins
> übernimmt.

Ja, aber ich muss doch die jeweiligen Pins als Ausgang setzen?!?.

von Thomas E. (picalic)


Lesenswert?

Christian S. schrieb:
> wenn pwm_cnt (wird bei jedem Aufruf der ISR um eins hochgezählt) =
> PWM_STEPS (1024), also bei "Überlauf"->pwm_cnt=0

Und wie, bitte, soll pwm_cnt bis 1024 zählen? pwm_cnd ist als "uint8_t" 
deklariert, geht nur bis 255.

von Christian S. (hunner)


Lesenswert?

Thomas E. schrieb:
> Christian S. schrieb:
>> wenn pwm_cnt (wird bei jedem Aufruf der ISR um eins hochgezählt) =
>> PWM_STEPS (1024), also bei "Überlauf"->pwm_cnt=0
>
> Und wie, bitte, soll pwm_cnt bis 1024 zählen? pwm_cnd ist als "uint8_t"
> deklariert, geht nur bis 255.

Ja, stimmt.

Mein Fehler :-| kommt wohl vom ewigen ändern/testen. Werd in ändern.

von Karl M. (Gast)


Lesenswert?

Hallo Christian,

Christian S. schrieb:
> PWM_STEPS ist ganz oben definiert mit 1024 ( 10 Bit)
> wenn pwm_cnt (wird bei jedem Aufruf der ISR um eins hochgezählt) =
> PWM_STEPS (1024), also bei "Überlauf"->pwm_cnt=0

> Und wie, bitte, soll pwm_cnt bis 1024 zählen? pwm_cnd ist als "uint8_t"
> deklariert, geht nur bis 255.

Darin begründet lang auch mein indirekte Frage, somit ist dies nun 
geklärt.

von chris (Gast)


Lesenswert?

Christian S. schrieb:
>> Christian S. schrieb:
>>> PWM_DDR = 0xFF;         // Port als Ausgang für PWM
>>>     //init_pwm();
>>
>> Tut nicht notwendig weil der MOde die volle Funktion der/des Pins
>> übernimmt.
>
> Ja, aber ich muss doch die jeweiligen Pins als Ausgang setzen?!?.

NEIN das ist es ja. Das ist mit der Übergabe auf die Zweit/Dritt/Nx 
Funktion des Pins Geschichte. Diese Funktion übernimmt die komplette 
Steuerung des Pins bis du wieder auf die Normalfunktion des Pin zurück 
schaltest. Ausser es ist explizit erwähnt das man händisch in diese 
erweiterte Pinfunktion eingreifen kann/muss.

> Weiß ich nicht genau, es ist eine kleine LED-Leiste von M3.

naja zumindest solltest mal in die Daten gucken wieviel Strom die Dinger 
bräuchten damit du den Transistor nicht überlastest.

> Die Farbänderung wird wohl nicht so wahrgenommen, aber die Helligkeit
> schon.

Die Farbänderung ist doch das Produkt der einzelnen RGB's-LED in ihrer 
Helligkeit. Also hört die Wahrnehmung doch dann auf wenn auch der 
Bereich erreicht ist, in der die Helligkeit einer Einzelnen nicht mehr 
wahrgenommen wird.

> Es geht um alle Variablen im SRAM (aufgefallen ist es mir bei i, j und
> volatile uint16_t pwm_setting[3];                    // Einstellungen
> für die einzelnen PWM-Kanäle)

Da bin ich leider raus Hochsprache ist nicht mein Ding aber aus der 
Erfahrung würde ich mich dem was Thomas Elger schrieb anschließen und es 
noch erweitern. Heißt das man entweder die falsche Variable hat oder man 
schreibt in die richtige Variable nur deren Wirkung hat keine Effekt 
weil man sie nicht abruft oder deren Inhalt für die Funktion zu groß ist 
weil die Schleife begrenzt (0-5 = Schleife; Variable = 90).

von Christian S. (hunner)


Lesenswert?

Hi Chris,

wie schon geschrieben, funktioniert alles, ausser dass ich eben die 
Variablen der main im SRAM nicht deklarieren kann, wenn ich den Timer 
setze.
Hab aber nochmal getestet, wenn ich in die main
1
pwm_setting[0] = 10;
2
pwm_setting[1] = 0;
3
pwm_setting[2] = 0;
 schreibe, so funktioniert es.

Was nicht geht, ist z.B.:
1
 pwm_setting[0] = i;
da i dann nicht deklariert werden kann. (Warum auch immer)
Ich versteh nicht, was ich beim initialisieren, oder sonst wo falsch 
mache.

von Christian S. (hunner)


Lesenswert?

Hi Leute.
hatte leider die letzte Zeit keine Zeit für dieses Projekt.
Bin nun draufgekommen, dass sich das Array "pwm_setting[]; " nicht mit 
den Werten aus einem anderen Array beschreiben ließ (warum auch 
immer...) und habe dieses durch drei einzelne Variablen erseetzt. Das 
zweite Array war leider recht groß und überschritt den restlichen 
Speicher (hab ich erst später bemerkt :-| ). Ausserdem wurde die ISR zu 
oft aufgerufen, wesshalb die main zu selten bearbeitet wurde. Nun läuft 
aber alles, so wie es soll :-).

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.