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