1 | /***********************************************************************************************
|
2 | * MPPTAlgorithmus.c
|
3 | *
|
4 | * Used µC : ATmega32U4
|
5 | * Compiler : AVR Studio 6.1
|
6 | * Configuration : External oscillator with 16 MHz.
|
7 | **********************************************************************************************/
|
8 |
|
9 |
|
10 | /***********************************************************************************************
|
11 | ************************************* Adjusted Fuse-Bits ***************************************
|
12 | ***********************************************************************************************/
|
13 |
|
14 | /*
|
15 | Notice: [x] means programmed (enabled or 0), while [] means unprogrammed (diasabled or 1)!
|
16 |
|
17 | BODLEVEL [4V3]
|
18 | HWBE [x]
|
19 | OCDEN []
|
20 | JTAGEN [] ... need to be disabled because of the ADC pins
|
21 | SPIEN [x] ... never disable this fuse otherwise the µC becomes not programmable!!!
|
22 | WDTON []
|
23 | EESAVE []
|
24 | BOOTSZ [2048W_3800]
|
25 | BOOTRST []
|
26 | CKDIV8 [] ... [x] => clock prescaler = 8: [] => clock prescaler = 1.
|
27 | CKOUT []
|
28 | SUT_CKSEL [EXTXOSC_8MHz_XX_258CK_65MS]
|
29 |
|
30 | */
|
31 |
|
32 |
|
33 | /***********************************************************************************************
|
34 | **************************************** Header-files ******************************************
|
35 | ***********************************************************************************************/
|
36 |
|
37 | // <avr/io.h> integrates all the necessary PORT and register names.
|
38 | #include <avr/io.h>
|
39 | //<util/delay.h> Header file with summary of waiting functions.
|
40 | #include <util/delay.h>
|
41 | //<stdint.h> Integer types with predefined width such as uint8_t or int16_t.
|
42 | #include <stdint.h>
|
43 |
|
44 |
|
45 | /***********************************************************************************************
|
46 | ************************************ Variable Definition ***************************************
|
47 | ************************************ Global ***************************************
|
48 | ***********************************************************************************************/
|
49 |
|
50 |
|
51 | volatile int8_t duty_cycle = 127;
|
52 |
|
53 | /***********************************************************************************************
|
54 | ******************************** Declaration of functions ************************************
|
55 | ******************************** "Function head" ************************************
|
56 | ***********************************************************************************************/
|
57 |
|
58 | void ADC_Initialization(void);
|
59 |
|
60 | void Set_DutyCycle(uint8_t duty_cycle);
|
61 |
|
62 | uint32_t ADC_Read_Value(uint8_t pin_channel);
|
63 |
|
64 | uint32_t ADC_Read_AvarageValue(uint8_t pin_channel, uint8_t samples);
|
65 |
|
66 |
|
67 | /***********************************************************************************************
|
68 | **************************************** Main Routine ******************************************
|
69 | ***********************************************************************************************/
|
70 |
|
71 | int main(void)
|
72 | {
|
73 |
|
74 |
|
75 | int32_t u_in = 0;
|
76 | int32_t i_in = 0;
|
77 |
|
78 | int32_t u_in_previous = 0;
|
79 | int32_t i_in_previous = 0;
|
80 |
|
81 | int32_t delta_u_in = 0;
|
82 | int32_t delta_i_in = 0;
|
83 |
|
84 | // set Pin F4-7 as Input (ADC Input Channels).
|
85 | DDRF &= ~((1<<DDF4)|(1<<DDF5)|(1<<DDF6)|(1<<DDF7));
|
86 | // deactivate Pull-Up Resistor on Pin F4-7.
|
87 | PORTF &= ~((1<<PF4)|(1<<PF5)|(1<<PF6)|(1<<PF7));
|
88 |
|
89 | /***********************************************************************************************
|
90 | *************************************** Timer/Counter ******************************************
|
91 | *************************************** PWM-generator ******************************************
|
92 | ***********************************************************************************************/
|
93 |
|
94 | TCCR0A|=(1<<WGM01)|(1<<WGM00); // Setting fast-PWM mode.
|
95 | TCCR0A|=(1<<COM0A1); /* OC0A become low at a match and high at top.*/
|
96 |
|
97 |
|
98 | // PWM-frequency = timer clock/(Prescaler * 256)= 16 MHz/(1*256) = 62.5 kHz
|
99 | TCCR0B|=(1<<CS00); // Prescaler = 1. Datasheet Page 105.
|
100 | TCCR0B &=~(1<<WGM02); // TCNT0 run continuous after match until TOP reaches.
|
101 |
|
102 | Set_DutyCycle(duty_cycle); // Clock ratio/ trigger the PWM.
|
103 |
|
104 | DDRB|=(1<<PB7); // Set Pin P7 for OC0A as output.
|
105 |
|
106 | /***********************************************************************************************
|
107 | *************************************** Initialize ADC *****************************************
|
108 | ***********************************************************************************************/
|
109 |
|
110 | ADC_Initialization();
|
111 |
|
112 | /***********************************************************************************************
|
113 | ***************************************** While Loop *******************************************
|
114 | ************************************************************************************************/
|
115 |
|
116 | while(1)
|
117 | {
|
118 | _delay_ms(2);
|
119 |
|
120 | //Sampling the current and voltage values
|
121 | u_in = ADC_Read_AvarageValue(4,10);
|
122 | i_in = ADC_Read_AvarageValue(5,10);
|
123 |
|
124 | /***********************************************************************************************
|
125 | ********************************** Incremental Conductance ************************************
|
126 | ********************************** Algorithm ************************************
|
127 | ***********************************************************************************************/
|
128 |
|
129 | delta_u_in = u_in-u_in_previous;
|
130 | delta_i_in = i_in-i_in_previous;
|
131 |
|
132 | if(delta_u_in == 0 )
|
133 | {//Yes branch delta_u_in == 0
|
134 |
|
135 | if(delta_i_in == 0)
|
136 | {
|
137 | // Yes branch do nothing. MPP is found.
|
138 |
|
139 | }
|
140 | else // No branch delta_i_in == 0
|
141 | {
|
142 | if(delta_i_in > 0)
|
143 | {
|
144 | -- duty_cycle;
|
145 | }
|
146 | else
|
147 | {
|
148 | if(delta_i_in < 0)
|
149 | {
|
150 | ++ duty_cycle;
|
151 | }
|
152 | }
|
153 | }
|
154 | }
|
155 | else // No branch delta_u_in == 0
|
156 | {
|
157 | if((1000*delta_i_in)/delta_u_in == - (1000*i_in)/u_in)
|
158 | {
|
159 | // Yes branch do nothing. MPP is found.
|
160 | }
|
161 | else // No branch delta_i_in/delta_u_in == - i_in/u_in.
|
162 | {
|
163 | if((1000*delta_i_in)/delta_u_in > - (1000*i_in)/u_in)
|
164 | {
|
165 | -- duty_cycle;
|
166 | }
|
167 | else
|
168 | {
|
169 | if((1000*delta_i_in)/delta_u_in < - (1000*i_in)/u_in)
|
170 | {
|
171 | ++ duty_cycle;
|
172 | }
|
173 | }
|
174 | }
|
175 | }
|
176 |
|
177 | u_in_previous = u_in;
|
178 | i_in_previous = i_in;
|
179 |
|
180 |
|
181 | Set_DutyCycle(duty_cycle);
|
182 | }
|
183 | }
|
184 | /***********************************************************************************************
|
185 | ******************************* Definition of the functions ***********************************
|
186 | ******************************* "Functionbody" ***********************************
|
187 | ************************************************************************************************/
|
188 |
|
189 | void ADC_Initialization(void)
|
190 | {
|
191 | ADMUX|=(1<<REFS0); // Set reference voltage to AVcc.
|
192 |
|
193 | ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Set prescaler to 128.
|
194 | ADCSRA|=(1<<ADEN); // Activate converter.
|
195 | //AD conversion is started
|
196 | ADCSRA|=(1<<ADSC);
|
197 | while (ADCSRA & (1<<ADSC) ) // Wait for completion of the conversion.
|
198 | {
|
199 | }
|
200 | /* ADCW must be read once, otherwise the result of the next conversion is not
|
201 | taken. */
|
202 | (void) ADCW;
|
203 |
|
204 | }
|
205 |
|
206 | uint32_t ADC_Read_AvarageValue(uint8_t pin_channel, uint8_t samples)
|
207 | {
|
208 | uint32_t sum = 0;
|
209 |
|
210 | for (uint8_t i = 0; i < samples; ++i )
|
211 | {
|
212 | sum += ADC_Read_Value( pin_channel );
|
213 | }
|
214 |
|
215 | return ( sum / samples );
|
216 | }
|
217 |
|
218 | uint32_t ADC_Read_Value(uint8_t pin_channel)
|
219 | {
|
220 | ADMUX = (ADMUX & ~(0x1F)) | (pin_channel & 0x1F);
|
221 | ADCSRA |= (1<<ADSC); // one Conversion "single conversion"
|
222 | while (ADCSRA & (1<<ADSC) )
|
223 | { // Wait for completion of the conversion
|
224 | }
|
225 | return ADCW;
|
226 | }
|
227 |
|
228 | void Set_DutyCycle(uint8_t duty_cycle)
|
229 | {
|
230 | OCR0A = duty_cycle;
|
231 | }
|