Forum: Mikrocontroller und Digitale Elektronik PWM Frequenz ATMega328P einstellen


von basti (Gast)


Lesenswert?

Hallo Leute,

hab eine Frage zur Einstellung der PWM-Frequenz beim ATMega328P. Ich 
will mit dem 16 und 8 Bit Timer zwei PWM Signale ausgeben. Beim 16 Bit 
Timer passt die Frequenz, die ich einstellen wollte.
1
TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1); //Fast PWM Mode with Top value 0x03FF = 1023 (10-Bit) and non-inverting Mode; OC1A
2
  TCCR1B = (1<<WGM12) | (1<<CS10); //TCCR1B no Prescaling: 8000000Hz/1024 = 7,8kHz (for LTSPice T(period)= 0.000128) with CPU frequency 8MHz

Da kommen ca 7,8kHz raus. Beim 8 Bit Timer kommt eine sehr viel 
niedrigere Frequenz, irgendwas um die 150Hz raus. Ich brauche aber ein 
Signal im kHz Bereich. Laut Datenblatt sollte sich die Frequenz beim 
Fast PWM Mode so berechnen:

fpwm = fclk/256 (ohne Prescaler)

also sollte eine Frequenz von ca. 31kHz herauskommen.
1
  TCCR0A = (1<<WGM00) | (1<<WGM01) | (1<<COM0A1); //Fast PWM Mode with Top value 0xFF = 255 (8-bit) and non-inverting Mode; OC0A
2
  TCCR0B = (1<<CS00) ; //TCCR0b ca. 31kHz

Kann mir jemand weiterhelfen, was da falsch ist. Bin noch Neuling und 
noch nicht so vertraut mit der ganzen Materie...

von M. K. (sylaina)


Lesenswert?

Bitte kompletten Code zeigen, der das Problem demonstriert.

von basti (Gast)


Lesenswert?

1
#define F_CPU 8000000UL     // 8MHz important: set right fuse bits
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h> //for testing
6
7
8
uint16_t ADC_Read( uint8_t channel )
9
{
10
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
11
  ADCSRA |= (1<<ADSC);            // conversion
12
  while (ADCSRA & (1<<ADSC) ) {   // wait until conversion is ready
13
  }
14
  return ADCW;                    // return ADC
15
}
16
17
18
int main()
19
{
20
21
  //Timer 0 PWM Register for DAC conversion
22
  TCCR0A = (1<<WGM00) | (1<<WGM01) | (1<<COM0A1); //Fast PWM Mode with Top value 0xFF = 255 (8-bit) and non-inverting Mode; OC0A
23
  TCCR0B = (1<<CS00) ; //TCCR0b ca. 31kHz
24
25
  //Timer 1 PWM Register for DAC conversion with filtering circuit
26
  TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1); //Fast PWM Mode with Top value 0x03FF = 1023 (10-Bit) and non-inverting Mode; OC1A
27
  TCCR1B = (1<<WGM12) | (1<<CS10); //TCCR1B no Prescaling: 8000000Hz/1024 = 7,8kHz (for LTSPice T(period)= 0.000128) with CPU frequency 8MHz
28
29
  //ADC Setup
30
  ADMUX = (1<<REFS0) | (1<<MUX0); //AVCC(5V) as reference and MUX = ADC1
31
  ADCSRA = (1<<ADEN) | (1<<ADSC) |(1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
32
33
  sei();
34
35
  DDRD = 0xFF;
36
  PORTD = 0x00;
37
  DDRC = 0x00;
38
  PORTC = 0x00;
39
  DDRD |= (1<<PD6); //PWM Output
40
  DDRB |= (1<<PB0); //green LED
41
  DDRB |= (1<<PB1); //PWM Output
42
  
43
  uint16_t Min1 = 122;
44
  uint16_t Min2 = 982;
45
  uint16_t Max1 = 982;
46
  uint16_t Max2 = 122;
47
48
   while(1)
49
  {
50
    uint16_t Hall1 = ADC_Read(1); //read Hall1 Signal
51
    uint16_t pwm1 = (((uint32_t)(Hall1-Min1)*1023)/(Max1-Min1)); //change of value range
52
    OCR1A = pwm1; //set duty cycle
53
54
55
    uint8_t Hall2 = ADC_Read(0); //read Hall2 Signal
56
    uint8_t pwm2 = (((uint32_t)(Hall2-Max2)*255)/(Min2-Max2)); //change of value range
57
    OCR0A = pwm2;
58
59
  }
60
}

