Forum: Mikrocontroller und Digitale Elektronik 8 bit PWM steuert nicht voll aus / casting problem


von cepheus (Gast)


Lesenswert?

hi,
ich habe 2 Probleme mit einem mega8.
1. Ich verwende 3 PWMs:
1
        TCCR1A |= (1 << CS01);
2
        TCCR1A |= (1<<WGM10);
3
        TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
4
        TCCR1B |= (1 << CS11);
5
        TCCR2 |= (1 << WGM20) | (1 << COM21);
6
        TCCR2 |= (1 << CS21) |(1 << CS20);
OC2 funktioniert einwandfrei, die OC1A/B sind aber erst bei 100% wenn 
ich 1023 in die Register schreibe, obwohl das Ganze doch 8 bit sein 
sollte?. Habe ich da was uebersehen?

2. Betrifft das erste nur etwas:
Die OCs steuern LEDs, ich wuerde dazu gerne Farb- und Helligkeitswerte 
kombinieren, und zwar getrennt.
Dazu folgendes Codeschnipsel, ergibt jetzt zwar wenig Sinn weil ich es 
zum debuggen schon ziemlich verwurstet habe, aber das
Problem konnte ich, egal wie weit ich das betrieben habe, nicht
beseitigen.
1
        if(mode_nmb > 4)  {
2
                uint8_t red = 0;
3
                red = (uint8_t)((uint16_t)value_current[0]*brightness[mode_nmb])/100;
4
                OCRED = red;
Erklaerung: value_current[] enthaelt den jeweiligen Farbwert, der mit 
einem zugehoerigen Helligkeitswert aus dem brightness[] (0-100) 
kombiniert werden soll.
Sobald ich jetzt in diesen Fall wandere, passieren die seltsamsten 
Dinge. Andere Variablen werden ueberschrieben, der Controler haengt sich 
auf, etc.
Hoffe, ihr koennt mir helfen, vielen Dank schonmal.

von Matthias L. (Gast)


Lesenswert?

wie wäre es mit etwas mehr Quellcode?

von cepheus (Gast)


Lesenswert?

Gerne, von was genau? Das ganze Teil ist ziemlich viel und noch recht 
unuebersichtlich, wollte ich jetzt keinem antun.
Glaube 2. hat sich gerade erledigt, schein mich einfach mit der casterei 
verhauen zu haben (blame me, aber ich hab wirklich vorher >2h probiert).

von Naja (Gast)


Lesenswert?

>Gerne, von was genau?

Für solche Fälle gilt folgendes:
Reduziere den Code auf das absolut notwendigste, so das der Fehler 
reproduzierbar ist.

von cepheus (Gast)


Lesenswert?

Okay, hier die kleine Version. Ich erkenne an der LED am OCR1B durch die 
Schleife eine deutliche Helligkeitsschwankung.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <inttypes.h>
4
#include <util/delay.h>
5
6
void init( void )
7
{
8
9
        PORTB = (1 << PB0) | (1 << PB6) | (1 << PB7);
10
        DDRB = (1 << PB1) | (1 << PB2) | (1 << PB3);
11
12
        TCCR1A |= (0 << CS02) | (1 << CS01) | (0 << CS00);
13
        TCCR1A |= (0 << WGM12) | (0<<WGM11) | (1<<WGM10);
14
        TCCR1A |= (1<<COM1A1) | (0 << COM1A0) | (1<<COM1B1) | (0 << COM1B0);
15
        TCCR1B |= (0<<CS12) | (1 << CS11) | (0 <<CS10);
16
        //blue 8 bit
17
        TCCR2 |= (0 << WGM21) | (1 << WGM20) | (1 << COM21) | (0 << COM20);
18
        TCCR2 |= (0 << CS22) | (1 << CS21) |(1 << CS20);
19
20
}
21
22
int main(void)
23
{
24
        init();
25
        while ( 1 ){
26
                OCR1B = 255;
27
                _delay_ms(50);
28
                OCR1B = 1023;
29
                _delay_ms(50);
30
        }
31
}

von Naja (Gast)


Lesenswert?

Da Du in der Hauptschleife nur Timer 1 verwendest, ist der minimale 
Code:
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <inttypes.h>
4
#include <util/delay.h>
5
6
void init( void )
7
{
8
9
        PORTB = (1 << PB0) | (1 << PB6) | (1 << PB7);
10
        DDRB = (1 << PB1) | (1 << PB2) | (1 << PB3);
11
12
        TCCR1A |= (1 << CS01;
13
        TCCR1A |= (1<<WGM10);
14
        TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
15
        TCCR1B |= (1 << CS11);
16
}
17
18
int main(void)
19
{
20
        init();
21
        while ( 1 ){
22
                OCR1B = 255;
23
                _delay_ms(50);
24
                OCR1B = 1023;
25
                _delay_ms(50);
26
        }
27
}

Leider kann ich selbst mit "Ich erkenne an der LED am OCR1B durch die
Schleife eine deutliche Helligkeitsschwankung." nicht viel anfangen. Ist 
das gut oder schlecht?

Du schriebst: "die OC1A/B sind aber erst bei 100% wenn
ich 1023 in die Register schreibe, obwohl das Ganze doch 8 bit sein
sollte?."

Ich weiss ja nicht welchen Prozessor Du verwendest, aber bei den AVRs 
ist Timer 1, soweit ich weiss ein 16Bit Timer. Daher scheint es mir 
völlig verständlich, das nur bei 1023 die volle Helligkeit eintritt, da 
nur das die maximale PWM ergibt.

von Naja (Gast)


Lesenswert?

Da Du zwischen 255 und 1023 wechselst, sollte auch eine 
Helligkeitsschwankung da sein.
Was ist Dein Takt?
Je nachdem sieht man die Schwankung auch.

von Naja (Gast)


Lesenswert?

Wahrscheinlich ein Fall von RTFM ;-)

von cepheus (Gast)


Lesenswert?

Zum ersten: Es ist schlecht, weil ich bei 8-bit bei 255 das Maximum 
erwarte.
Wie oben erwaehnt, ist ein Mega8, da ist Timer1 schon 16bit, klar.
Nur habe ich durch die WGM bits den in den 8-bit PWM-Modus gesetzt. Oder 
habe ich am Datenblatt was grundlegend falsch verstanden? Da steht fuer 
diesen Modus als Top "0x00FF".

@Naja: 8MHz. Die Schwankung ist hier zu Testzwecken beabsichtigt, ich 
wollte den Unterschied der beiden Visualisieren.

von Naja (Gast)


Lesenswert?

OK. Das mit dem ATMega8 habe ich überlesen. (Bitte Gross-Kleinschreibung 
beachten).

1. Die Clock-Select Bits CS01 in dem Steuerregister A von Timer 1 zu 
setzen gibt wahrscheinlich Murks.
2. Mit dem 8 Bit Modus hast Du eigentlich recht. Da aber in 255 und 1023 
alle 8 niederwertigen Bits gesetzt sind, dürfte das garkeine 
Helligkeitsveränderung geben. Merkwürdig.

Ändere mal das mit CS01 und probiere es nochmal. Poste den dann 
enstandenen Code (bitte ohne 0 << 109120912, das gibt sowieso nur 0)

von Naja (Gast)


Lesenswert?

Das fehlgeleitete CS01 stellt Dir eine 10-Bit PWM ein. Deswegen gibt es 
eine Änderung der Helligkeit zwischen 255 und 1023.

von cepheus (Gast)


Lesenswert?

Oh danke, das hatte ich ueberlesen dass das da nicht hingehoert.
Sieht gleich viel besser aus (== 255 ist volle Helligkeit).
Was rauskommt ist mir dann auch klar, CS01 ist als 1 definiert, also in 
dem
Fall setzt er dann WGM11 und WGM10, das gibt 10-bit PWM.
Hier trotzdem nochmal der funktionierende Code.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <inttypes.h>
4
5
#include <util/delay.h>
6
7
void init( void )
8
{
9
        DDRB = (1 << PB1) | (1 << PB2) | (1 << PB3);
10
11
        TCCR1A |= (1<<WGM10);
12
        TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
13
        TCCR1B |= (1 << CS11);
14
15
}
16
17
int main(void)
18
{
19
        init();
20
        while ( 1 ){
21
                OCR1B = 255;
22
                _delay_ms(50);
23
                OCR1B = 1023;
24
                _delay_ms(50);
25
        }
26
}

von Naja (Gast)


Lesenswert?

Na bestens.

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.