Forum: Mikrocontroller und Digitale Elektronik ADC und PWM am ATtiny84


von Felix (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte mit 4 Potis 4 LEDs über PWM dimmen. Dafür habe ich mir mit 
Hilfe des Datenblatts zum ATtiny84 und ein paar Codebeispielen aus dem 
Internet ein Programm zusammengebaut. Leider Funktionier Garnichts. Die 
LEDs an den PWM Ausgängen bleiben aus. Im Anhang ist mein Programm.

Vielleicht kann sich das ja mal einer genauer Anschauen. Bin für jede 
Hilfe dankbar.

Gruß Felix

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Passiert GAR NICHTS, oder irgend was, was Du so nicht erwartet hättest?

Hast Du schon Mal probiert, hier und da im Programm einen Ausgang zu 
toggeln, damit man sieht, daß das Programm zumindest läuft?

Hatte mit den While-Schleifen Bedenken, sind aber in dem Beispiel:
http://rn-wissen.de/wiki/index.php/ADC_(Avr)
ebenso ausgeführt - wird's dann wohl nicht sein.

MfG

von holger (Gast)


Lesenswert?

Hier sind deine fehlerhaften Zeilen:

  ADMUX = (0<<REFS1) | (1<<REFS0);
  ADMUX = (1<<ADLAR);
  ADMUX = (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);

  //ADC einschalten
  //Prescaler auf 64 (8.000.000Hz / 64 = 125.000Hz)
  ADCSRA = (1<<ADEN);
  ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);

Denk mal drüber nach was nach jeder ausgeführten Codezeile
im jeweiligen Register steht.

>   ADMUX = (0<<MUX3) | (0<<MUX2) | (2<<MUX1) | (0<<MUX0);

Die '2' ist da mit Sicherheit auch falsch.

von Felix (Gast)


Lesenswert?

Hallo,
das mit der ist mir klar, hab ich mich wohl vertippt. Aber was in den 
anderen Fehlerhaften Zeilen ist, weiß ich nicht genau worauf du hinaus 
willst. Währe schön wenn du mir es mal erklären könntest.

Gruß Felix

von Karl M. (Gast)


Lesenswert?

Hallo Felix,

das ist ein grundsätzliches Problem, erst muss man C lernen, dann die 
Bitmanipulation - um die geht es hier - beherrschen, dann kann man die 
Vorgaben aus dem Datenblatt auch umsetzen.

Also:
a = b;
a |= c;
a &= ~(d);

a = (1<<2);
a = (a & ~(0b00001111)) | 0b00000011;

Dies sind einige Beispiele die Du aus dem "ff" beherrschen müsstest.
Damit will ich Dich nicht angreifen, nur die nächste Lernstufe 
aufzeigen.
Wir habe alle mal von Null angefangen.
Mach weiter.

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


Lesenswert?

holger schrieb:
> ADMUX = (0<<REFS1) | (1<<REFS0);
>   ADMUX = (1<<ADLAR);
>   ADMUX = (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);

Da du immer ein '=' schreibst, wird der jeweils vorherige Zustand 
überschrieben. Das gilt nicht nur für ADMUX, sondern auch für deine 
anderen Registermanipulationen.
Du solltest also verODERn.

von C tut weh (Gast)


Lesenswert?

Karl M. schrieb:
> das ist ein grundsätzliches Problem, erst muss man C lernen...

Naja, nicht unbedingt. Man kann auch eine Sprache verwenden, die mittels 
des Befehls "Bits" nur die Bits im entsprechenden Register setzt, die 
gesetzt werden sollen und die anderen in Ruhe läßt. Ohne VerOderungen 
und/oder VerUndungen oder VerRenkungen.

$regfile = "attiny84.dat"

 Admux = Bits(refs0 , Adlar)
 Adcsra = Bits(aden , Adps2 , Adps1)

 Do
    nop
 Loop

von Walter S. (avatar)


Lesenswert?

C tut weh schrieb:
> Naja, nicht unbedingt. Man kann auch eine Sprache verwenden, die mittels
> des Befehls "Bits" nur die Bits im entsprechenden Register setzt, die
> gesetzt werden sollen und die anderen in Ruhe läßt. Ohne VerOderungen
> und/oder VerUndungen oder VerRenkungen.

