Hallo! Ich habe mir letzens ein myavr Board geholt und muss damit nun einen PID Regler aufbauen. Ich kenne mich in C Sprache einigermaßen aus weswegen ich das auch direkt in C Programmieren wollte. Ich habe auch einige Beiträge in dem Forum gelesen und einige Quellcodes für einen PID Regler gefunden. Da ich aber trotz allem ein ziemlicher Anfänger in Sachen µC bin, hat es natürlich nicht geklappt...leider finde ich den Fehler nicht. Die Ausgabe der PWM an meinem Port (PORTB2) gibt immer nur einen Maximalwert aus. Ich habe ein myAVR Board MK2 mit USB Anschluss und verwende einen Atmel Mega8 Controller. Hier mein Quellcode:
1 | #define F_CPU 3686400
|
2 | #include <avr\io.h> |
3 | |
4 | |
5 | uint16_t ReadChannel(uint8_t mux_adc_channel); |
6 | |
7 | unsigned int PID_Berechnung (signed int x, signed int w); |
8 | |
9 | int main(void) |
10 | {
|
11 | TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1); // 10Bit-PWM-Modus (Auflösung=1024!) |
12 | //Nicht Invertierend
|
13 | TCCR1B = (1<<CS10); // Aktivieren mit Prescaler 1, also keine Frequenz-'Teilung' |
14 | DDRB |= (1<<DDB1); |
15 | while(1){ |
16 | |
17 | uint16_t adc_value; |
18 | adc_value = ReadChannel(1); |
19 | OCR1A = PID_Berechnung(adc_value, 22); |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | }
|
27 | return 0; |
28 | }
|
29 | |
30 | uint16_t ReadChannel(uint8_t mux_adc_channel) |
31 | {
|
32 | uint8_t i; |
33 | uint16_t result = 0; |
34 | |
35 | ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // Frequenzvorteiler auf 32 setzen und ADC aktivieren |
36 | |
37 | ADMUX = mux_adc_channel; |
38 | ADMUX |= (1<<REFS1) | (1<<REFS0); |
39 | |
40 | ADCSRA |= (1<<ADSC); |
41 | while ( ADCSRA & (1<<ADSC) ) { |
42 | ;
|
43 | }
|
44 | |
45 | |
46 | for(i=0;i<4;i++) |
47 | {
|
48 | ADCSRA |= (1<<ADSC); |
49 | while ( ADCSRA & (1<<ADSC) ) { |
50 | ; } |
51 | result += ADCW; |
52 | }
|
53 | ADCSRA &= ~(1<<ADEN); |
54 | |
55 | result /= 4; |
56 | return result; |
57 | }
|
58 | |
59 | |
60 | unsigned int PID_Berechnung (signed int x, signed int w) |
61 | {
|
62 | |
63 | double Kp; |
64 | double I; |
65 | double Ta; |
66 | double D; |
67 | unsigned int prop; |
68 | unsigned int integ; |
69 | unsigned int diff; |
70 | unsigned int ealt; |
71 | unsigned int esum; |
72 | unsigned int e; |
73 | unsigned int y; |
74 | |
75 | Kp = 0.3; |
76 | I = 0.1; |
77 | D= 0.05; |
78 | Ta = 0.3; |
79 | |
80 | e = w - x; |
81 | if ((integ <= 1023)&&(integ >= 0)) |
82 | {
|
83 | esum+=e; } |
84 | |
85 | prop = (Kp*e); // Proportional Faktor |
86 | integ = (I*Ta*esum); // Integraler Anteil |
87 | diff = (D*((e-ealt))/Ta); // Differenzieller Anteil |
88 | ealt = e; // Regelabweichung für nächste Abtastung merken |
89 | y = prop + integ + diff; // Ausgangsstellgröße |
90 | |
91 | if (y > 1023) // Stellgröße auf 0..1023 begrenzen(10 bitPWM) |
92 | {
|
93 | y = 1023; |
94 | }
|
95 | if (y < 1) |
96 | {
|
97 | y = 0; |
98 | }
|
99 | return y; // unsigned int weil y nur zwischen 0 und 1023 |
100 | }
|
Für Hilfe danke ich im Voraus! Im myAVR Forum hat mir bislang keiner Helfen können...