von basti (Gast)


Lesenswert?

Und noch eine Frage. Könnte man anstatt zwei Timer zu nutzen, nur mit 
einem Timer zwei unterschiedliche PMW Signale generieren. Also gleiche 
Einstellungen, gleiche Frequenz usw., aber unterschiedliche Tastgrade?

Weil dann würde ich den 16-Bit Timer nutzen um beide PWM Signale 
auszugeben.

von Eberhard H. (sepic) Benutzerseite


Lesenswert?

basti schrieb:
> Und noch eine Frage. Könnte man anstatt zwei Timer zu nutzen, nur mit
> einem Timer zwei unterschiedliche PMW Signale generieren. Also gleiche
> Einstellungen, gleiche Frequenz usw., aber unterschiedliche Tastgrade?

Natürlich geht das und zwar mit OC1A (PORTB,1) und OC1B (PORTB,2) als 
PWM-Ausgänge.

Hier ein LED-Crossfader, einmal mit gleicher Phasenlage beider 
PWM-Kanäle: 
http://www.led-treiber.de/html/software-fader.html#Cross-Fader

Und dann noch 180° phasenverschoben: 
http://www.led-treiber.de/html/software-fader.html#Phase

Allerdings ist das nicht in C, sondern in (strukturiertem) AVR-Assembler 
geschrieben.

von M. K. (sylaina)


Lesenswert?

basti schrieb:
> nd noch eine Frage. Könnte man anstatt zwei Timer zu nutzen, nur mit
> einem Timer zwei unterschiedliche PMW Signale generieren. Also gleiche
> Einstellungen, gleiche Frequenz usw., aber unterschiedliche Tastgrade?

Ja, das kann man. Der Atmega328P hat insgesamt 6 PWM Pins die alle 
unabhängige PWM-Tastgrade ermöglichen. Der 16 Bit Timer ermöglicht 
hierbei zwei unabhängige PWM-Signale.

Erstmal fällt mir kein signifikanter Fehler auf bis auf die Tatsache, 
dass, rein mathematisch, deine PWM-Werte, je nach ADC-Wert, außerhalb 
des zulässigen Bereiches laufen können (beide können negativ werden, der 
Wert für Timer0 kann auch größer 255 werden). Das hast du nicht 
abgefangen, würde ich an deiner Stelle aber damit immer ein definiertes 
Verhalten entsteht ;)

Desweiteren könnte man mal prüfen was der Compiler optimiert.
1
(uint32_t)(Hall2-Max2)*255)/(Min2-Max2)

Kann man auch schreiben als
1
(uint32_t)(Hall2-Max2)*(255/(Min2-Max2))

Und wenn der Compiler das erkennt sieht er dass
1
(255/(Min2-Max2)

als Integer-Operation in deinem Fall 0 sein wird da Min2-Max2 > 255 ist. 
Schreibe statt 255 einfach 255.0, hierbei zwingst du das System zur 
einer Floatoperation und da der Atmega328P einen Hardwaremultiplizierer 
hat ist das auch kein Beinbruch, ich denke zumindest mal, dass du keine 
Timingprobleme hast.

von basti (Gast)


Lesenswert?

Ahhhh jetz hab ichs kapiert, also mit 16-Bit funktionierts jetzt 
einwandfrei. Komischerweise funktioniert es mit dem 8-Bit Timer nicht. 
Meiner Meinung nach müsste der allerdings korrekt eingestellt sein...

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.