wenn du BASCOM meinst, das kenne ich zwar nicht wirklich, aber auch da 
sind Veroderungen nötig (aus 
http://www.roboternetz.de/community/threads/45591-Wie-Mehrere-Bits-in-Register-setzen):

Gicr = Gicr Or Bits(int1) -> Setzt Bit7 in Register GICR

Bascom macht daraus:
IN      R16,0x3B         In from I/O location
PUSH    R16              Push register on stack
LDI     R24,0x80         Load immediate
MOV     R20,R24          Copy register
POP     R16              Pop register from stack
OR      R16,R20          Logical OR
OUT     0x3B,R16         Out to I/O location

und so richtig optimaler Code scheint das auch nicht

von S. Landolt (Gast)


Lesenswert?

Das Problem von Felix ist doch, dass er (noch) nicht erkennt, dass in 
der Sequenz
1
  ADCSRA = (1<<ADEN);
2
  ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
der zweite Befehl den ersten glatt annulliert.
Nach der Argumentation von 'C tut weh' wären bei dieser anderen 
Programmiersprache nach
1
  ADCSRA = Bits(ADEN)
2
  ADCSRA = Bits(ADPS2,ADPS1)
in ADCSRA alle drei Bits ADEN, ADPS2 und ADPS1 gesetzt! ? - Sehr 
interessant, um welche Sprache handelt es sich?

von C tut weh (Gast)


Lesenswert?

S. Landolt schrieb:
> Nach der Argumentation von 'C tut weh' wären bei dieser anderen
> Programmiersprache nach  ADCSRA = Bits(ADEN)
>   ADCSRA = Bits(ADPS2,ADPS1)
> in ADCSRA alle drei Bits ADEN, ADPS2 und ADPS1 gesetzt! ? - Sehr
> interessant, um welche Sprache handelt es sich?

Es handelt sich um Bascom. Der Befehl "Bits" setzt die Bits in der 
Klammer in dem jeweiligen Register. Alle Anderen (nicht genannten) 
bleiben, wie sie vorher waren. Als Gegenstück gibt es dann "NBits", der 
alle Bits in der Klammer löscht.

Natürlich ist es auch wichtig, die Bitmanipulationsbefehle zu kennen und 
richtig benutzen zu können -wenn man sie braucht. Wenn man sie aber 
NICHT braucht, dann kann man dadurch Fehlerquellen eliminieren und man 
sieht auf einen Blick, was los ist.

(Ich habe nicht geprüft, ob die gesetzten Bits aus der Frage des TO den 
von ihm gewünschten Effekt erzielen -ich habe es nur so übernommen, wie 
er es stehen hatte.)

von manmanman (Gast)


Lesenswert?

C tut weh schrieb:
> Es handelt sich um Bascom. Der Befehl "Bits" setzt die Bits in der
> Klammer in dem jeweiligen Register. Alle Anderen (nicht genannten)
> bleiben, wie sie vorher waren.

Das stimmt nicht! Es muß genauso verodert werden, wenn schon gesetzte 
Bits im Ziel nicht verändert werden sollen.

von C tut weh (Gast)


Lesenswert?

manmanman schrieb:
> Das stimmt nicht!

Natürlich stimmt das. Probiers aus und verwirre die Leser nicht!

von S. Landolt (Gast)


Lesenswert?

> ...Es muß genauso verodert werden...

Genauso sehe ich das nämlich auch. Und Felix hat ja nicht nach einer 
kürzeren oder eleganteren Schreibweise gefragt, er sucht Fehler im 
Programm.
  Aber nach Argumentation und Wortspielen den Autor ahnend, möchte ich 
mich an dieser Stelle verabschieden. Einen schönen Abend allerseits!

von Karl M. (Gast)


Lesenswert?

Guten Abend,

immer diese Mutmaßungen, die Onlinehilfe ist doch zu Var = Bits(b1 
[,bn]) eindeutig.

https://avrhelp.mcselec.com/index.html?bits.htm

Man muss bei weiterem Zugriff auf das selbe Register dieses auch sich 
selbst (ODER) beziehen.

Als Beispiel sind die unten gezeigten Zeilen ok.

C tut weh schrieb:
> Karl M. schrieb:
>> das ist ein grundsätzliches Problem, erst muss man C lernen...
>
> Naja, nicht unbedingt. Man kann auch eine Sprache verwenden, die mittels
> des Befehls "Bits" nur die Bits im entsprechenden Register setzt, die
> gesetzt werden sollen und die anderen in Ruhe läßt. Ohne VerOderungen
> und/oder VerUndungen oder VerRenkungen.
>
> $regfile = "attiny84.dat"
>
>  Admux = Bits(refs0 , Adlar)
>  Adcsra = Bits(aden , Adps2 , Adps1)
>
>  Do
>     nop
>  Loop

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


Lesenswert?

C tut weh schrieb:
> Es handelt sich um Bascom.

Wie kommt ihr auf Bascom? Der TE schreibt in C und nicht in Basic.

von manmanman (Gast)


Lesenswert?

C tut weh schrieb:
> manmanman schrieb:
>> Das stimmt nicht!
>
> Natürlich stimmt das. Probiers aus und verwirre die Leser nicht!

Dann gib mir mal ein Beispiel zum probieren. Unten stehendes eignet sich 
nicht, da nicht bekannt ist, was in Admux oder Adcsra zu Beginn steht. 
Im Zweifel sind alle "0" (Tipp: Probier es erstmal selber aus)

C tut weh schrieb:
> Naja, nicht unbedingt. Man kann auch eine Sprache verwenden, die mittels
> des Befehls "Bits" nur die Bits im entsprechenden Register setzt, die
> gesetzt werden sollen und die anderen in Ruhe läßt. Ohne VerOderungen
> und/oder VerUndungen oder VerRenkungen.
>
> $regfile = "attiny84.dat"
>
>  Admux = Bits(refs0 , Adlar)
>  Adcsra = Bits(aden , Adps2 , Adps1)
>
>  Do
>     nop
>  Loop

von C tut weh (Gast)


Angehängte Dateien:

Lesenswert?

manmanman schrieb:
> Unten stehendes eignet sich
> nicht, da nicht bekannt ist, was in Admux oder Adcsra zu Beginn steht.
> Im Zweifel sind alle "0" (Tipp: Probier es erstmal selber aus)

Natürlich ist das bekannt: Der Initialwert der Bits des Registers steht 
im Datenblatt. (Siehe Anhang) Da hinein muß man sowieso sehen, um die 
gewünschte Betriebsart einstellen zu können.

von manmanman (Gast)


Lesenswert?

C tut weh schrieb:
> manmanman schrieb:
>> Im Zweifel sind alle "0" (Tipp: Probier es erstmal selber aus)
>
> Natürlich ist das bekannt: Der Initialwert der Bits des Registers steht
> im Datenblatt. (Siehe Anhang) Da hinein muß man sowieso sehen, um die
> gewünschte Betriebsart einstellen zu können.

Und? Weiter? Was soll ich nun probieren?

von C tut weh (Gast)


Lesenswert?

manmanman schrieb:
> Und? Weiter? Was soll ich nun probieren?

Das weiß ich doch nicht, was Du probieren sollst. Du mußt doch selbst 
wissen, welche Betriebsart Du einstellen willst. Da das Register initial 
mit Null gefüllt ist, mußt Du nachsehen, welche Bits gesetzt werden 
sollen.
Das kann ich doch nicht für Dich entscheiden.

von manmanman (Gast)


Lesenswert?

C tut weh schrieb:
> manmanman schrieb:
>> Und? Weiter? Was soll ich nun probieren?
>
> Das weiß ich doch nicht, was Du probieren sollst.

Viel Glück bei deiner Interpretation des BITS Befehls in Bascom. Das 
wirst du brauchen.

von Felix (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

danke erst mal für die ganzen Antworten. Um nochmal auf das Thema 
zurückzukommen: Ich habe mich da noch mal eingelesen und mein Programm 
überarbeitet. Das auslesen vom ADC funktioniert jetzt. ABER: Egal an 
welchem ADC-Kanal ich das Signal auslese und einem der PWM-Kanäle 
zuordne, es wird immer an den Kanal OC1B (PB5) ausgegeben. Muss ich die 
einzelnen ADC-Kanäle speziell auslesen oder ist der Befehl ADCH in 
dieser Situation richtig? Gibt es irgend eine Seite, die man empfehlen 
kann wenn es um Code-Beispiele für den AVR in C gibt?

Danke schon mal für jede weitere Hilfe!!

Gruß Felix

von Karl M. (Gast)


Lesenswert?

Hallo Felix,

ich sage / schreibe nur
1
while (1) 
2
  {    
3
    adc_init();
4
    pwm_init();
5
...
6
  }

Und warum programmierst Du nicht weiter funktional ?
1
uint16_t readADC_Channel( uint8_t channel )
2
{
3
  uint16_t result = 0;
4
// adc Kanal auswählen
5
...
6
// adc Messung starten
7
...
8
// adc Warte auf das Ende der Messung 
9
...
10
// das Ergebnis auslesen
11
...
12
// und zurückliefern
13
  return result;
14
}

Dann solltest Du dich mit den DIDRn Digital Input Disable Register 
beschäftigen.

Wenn Du mal nicht Vcc als Referenz verwenden möchtest
ADMUX - REFS[1:0] = 00 : "Vcc used as analog reference, disconnected 
from PA0 (AREF)"
Dann würde mann bei deinem Vorgehen immer die REFS[1:0] Bits in ADMUX 
überschreiben.
Im Modus Single Ended Input sind nicht alle MUX[5:0] Bits von 
Bedeutung, den man hat nur ADC0 bis ADC7 als Auswahl.
Also sind nur MUX[2:0] betroffen.

Besser ist es dann den Kanal wie folgt neu zu setzten:
1
ADMUX = (ADMUX & ~( 0b000111 )) | (channel & 0b000111);
Die Atmel Entwickler habe zum Glück für den single ended input die 
MUX[2:0] Bits passend belegt.

von Karl M. (Gast)


Lesenswert?

Hallo Felix,

noch etwas, wenn man eine ADC-Wandlung anwirft, muss man sie auch 
auslesen und kann sie dann das Ergebnis verwerfen.
[c]void adc_init(void)
{
...
  //Messung starten
  ADCSRA |= (1 << ADSC);
  //Warten auf Ergebnis
  while (ADCSRA & (1 << ADSC));
  // und nun noch den ADC auslesen und den Wert verwerfen.
...
}

von Oliver S. (oliverso)


Lesenswert?

Karl M. schrieb:
>   // und nun noch den ADC auslesen und den Wert verwerfen.

... aber nur, wenn das ganze an einem Freitag, den 13. stattfindet indem 
gleichzeitig Neumond ist. Sonst sollte man zur Sicherheit die ersten 42 
Werte verwerfen.

Man könnte das aber auch einfach sein lassen.

Oliver

von Felix (Gast)


Lesenswert?

Hallo,

ich bin's nochmal. Ich habe sowohl den ADC als auch die PWM Ausgänge zum 
laufen bekommen (Habe bei RN-Wissen was zu dem ADC gefunden). Ich habe 
aber noch 2 Probleme:

1. Ich muss mein ADC Ergebnis durch 4 Teilen, um auf einen maximalen 
wert von 255 zu kommen.

2. Ich kann immer nur einen Kanal der beiden PWM Timer verwenden. Damit 
meine ich, entweder OC1A oder OC1B. Beide gleichzeitig bekomme ich 
einfach nicht hin.

Währe sehr schön wenn ihr nochmal über meinen Code schauen könntet.
1
#define F_CPU 8000000UL //Interner Oszilator mit 8MHz
2
3
#include <avr/io.h>
4
#include <inttypes.h>
5
6
7
uint16_t readADC(uint8_t channel) {
8
  uint16_t ergebnis = 0;
9
  uint8_t i;
10
  
11
  //ADC aktivieren und Prescaler einstellen (64)
12
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
13
  
14
  //Multiplexer Kanal auswählen und Referenzspannung auswählen
15
  ADMUX |= channel | (0 << REFS1) | (0 << REFS0);
16
  
17
  //ADC initialisieren und Dummyreadout machen
18
  ADCSRA |= (1 << ADSC);
19
  while (ADCSRA & (1 << ADSC));
20
  
21
  //3x Spannung auslesen und Mittelwert bilden
22
  for (i=0; i<3; i++){
23
    //Wandlung durchführen und auf Ergebnis warten
24
    ADCSRA |= (1 << ADSC);
25
    while (ADCSRA & (1 << ADSC));
26
    
27
    ergebnis += ADCW;
28
  }
29
  
30
  //ADC deaktivieren
31
  ADCSRA &= ~(1 << ADEN);
32
  
33
  ergebnis /= 3;
34
  
35
  return ergebnis;
36
}
37
38
void pwm_init(){
39
  
40
  //Ausgänge setzen
41
  DDRA |= (1 << PA6) | (1 << PA7) | (1 << PA5);
42
  DDRB |= (1 << PB2);
43
  
44
  //Timer 0 (8 Bit)
45
  //Löschen von Bits: OC0A/OC0B Bit 7 + 6
46
  //Art der Wellenform erzeugung: PWM, Phase Correct
47
  TCCR0A |= (1 << COM0A1) | 
48
        (1 << COM0B0) |  
49
        (0 << WGM02)  | 
50
        (0 << WGM01)  | 
51
        (1 << WGM00);
52
  
53
  //Prescaler auf 256 einstellen     
54
  TCCR0B |= (1 << CS02) | 
55
        (0 << CS01) | 
56
        (0 << CS00);
57
  
58
  //Timer 1 (16 Bit)
59
  //Löschen von Bits: OC0A/OC0B Bit 7 + 6
60
  //Art der Wellenform erzeugung: PWM, Phase Correct
61
  
62
  TCCR1A |= (1<<COM1A1) | 
63
        (1<<COM1B1) | 
64
        (0<<WGM02)  | 
65
        (0<<WGM01)  |   
66
        (1<<WGM00);
67
  
68
  //Prescaler auf 256 einstellen
69
  TCCR1B |= (1<<CS02) | 
70
        (0<<CS01) | 
71
        (0<<CS00);
72
}
73
74
int main(void)
75
{    
76
  pwm_init();
77
      
78
    while (1) 
79
    {  
80
    //ADC-Ergebnisse an PWM ausgeben  
81
    OCR1A = readADC(0) / 4;
82
    OCR0B = readADC(1) / 4;
83
    OCR0A = readADC(2) / 4;
84
    OCR1B = readADC(3) / 4;
85
  }
86
}

von S. Landolt (Gast)


Lesenswert?

> ADMUX |= channel | (0 << REFS1) | (0 << REFS0);
Das alte Missverständnis, wieder verodert.

Und es ist pures Glück, dass WGM0_ und WGM1_ bzw. CS0_ und CS1_ dieselbe 
Wertigkeit haben.

von Stefan E. (sternst)


Lesenswert?

S. Landolt schrieb:
> Und es ist pures Glück, dass WGM0_ und WGM1_ bzw. CS0_ und CS1_ dieselbe
> Wertigkeit haben.

Und dass WGMx2 Null sein soll und es daher nicht stört, dass es im 
falschen Register nicht gesetzt wird.

von S. Landolt (Gast)


Lesenswert?

meinereiner schrieb
> Das alte Missverständnis
Pardon, das war wohl irgendwo anders.
Also, mit
> ADMUX |= channel | (0 << REFS1) | (0 << REFS0);
"sammeln" sich die Kanäle in ADMUX an, nach
> OCR1B = readADC(3) / 4;
ist und bleibt der Kanal auf 3 stehen.

von Felix (Gast)


Lesenswert?

Hallo,

ich habe jetzt eine Lösung gefunden. Ich stelle den funktionierenden 
Code noch mal hier rein, falls es jemanden interessiert oder den 
gleichen Fehler hat. Danke an alle, die mir geholfen haben!

Gruß Felix
1
#define F_CPU 8000000UL //Interner Oszilator mit 8MHz
2
3
#include <avr/io.h>
4
#include <inttypes.h>
5
6
7
uint16_t readADC(uint8_t channel) {
8
  uint16_t ergebnis = 0;
9
  uint8_t i;
10
  
11
  //ADC aktivieren und Prescaler einstellen (64)
12
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
13
  
14
  //Multiplexer Kanal auswählen und Referenzspannung auswählen
15
  ADMUX = channel | (0 << REFS1) | (0 << REFS0);
16
  
17
  //ADC initialisieren und Dummyreadout machen
18
  ADCSRA |= (1 << ADSC);
19
  while (ADCSRA & (1 << ADSC));
20
  
21
  //3x Spannung auslesen und Mittelwert bilden
22
  for (i=0; i<3; i++){
23
    //Wandlung durchführen und auf Ergebnis warten
24
    ADCSRA |= (1 << ADSC);
25
    while (ADCSRA & (1 << ADSC));
26
    
27
    ergebnis += ADCW;
28
  }
29
  
30
  //ADC deaktivieren
31
  ADCSRA &= ~(1 << ADEN);
32
  
33
  ergebnis /= 3;
34
  
35
  return ergebnis;
36
}
37
38
void pwm_init(){
39
  
40
  //Ausgänge setzen
41
  DDRA |= (1 << PA6) | (1 << PA7) | (1 << PA5);
42
  DDRB |= (1 << PB2);
43
  
44
  //Inerups für Timer setzen
45
  //TIMSK0 = (1 << TOIE0);
46
  //TIMSK1 = (1 << TOIE0);
47
  
48
  //Timer 0 (8 Bit)
49
  //Löschen von Bits: OC0A/OC0B Bit 7 + 6
50
  //Art der Wellenform erzeugung: PWM, Phase Correct
51
  TCCR0A |= (0 << COM0A1) | 
52
        (0 << COM0A0) |
53
        (0 << COM0B1) |
54
        (0 << COM0B0) |
55
        (0 << WGM02)  | 
56
        (0 << WGM01)  | 
57
        (1 << WGM00);
58
  
59
  //Prescaler auf 256 einstellen     
60
  TCCR0B |= (0 << WGM02)|
61
        (0 << FOC0A)|
62
        (0 << FOC0B)|
63
        (0 << CS02) | 
64
        (0 << CS01) | 
65
        (1 << CS00);
66
  
67
  //Timer 1 (16 Bit)
68
  //Löschen von Bits: OC0A/OC0B Bit 7 + 6
69
  //Art der Wellenform erzeugung: PWM, Phase Correct
70
  TCCR1A |= (0 << COM1A1) | 
71
        (0 << COM1A0) |
72
        (0 << COM1B1) |
73
        (0 << COM1B0) |
74
        (0 << WGM12)  | 
75
        (0 << WGM11)  |   
76
        (1 << WGM10);
77
  
78
  //Prescaler auf 256 einstellen
79
  TCCR1B |= (0 << WGM12)|
80
        (0 << FOC1A)|
81
        (0 << FOC1B)|
82
        (0 << CS12) | 
83
        (0 << CS11) | 
84
        (1 << CS10);
85
}
86
87
void pwm_OC0A(int adc){
88
  TCCR0A &= ~(1 << COM0B1);
89
  TCCR0A |= (1 << COM0A1);
90
  
91
  OCR0A = adc;
92
}
93
94
void pwm_OC0B(int adc){
95
  TCCR0A &= ~(1 << COM0A1);
96
  TCCR0A |= (1 << COM0B1);
97
  
98
  OCR0B = adc;
99
}
100
101
void pwm_OC1A(int adc){
102
  TCCR1A &= ~(1 << COM1B1);
103
  TCCR1A |= (1 << COM1A1);
104
  
105
  OCR1A = adc;
106
}
107
108
void pwm_OC1B(int adc){
109
  TCCR1A &= ~ (1 << COM1A1);
110
  TCCR1A |= (1 << COM1B1);
111
  
112
  OCR1B = adc;
113
}
114
115
int main(void)
116
{    
117
  pwm_init();
118
      
119
    while (1) 
120
    {  
121
    //ADC-Ergebnisse an PWM ausgeben  
122
    pwm_OC0A(readADC(2) / 4);//
123
    pwm_OC0B(readADC(1) / 4);//
124
    pwm_OC1A(readADC(0) / 4);//
125
    pwm_OC1B(readADC(3) / 4);//
126
  }
127
}

von S. Landolt (Gast)


Lesenswert?

Wie Stefan Ernst bereits schrieb, steht WGM12 nicht in TCCR1A, auch wenn 
es, da 0, diesmal keinen Fehler verursacht.
  Unklar ist mir, weshalb die PWM-Kanäle ständig aus- und wieder 
eingeschaltet werden.

von C tut weh (Gast)


Lesenswert?

S. Landolt schrieb:
> meinereiner schrieb
>> Das alte Missverständnis
> Pardon, das war wohl irgendwo anders.

Ach?!

> Also, mit
>> ADMUX |= channel | (0 << REFS1) | (0 << REFS0);
> "sammeln" sich die Kanäle in ADMUX an, nach
>> OCR1B = readADC(3) / 4;
> ist und bleibt der Kanal auf 3 stehen.

Das sieht nicht so aus...

S. Landolt schrieb:
> Unklar ist mir, weshalb die PWM-Kanäle ständig aus- und wieder
> eingeschaltet werden.

Vielleicht deshalb:

Felix schrieb:
> ich möchte mit 4 Potis 4 LEDs über PWM dimmen.

Wolltest Du nicht längst nach Diktat verreist sein?

S. Landolt schrieb:
> Aber nach Argumentation und Wortspielen den Autor ahnend, möchte ich
> mich an dieser Stelle verabschieden. Einen schönen Abend allerseits!

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.