Hallo,
Ich habe einen einfachen Buck-Converter aufgebaut welchen ich über einen
ATmega32 regeln möchte.
An den Pins PD0 und PD1 hängen (über Treiber) die Mosfets.
(Der Treiber schaltet bei Low-Pegel die Leistungs-Mosfets ein).
Die Eingangsspannung beträgt 12V und Uout ist 5V.
Zur Ansteuerung (später soll ein PI-Regler im Mikrocontroller
implementiert werden) verwende ich eine PWM mit (derzeit) 5KHz.
Gerne würde ich die Frequenz erhöhen, aber so ganz will das nicht
klappen.
Der mega32 läuft mit externem 16MHz Quarz.
Hier der Code:
1 | #include "main.h"
|
2 |
|
3 | volatile uint8_t state = 0; // state = 0: tg_on, bg_off state = 1: tg_off and bg_off state = 2: tg_off and bg_on state = 3: tg_off and bg_off
|
4 |
|
5 | void bg_on()
|
6 | {
|
7 | PORTD &= ~(1 << PD1); // BG MOSFET is on, if PD1 is low
|
8 | }
|
9 |
|
10 | void bg_off()
|
11 | {
|
12 | PORTD |= (1 << PD1); // BG MOSFET is off, if PD1 is high
|
13 | }
|
14 |
|
15 | void tg_on()
|
16 | {
|
17 | PORTD &= ~(1 << PD0); // TG MOSFET is on, if PD0 is low
|
18 | }
|
19 |
|
20 | void tg_off()
|
21 | {
|
22 | PORTD |= (1 << PD0); // TG MOSFET is off, if PD1 is high
|
23 | }
|
24 |
|
25 | void init_timer()
|
26 | {
|
27 | OCR1A = COUNTER1_TOP; // counter goes from 0 to COUNTER1_TOP
|
28 |
|
29 | TCCR1B |= (1 << WGM12); // CTC, TOP = OCR1A
|
30 | TCCR1B |= (1 << CS10); // CLK / 1
|
31 |
|
32 | TIMSK |= (1 << OCIE1A); // enable interrupt on compare match
|
33 | }
|
34 |
|
35 | int main (void)
|
36 | {
|
37 | DDRD |= (1 << PD0) | (1 << PD1); // PD0 and PD1 as outputs
|
38 | DDRC = 0xFF; // whole PORTC as output
|
39 | DDRB = 0xFF; // whole PORTB as output
|
40 |
|
41 | bg_off();
|
42 | tg_off();
|
43 |
|
44 | init_timer();
|
45 | sei(); // enable interrupts globally
|
46 |
|
47 | while(1)
|
48 | {
|
49 | }
|
50 | }
|
51 |
|
52 | ISR(TIMER1_COMPA_vect)
|
53 | {
|
54 | switch(state)
|
55 | {
|
56 | case 0:
|
57 | // set outputs
|
58 | tg_on();
|
59 | bg_off();
|
60 |
|
61 | // next state
|
62 | state = 1;
|
63 |
|
64 | // next delay
|
65 | OCR1A = ON_STEPS;
|
66 |
|
67 | // reset counter
|
68 | TCNT1 = 0;
|
69 | break;
|
70 |
|
71 | case 1:
|
72 | // set outputs
|
73 | tg_off();
|
74 | bg_off();
|
75 |
|
76 | // next state
|
77 | state = 2;
|
78 |
|
79 | // next delay
|
80 | OCR1A = TOT_STEPS;
|
81 |
|
82 | // reset counter
|
83 | TCNT1 = 0;
|
84 | break;
|
85 |
|
86 | case 2:
|
87 | // set outputs
|
88 | tg_off();
|
89 | bg_on();
|
90 |
|
91 | // next state
|
92 | state = 3;
|
93 |
|
94 | // next delay
|
95 | OCR1A = COUNTER1_TOP - ON_STEPS - (2 * TOT_STEPS);
|
96 |
|
97 | // reset counter
|
98 | TCNT1 = 0;
|
99 | break;
|
100 |
|
101 | case 3:
|
102 | // set outputs
|
103 | tg_off();
|
104 | bg_off();
|
105 |
|
106 | // next state
|
107 | state = 0;
|
108 |
|
109 | // next delay
|
110 | OCR1A = TOT_STEPS;
|
111 |
|
112 | // reset counter
|
113 | TCNT1 = 0;
|
114 | break;
|
115 | }
|
116 | }
|
Und dazu noch die .h Datei:
1 | #include <avr/io.h>
|
2 | #include <stdint.h>
|
3 | #include <avr/interrupt.h>
|
4 | #include <inttypes.h>
|
5 |
|
6 | #define F_CPU 16000000
|
7 | #define F_PWM 5000
|
8 |
|
9 | #define U_IN 12
|
10 | #define U_OUT 5
|
11 |
|
12 | #define U_REF ((U_OUT * R_2) / (R_1 + R_2)) // 1.8243 V
|
13 |
|
14 | #define COUNTER1_TOP (F_CPU / F_PWM) // 3200
|
15 | #define ON_STEPS ((COUNTER1_TOP * U_OUT) / U_IN) // 1333
|
16 | #define TOT_STEPS 90 // => t_tot =
|
17 |
|
18 | void init_timer(void);
|
19 | void bg_on(void);
|
20 | void bg_off(void);
|
21 | void tg_on(void);
|
22 | void tg_off(void);
|
Meine Fragen:
1) Was kann ich besser machen?
2) Wie könnte ich auf eine höhere PWM Frequenz kommen? (sind 300KHz mit
16 MHz Takt zu schaffen?) Wenn nein, wie könnte ich auf wenigstens
~200KHz kommen?
3) Wie könnte ich am besten einen Regler einbauen? (PI-Regler)? Mit dem
ADC die Ausgangsspannung messen? (Hat der mega32 soviele Resourcen?)
Brauche ich für eine so hohe PWM-Frequenz (> 200KHz) einen schnelleren
Mikrocontroller?
Über ein paar Tipps würde ich mich sehr freuen!
Gruß
Doran