Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1538 | killagreg | 1 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 | // + Copyright (c) Holger Buss, Ingo Busker |
||
3 | // + Nur für den privaten Gebrauch |
||
4 | // + www.MikroKopter.com |
||
5 | // + porting the sources to other systems or using the software on other systems (except hardware from www.mikrokopter.de) is not allowed |
||
6 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
7 | // + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation), |
||
8 | // + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist. |
||
9 | // + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt |
||
10 | // + bzgl. der Nutzungsbedingungen aufzunehmen. |
||
11 | // + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen, |
||
12 | // + Verkauf von Luftbildaufnahmen, usw. |
||
13 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
14 | // + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht, |
||
15 | // + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen |
||
16 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
17 | // + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts |
||
18 | // + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de" |
||
19 | // + eindeutig als Ursprung verlinkt werden |
||
20 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
21 | // + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion |
||
22 | // + Benutzung auf eigene Gefahr |
||
23 | // + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden |
||
24 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
25 | // + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur |
||
26 | // + mit unserer Zustimmung zulässig |
||
27 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
28 | // + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen |
||
29 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
30 | // + Redistributions of source code (with or without modifications) must retain the above copyright notice, |
||
31 | // + this list of conditions and the following disclaimer. |
||
32 | // + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived |
||
33 | // + from this software without specific prior written permission. |
||
34 | // + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet |
||
35 | // + for non-commercial use (directly or indirectly) |
||
36 | // + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted |
||
37 | // + with our written permission |
||
38 | // + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be |
||
39 | // + clearly linked as origin |
||
40 | // + * porting to systems other than hardware from www.mikrokopter.de is not allowed |
||
41 | // + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
42 | // + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
43 | // + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
44 | // + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
45 | // + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
46 | // + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
47 | // + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
48 | // + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
49 | // + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
50 | // + POSSIBILITY OF SUCH DAMAGE. |
||
51 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
52 | #include <stdlib.h> |
||
53 | #include <avr/io.h> |
||
54 | #include <avr/interrupt.h> |
||
55 | |||
56 | #include "analog.h" |
||
57 | #include "main.h" |
||
58 | #include "timer0.h" |
||
59 | #include "fc.h" |
||
60 | #include "printf_P.h" |
||
61 | #include "eeprom.h" |
||
62 | #include "twimaster.h" |
||
63 | #include "uart0.h" |
||
64 | |||
65 | volatile uint16_t Test = 0; |
||
66 | |||
67 | volatile int16_t UBat = 100; |
||
68 | volatile int16_t AdValueGyroNick = 0, AdValueGyroRoll = 0, AdValueGyroYaw = 0; |
||
69 | volatile int16_t FilterHiResGyroNick = 0, FilterHiResGyroRoll = 0; |
||
70 | volatile int16_t HiResGyroNick = 2500, HiResGyroRoll = 2500; |
||
71 | volatile int16_t AdValueAccRoll = 0, AdValueAccNick = 0, AdValueAccTop = 0, AdValueAccZ = 0; |
||
72 | volatile int32_t AirPressure = 32000; |
||
73 | volatile int32_t StartAirPressure; |
||
74 | volatile int16_t AdAirPressure = 1023; |
||
75 | volatile int32_t ReadingHeight = 0; |
||
76 | volatile int16_t ReadingVario = 0; |
||
77 | volatile int32_t SumHeight = 0; |
||
78 | volatile uint16_t MeasurementCounter = 0; |
||
79 | volatile uint8_t ADReady = 1; |
||
80 | |||
81 | uint8_t DacOffsetGyroNick = 115, DacOffsetGyroRoll = 115, DacOffsetGyroYaw = 115; |
||
82 | uint8_t GyroDefectNick = 0, GyroDefectRoll = 0, GyroDefectYaw = 0; |
||
83 | int8_t ExpandBaro = 0; |
||
84 | uint8_t PressureSensorOffset; |
||
85 | |||
86 | /*****************************************************/ |
||
87 | /* Initialize Analog Digital Converter */ |
||
88 | /*****************************************************/ |
||
89 | void ADC_Init(void) |
||
90 | { |
||
91 | uint8_t sreg = SREG; |
||
92 | // disable all interrupts before reconfiguration |
||
93 | cli(); |
||
94 | //ADC0 ... ADC7 is connected to PortA pin 0 ... 7 |
||
95 | DDRA = 0x00; |
||
96 | PORTA = 0x00; |
||
97 | // Digital Input Disable Register 0 |
||
98 | // Disable digital input buffer for analog adc_channel pins |
||
99 | DIDR0 = 0xFF; |
||
100 | // external reference, adjust data to the right |
||
101 | ADMUX &= ~((1 << REFS1)|(1 << REFS0)|(1 << ADLAR)); |
||
102 | // set muxer to ADC adc_channel 0 (0 to 7 is a valid choice) |
||
103 | ADMUX = (ADMUX & 0xE0) | 0x00; |
||
104 | //Set ADC Control and Status Register A |
||
105 | //Auto Trigger Enable, Prescaler Select Bits to Division Factor 128, i.e. ADC clock = SYSCKL/128 = 156.25 kHz |
||
106 | ADCSRA = (0<<ADEN)|(0<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(0<<ADIE); |
||
107 | //Set ADC Control and Status Register B |
||
108 | //Trigger Source to Free Running Mode |
||
109 | ADCSRB &= ~((1 << ADTS2)|(1 << ADTS1)|(1 << ADTS0)); |
||
110 | // Start AD conversion |
||
111 | ADC_Enable(); |
||
112 | // restore global interrupt flags |
||
113 | SREG = sreg; |
||
114 | } |
||
115 | |||
116 | void SearchAirPressureOffset(void) |
||
117 | { |
||
118 | uint8_t off; |
||
119 | off = GetParamByte(PID_PRESSURE_OFFSET); |
||
120 | if(off > 20) off -= 10; |
||
121 | OCR0A = off; |
||
122 | ExpandBaro = 0; |
||
123 | Delay_ms_Mess(100); |
||
124 | if(AdAirPressure < AIR_PRESSURE_SEARCH) off = 0; |
||
125 | for(; off < 250;off++) |
||
126 | { |
||
127 | OCR0A = off; |
||
128 | Delay_ms_Mess(50); |
||
129 | printf("."); |
||
130 | if(AdAirPressure < AIR_PRESSURE_SEARCH) break; |
||
131 | } |
||
132 | SetParamByte(PID_PRESSURE_OFFSET, off); |
||
133 | PressureSensorOffset = off; |
||
134 | AirPressure = AIR_PRESSURE_SCALE * (int32_t)AdAirPressure; // init IIR Filter |
||
135 | Delay_ms_Mess(300); |
||
136 | } |
||
137 | |||
138 | |||
139 | void SearchDacGyroOffset(void) |
||
140 | { |
||
141 | uint8_t i, ready = 0; |
||
142 | uint16_t timeout ; |
||
143 | |||
144 | GyroDefectNick = 0; GyroDefectRoll = 0; GyroDefectYaw = 0; |
||
145 | |||
146 | timeout = SetDelay(2000); |
||
147 | if(BoardRelease == 13) // the auto offset calibration is available only at board release 1.3 |
||
148 | { |
||
149 | for(i = 140; i != 0; i--) |
||
150 | { |
||
151 | if(ready == 3 && i > 10) i = 9; |
||
152 | ready = 0; |
||
153 | if(AdValueGyroNick < 1020) DacOffsetGyroNick--; else if(AdValueGyroNick > 1030) DacOffsetGyroNick++; else ready++; |
||
154 | if(AdValueGyroRoll < 1020) DacOffsetGyroRoll--; else if(AdValueGyroRoll > 1030) DacOffsetGyroRoll++; else ready++; |
||
155 | if(AdValueGyroYaw < 1020) DacOffsetGyroYaw-- ; else if(AdValueGyroYaw > 1030) DacOffsetGyroYaw++ ; else ready++; |
||
156 | I2C_Start(TWI_STATE_GYRO_OFFSET_TX); // initiate data transmission |
||
157 | if(DacOffsetGyroNick < 10) { GyroDefectNick = 1; DacOffsetGyroNick = 10;}; if(DacOffsetGyroNick > 245) { GyroDefectNick = 1; DacOffsetGyroNick = 245;}; |
||
158 | if(DacOffsetGyroRoll < 10) { GyroDefectRoll = 1; DacOffsetGyroRoll = 10;}; if(DacOffsetGyroRoll > 245) { GyroDefectRoll = 1; DacOffsetGyroRoll = 245;}; |
||
159 | if(DacOffsetGyroYaw < 10) { GyroDefectYaw = 1; DacOffsetGyroYaw = 10;}; if(DacOffsetGyroYaw > 245) { GyroDefectYaw = 1; DacOffsetGyroYaw = 245;}; |
||
160 | while(twi_state) |
||
161 | { |
||
162 | if(CheckDelay(timeout)) |
||
163 | { |
||
164 | printf("\r\n DAC or I2C Error1 check I2C, 3Vref, DAC, and BL-Ctrl"); |
||
165 | break; |
||
166 | } |
||
167 | } // wait for end of data transmission |
||
168 | ADReady = 0; |
||
169 | ADC_Enable(); |
||
170 | while(!ADReady); |
||
171 | if(i < 10) Delay_ms_Mess(10); |
||
172 | } |
||
173 | Delay_ms_Mess(70); |
||
174 | } |
||
175 | } |
||
176 | |||
177 | |||
178 | |||
179 | |||
180 | /*****************************************************/ |
||
181 | /* Interrupt Service Routine for ADC */ |
||
182 | /*****************************************************/ |
||
183 | // runs at 312.5 kHz or 3.2 µs |
||
184 | // if after (60.8µs) all 19 states are processed the interrupt is disabled |
||
185 | // and the update of further ads is stopped |
||
186 | |||
187 | /* |
||
188 | |||
189 | 1 rollgyro |
||
190 | 2 yawgyro |
||
191 | 3 accroll |
||
192 | 4 accnick |
||
193 | 5 nickgyro |
||
194 | 6 rollgyro |
||
195 | 7 ubat |
||
196 | 8 acctop |
||
197 | 9 air pressure |
||
198 | 10 nickgyro |
||
199 | 11 rollgyro |
||
200 | 12 yawgyro |
||
201 | 13 accroll |
||
202 | 14 accnick |
||
203 | 15 gyronick |
||
204 | 16 gyroroll |
||
205 | 17 air pressure |
||
206 | */ |
||
207 | |||
208 | |||
209 | #define AD_GYRO_YAW 0 |
||
210 | #define AD_GYRO_ROLL 1 |
||
211 | #define AD_GYRO_NICK 2 |
||
212 | #define AD_AIRPRESS 3 |
||
213 | #define AD_UBAT 4 |
||
214 | #define AD_ACC_TOP 5 |
||
215 | #define AD_ACC_ROLL 6 |
||
216 | #define AD_ACC_NICK 7 |
||
217 | |||
218 | ISR(ADC_vect) |
||
219 | { |
||
220 | static uint8_t ad_channel = AD_GYRO_NICK, state = 0; |
||
221 | static uint16_t gyroyaw, gyroroll, gyronick, accroll, accnick; |
||
222 | static int32_t filtergyronick, filtergyroroll; |
||
223 | static int32_t tmpAirPressure = 0; |
||
224 | static uint8_t AirPressCount = 0; |
||
225 | |||
226 | // state machine |
||
227 | switch(state++) |
||
228 | { |
||
229 | case 0: |
||
230 | gyronick = ADC; // get nick gyro voltage 1st sample |
||
231 | ad_channel = AD_GYRO_ROLL; |
||
232 | break; |
||
233 | case 1: |
||
234 | gyroroll = ADC; // get roll gyro voltage 1st sample |
||
235 | ad_channel = AD_GYRO_YAW; |
||
236 | break; |
||
237 | case 2: |
||
238 | gyroyaw = ADC; // get yaw gyro voltage 1st sample |
||
239 | ad_channel = AD_ACC_ROLL; |
||
240 | break; |
||
241 | case 3: |
||
242 | accroll = ADC; // get roll acc voltage 1st sample |
||
243 | ad_channel = AD_ACC_NICK; |
||
244 | break; |
||
245 | case 4: |
||
246 | accnick = ADC; // get nick acc voltage 1st sample |
||
247 | ad_channel = AD_GYRO_NICK; |
||
248 | break; |
||
249 | case 5: |
||
250 | gyronick += ADC; // get nick gyro voltage 2nd sample |
||
251 | ad_channel = AD_GYRO_ROLL; |
||
252 | break; |
||
253 | case 6: |
||
254 | gyroroll += ADC; // get roll gyro voltage 2nd sample |
||
255 | ad_channel = AD_UBAT; |
||
256 | break; |
||
257 | case 7: |
||
258 | // get actual UBat (Volts*10) is ADC*30V/1024*10 = ADC/3 |
||
259 | UBat = (3 * UBat + ADC / 3) / 4; // low pass filter updates UBat only to 1 quater with actual ADC value |
||
260 | ad_channel = AD_ACC_TOP; |
||
261 | break; |
||
262 | case 8: |
||
263 | AdValueAccZ = ADC; // get plain acceleration in Z direction |
||
264 | AdValueAccTop = (int16_t)ADC - AdBiasAccTop; // get acceleration in Z direction |
||
265 | if(AdValueAccTop > 1) |
||
266 | { |
||
267 | if(AdBiasAccTop < 750) |
||
268 | { |
||
269 | AdBiasAccTop += 0.02; |
||
270 | if(ModelIsFlying < 500) AdBiasAccTop += 0.1; |
||
271 | } |
||
272 | } |
||
273 | else if(AdValueAccTop < -1) |
||
274 | { |
||
275 | if(AdBiasAccTop > 550) |
||
276 | { |
||
277 | AdBiasAccTop -= 0.02; |
||
278 | if(ModelIsFlying < 500) AdBiasAccTop -= 0.1; |
||
279 | } |
||
280 | } |
||
281 | // averaging acc |
||
282 | ReadingIntegralTop -= ReadingIntegralTop / 1024; // discharge |
||
283 | ReadingIntegralTop += AdValueAccTop; // load |
||
284 | ad_channel = AD_AIRPRESS; |
||
285 | break; |
||
286 | // case 9 is moved to the end |
||
287 | case 10: |
||
288 | gyronick += ADC; // get nick gyro voltage 3rd sample |
||
289 | ad_channel = AD_GYRO_ROLL; |
||
290 | break; |
||
291 | case 11: |
||
292 | gyroroll += ADC; // get roll gyro voltage 3rd sample |
||
293 | ad_channel = AD_GYRO_YAW; |
||
294 | break; |
||
295 | case 12: |
||
296 | gyroyaw += ADC; // get yaw gyro voltage 2nd sample |
||
297 | if(BoardRelease == 10) AdValueGyroYaw = (gyroyaw + 1) / 2; // analog gain on board 1.0 is 2 times higher |
||
298 | else |
||
299 | if(BoardRelease == 20) AdValueGyroYaw = 2047 - gyroyaw; // 2 times higher than a single sample |
||
300 | else AdValueGyroYaw = gyroyaw; // 2 times higher than a single sample |
||
301 | ad_channel = AD_ACC_ROLL; |
||
302 | break; |
||
303 | case 13: |
||
304 | accroll += ADC; // get roll acc voltage 2nd sample |
||
305 | AdValueAccRoll = AdBiasAccRoll - accroll; // subtract bias |
||
306 | ad_channel = AD_ACC_NICK; |
||
307 | break; |
||
308 | case 14: |
||
309 | accnick += ADC; // get nick acc voltage 2nd sample |
||
310 | AdValueAccNick = accnick - AdBiasAccNick; // subtract bias |
||
311 | ad_channel = AD_GYRO_NICK; |
||
312 | break; |
||
313 | case 15: |
||
314 | gyronick += ADC; // get nick gyro voltage 4th sample |
||
315 | if(BoardRelease == 10) gyronick *= 2; // 8 times higer than a single sample, HW gain x2 |
||
316 | else gyronick *= 4; // 16 times higer than a single sample |
||
317 | AdValueGyroNick = gyronick / 8; // 2 times higher than a single sample |
||
318 | filtergyronick = (filtergyronick + gyronick) / 2; //(16 samples)/2 results in a factor of 8 higher than a single sample) see HIRES_GYRO_AMPLIFY |
||
319 | HiResGyroNick = filtergyronick - BiasHiResGyroNick; |
||
320 | FilterHiResGyroNick = (FilterHiResGyroNick + HiResGyroNick) / 2; |
||
321 | ad_channel = AD_GYRO_ROLL; |
||
322 | break; |
||
323 | case 16: |
||
324 | gyroroll += ADC; // get roll gyro voltage 4th sample |
||
325 | if(BoardRelease == 10) gyroroll *= 2; // 8 times higer than a single sample, HW gain x2 |
||
326 | else gyroroll *= 4; // 16 times higher than a single sample |
||
327 | AdValueGyroRoll = gyroroll / 8; // 2 times higher than a single sample |
||
328 | filtergyroroll = (filtergyroroll + gyroroll) / 2; //(16 samples)/2 results in a factor of 8 higher than a single sample) see HIRES_GYRO_AMPLIFY |
||
329 | HiResGyroRoll = filtergyroroll - BiasHiResGyroRoll; |
||
330 | FilterHiResGyroRoll = (FilterHiResGyroRoll + HiResGyroRoll) / 2; |
||
331 | ad_channel = AD_AIRPRESS; |
||
332 | break; |
||
333 | case 17: |
||
334 | state = 0; // restart sequence from beginning |
||
335 | ADReady = 1; // mark |
||
336 | MeasurementCounter++; // increment total measurement counter |
||
337 | // "break;" is missing to enable fall thru case 9 at the end of the sequence |
||
338 | case 9: |
||
339 | AdAirPressure = ADC; // update meassured air pressure, changes -523 counts per OPA_OFFSET_STEP |
||
340 | tmpAirPressure += AdAirPressure; |
||
341 | if(++AirPressCount >= AIR_PRESSURE_SCALE) |
||
342 | { |
||
343 | #define AIRPRESSURE_FILTER_TIME 8 |
||
344 | AirPressure = (AirPressure * (AIRPRESSURE_FILTER_TIME - 1) + tmpAirPressure + (AIR_PRESSURE_SCALE * EXPANDBARO_ADC_SHIFT) * (int32_t)ExpandBaro + AIRPRESSURE_FILTER_TIME/2)/AIRPRESSURE_FILTER_TIME; |
||
345 | ReadingHeight = (StartAirPressure - AirPressure); // change of air pressure to ground |
||
346 | SumHeight -= SumHeight/SM_FILTER; |
||
347 | SumHeight += ReadingHeight; |
||
348 | ReadingVario = (15 * ReadingVario + 8 * (int16_t)(ReadingHeight - SumHeight/SM_FILTER))/16; |
||
349 | tmpAirPressure /= 2; |
||
350 | AirPressCount = AIR_PRESSURE_SCALE/2; |
||
351 | } |
||
352 | ad_channel = AD_GYRO_NICK; |
||
353 | break; |
||
354 | default: |
||
355 | ad_channel = AD_GYRO_NICK; |
||
356 | state = 0; |
||
357 | break; |
||
358 | } |
||
359 | // set adc muxer to next ad_channel |
||
360 | ADMUX = (ADMUX & 0xE0) | ad_channel; |
||
361 | // after full cycle stop further interrupts |
||
362 | if(state != 0) ADC_Enable(); |
||
363 | } |