Ich möchte über Poti eine PWM (Tastgrad zwischen 0-100%) steuern. Macht
aber nicht! Ich habe mal meinen Code gepostet.
Ich benutze Fast Pwm Modus. Den Poti habe ich in Reihe mit eine 1k
Widerstand geschaltet. Das Problem liegt bei der ADC Wandlung. Das
Tastverhältnis ändert sich gar nicht, wenn ich den Poti drehe.
1
/*
2
* GccLibrary1.c
3
*
4
* Created: 30.11.2014 17:31:17
5
* Author: **** *****
6
* Tiefsetzsteller
7
*/
8
9
#include<avr/io.h>
10
#include<inttypes.h>
11
12
#define F_CPU 8000000UL
13
14
uint16_treadADC(doublex){
15
uint8_ti;
16
uint16_tresult=0;
17
18
// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
19
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
20
21
// VCC als Referenzspannung verwenden (also VCC=5V)
22
// ADC8, PB5
23
ADMUX=(1<<MUX3);
24
25
// Den ADC initialisieren und einen sog. Dummyreadout machen
26
ADCSRA|=(1<<ADSC);
27
while(ADCSRA&(1<<ADSC));
28
29
// Jetzt 3x die analoge Spannung and Kanal channel auslesen
30
// und dann Durchschnittswert ausrechnen.
31
for(i=0;i<3;i++){
32
// Eine Wandlung
33
ADCSRA|=(1<<ADSC);
34
// Auf Ergebnis warten...
35
while(ADCSRA&(1<<ADSC));
36
37
result+=ADCW;
38
}
39
40
// ADC wieder deaktivieren
41
ADCSRA&=~(1<<ADEN);
42
43
result/=3;
44
45
result=x*(double)result;
46
returnresult;
47
}
48
49
//Timer 1 (PWM) initialisieren
50
voidtimer1_pwm(uint16_tresult){
51
PORTB=0;
52
DDRB=(1<<PB0);
53
OCR1A=0;
54
55
//Timer1 Konfigurieren
56
TCCR1A=(1<<COM1A1)|(1<<PWM1A);//PWM, OC1A
57
TCCR1B=(1<<CS10);//F_CPU ohne Prescaler
58
TCCR1D=(0<<WGM11)|(0<<WGM10);//Fast PWM
59
OCR1A=444-result;//default
60
61
//TOP Setzen, 18kHz
62
TC1H=444>>8;
63
OCR1C=444&0xFF;
64
}
65
66
intmain(void)
67
{
68
doublex=0.867;
69
70
//uint16_t readADC(); //Auslesen der analogen Spannungen an PB5,
hari schrieb:> Den Poti habe ich in Reihe mit eine 1k> Widerstand geschaltet.
Welchen Sinn soll das haben?
Warum initialisierst du alles jedes mal wieder neu?
ADC und Timer werden einmal initialisiert und im Programmlauf wird nur
noch das OCR-Register entsprechend dem ADC-Wert aktualisert.
mfg.
Bei der derzeitigen Beschaltung wirst du übrigens nicht über VCC/2 am
ADC Eingang hinauskommen. Entweder ersetzt du den 1k Widerstand durch
eine Brücke oder benutzt die interne 2,56V Referenz des Tiny.
Thomas Eckmann schrieb:> hari schrieb:>> Den Poti habe ich in Reihe mit eine 1k>> Widerstand geschaltet.>> Welchen Sinn soll das haben?>> Warum initialisierst du alles jedes mal wieder neu?>> ADC und Timer werden einmal initialisiert und im Programmlauf wird nur> noch das OCR-Register entsprechend dem ADC-Wert aktualisert.>> mfg.
Ich habe den Code nochmal verändert. Das Problem ist, Tastverhältnis
bleibt immer gleich. Irgendwas stimmt mit der ADC Wandlung nicht. Ich
drehe den Poti aber alles bleibt gleich. Ich kann die Signale
Oszilloskopieren.
1
/*
2
* GccLibrary1.c
3
*
4
* Created: 30.11.2014 17:31:17
5
* Author: **** *****
6
* Tiefsetzsteller
7
*/
8
9
#include<avr/io.h>
10
#include<inttypes.h>
11
12
#define F_CPU 8000000UL
13
14
uint16_treadADC(doublex){
15
uint8_ti;
16
uint16_tresult=0;
17
18
// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
19
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
20
21
// VCC als Referenzspannung verwenden (also VCC=5V)
22
// ADC8, PB5
23
ADMUX=(1<<MUX3);
24
25
// Den ADC initialisieren und einen sog. Dummyreadout machen
26
ADCSRA|=(1<<ADSC);
27
while(ADCSRA&(1<<ADSC));
28
29
// Jetzt 3x die analoge Spannung and Kanal channel auslesen
30
// und dann Durchschnittswert ausrechnen.
31
for(i=0;i<3;i++){
32
// Eine Wandlung
33
ADCSRA|=(1<<ADSC);
34
// Auf Ergebnis warten...
35
while(ADCSRA&(1<<ADSC));
36
37
result+=ADCW;
38
}
39
40
// ADC wieder deaktivieren
41
ADCSRA&=~(1<<ADEN);
42
43
result/=3;
44
45
result=x*(double)result;
46
returnresult;
47
}
48
49
intmain(void)
50
{
51
PORTB=0;
52
DDRB=(1<<PB1);
53
54
//Timer1 Konfigurieren
55
TCCR1A=(1<<COM1A1)|(1<<PWM1A);//PWM, OC1A
56
TCCR1B=(1<<CS10);//F_CPU ohne Prescaler
57
TCCR1D=(0<<WGM11)|(0<<WGM10);//Fast PWM
58
OCR1A=0;//default
59
60
//TOP Setzen, 18kHz
61
TC1H=444>>8;
62
OCR1C=444&0xFF;
63
64
doublex=0.867;
65
66
//uint16_t readADC(); //Auslesen der analogen Spannungen an PB5,
Thomas Eckmann schrieb:> hari schrieb:>> Den Poti habe ich in Reihe mit eine 1k>> Widerstand geschaltet.>> Welchen Sinn soll das haben?>> Warum initialisierst du alles jedes mal wieder neu?>> ADC und Timer werden einmal initialisiert und im Programmlauf wird nur> noch das OCR-Register entsprechend dem ADC-Wert aktualisert.>> mfg.
Nur beim Einschalten nimmt er den ADC Wert von Poti und danach nicht
mehr!
Axel Z. schrieb:> Nimm mal das return 0 aus der while-Schleife heraus. Dann hat das> Programm wenigstens die Chance mehr als einmal zu laufen.>> Gruß
Das habe ich übersehen. Funktioniert jetzt.
Ich möchte ein PWM Signal (Fast PWM, 10bit) erzeugen. PWM Frequenz soll
ca. 18Khz betragen. Das Problem ist, dass nur ca. 2,5khz signal erzeugt
wird. Wo mache ich fehler?
Mein (Teil)Code:
1
#include<avr/io.h>
2
#include<inttypes.h>
3
4
#define F_CPU 8000000UL
5
6
uint16_treadADC(doublex){
7
blabla
8
}
9
10
intmain(void)
11
{
12
PORTB=0;
13
DDRB=(1<<PB1);
14
15
//Timer1 Konfigurieren
16
TCCR1A=(1<<COM1A1)|(1<<PWM1A);//PWM, OC1A
17
TCCR1B=(1<<CS10);//F_CPU ohne Prescaler
18
TCCR1D=(0<<WGM11)|(0<<WGM10);//Fast PWM
19
20
OCR1A=0;//default
21
22
//TOP Setzen, 18kHz
23
TC1H=444>>8;
24
OCR1C=444&0xFF;
25
26
doublex=0.4333;
27
28
//uint16_t readADC(); //Auslesen der analogen Spannungen an PB5,
ariba schrieb:> #define F_CPU 8000000UL
Das ist nicht zum Einstellen des Prozessortaktes, sondern dient nur dazu
dass dein Programm weiss wie schnell dein Prozessor tatsächlich taktet.
Die tatsächliche Taktfrequenz musst du entsprechend konfigurieren
(Fuses) bzw. über einen Quarz oder externen Oszillator festlegen.
Maik S. schrieb:> Stimmen alle Bezeichnungen oder hast du den Teil für die PWM> Erzuegung> kopiert, von einem "älteren" Attiny / Mega ?
Ich habe nichts kopiert. Ich habe anhand Datenblatt konfiguriert.
ariba schrieb:> Maik S. schrieb:>> Stimmen alle Bezeichnungen oder hast du den Teil für die PWM>> Erzuegung>> kopiert, von einem "älteren" Attiny / Mega ?>> Ich habe nichts kopiert. Ich habe anhand Datenblatt konfiguriert.
Wo liegt der Fehler?
Ingo schrieb:> CKDIV8 meinte ich
Er erzeugt aber jetzt ca. 15khz. Theoretisch sollte 18khz raus kommen.
Ist soviel abweichung normal?
fpwm=1/((1/8mhz)*444)
Ich hatte mal ein Problem, dass die Bezeichnungen anders hießen bei den
"neueren" Tinys. Hab mich anhand von Tutorials totgesucht.
Scheint hier aber zu passen.
TC1H=readADC(x) >> 8;
OCR1A=readADC(x) & 0xFF;
TC1H ist IIRC 2 Bit groß
OCR1A ist IIRC 8 Bit groß
Ich verstehe nicht, was hier passieren soll.
Maik S. schrieb:> Ich hatte mal ein Problem, dass die Bezeichnungen anders hießen> bei den> "neueren" Tinys. Hab mich anhand von Tutorials totgesucht.>> Scheint hier aber zu passen.>> TC1H=readADC(x) >> 8;> OCR1A=readADC(x) & 0xFF;>> TC1H ist IIRC 2 Bit groß> OCR1A ist IIRC 8 Bit groß>> Ich verstehe nicht, was hier passieren soll.
Ich möchte ja 10bit Fast PWM programmieren. OCR1A ist 8 Bit groß. Die
anderen 2 bits liegen im Register TC1H. Wenn der Timer diesen Wert
erreich, soll den Pegel von 5V auf 0V setzen. So habe ich verstanden.
Der Timer zählt von 0 bis 444.
Eine eigene Frage?
Dieser Thread ist über 11 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.