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; |
||
138 | |||
139 | GyroDefectNick = 0; GyroDefectRoll = 0; GyroDefectYaw = 0; |
||
1180 | killagreg | 140 | if(BoardRelease == 13) // the auto offset calibration is available only at board release 1.3 |
141 | { |
||
142 | for(i = 140; i != 0; i--) |
||
143 | { |
||
144 | if(ready == 3 && i > 10) i = 9; |
||
145 | ready = 0; |
||
146 | if(AdValueGyroNick < 1020) DacOffsetGyroNick--; else if(AdValueGyroNick > 1030) DacOffsetGyroNick++; else ready++; |
||
147 | if(AdValueGyroRoll < 1020) DacOffsetGyroRoll--; else if(AdValueGyroRoll > 1030) DacOffsetGyroRoll++; else ready++; |
||
148 | if(AdValueGyroYaw < 1020) DacOffsetGyroYaw-- ; else if(AdValueGyroYaw > 1030) DacOffsetGyroYaw++ ; else ready++; |
||
149 | twi_state = TWI_STATE_GYRO_OFFSET_TX; // set twi_state in TWI ISR to start of Gyro Offset |
||
150 | I2C_Start(); // initiate data transmission |
||
151 | if(DacOffsetGyroNick < 10) { GyroDefectNick = 1; DacOffsetGyroNick = 10;}; if(DacOffsetGyroNick > 245) { GyroDefectNick = 1; DacOffsetGyroNick = 245;}; |
||
152 | if(DacOffsetGyroRoll < 10) { GyroDefectRoll = 1; DacOffsetGyroRoll = 10;}; if(DacOffsetGyroRoll > 245) { GyroDefectRoll = 1; DacOffsetGyroRoll = 245;}; |
||
153 | if(DacOffsetGyroYaw < 10) { GyroDefectYaw = 1; DacOffsetGyroYaw = 10;}; if(DacOffsetGyroYaw > 245) { GyroDefectYaw = 1; DacOffsetGyroYaw = 245;}; |
||
154 | while(twi_state); // wait for end of data transmission |
||
155 | average_pressure = 0; |
||
156 | ADC_Enable(); |
||
157 | while(average_pressure == 0); |
||
158 | if(i < 10) Delay_ms_Mess(10); |
||
159 | } |
||
160 | Delay_ms_Mess(70); |
||
936 | killagreg | 161 | } |
162 | } |
||
163 | |||
164 | |||
165 | |||
166 | |||
886 | killagreg | 167 | /*****************************************************/ |
168 | /* Interrupt Service Routine for ADC */ |
||
169 | /*****************************************************/ |
||
1180 | killagreg | 170 | // runs at 312.5 kHz or 3.2 µs |
171 | // if after (60.8µs) all 19 states are processed the interrupt is disabled |
||
886 | killagreg | 172 | // and the update of further ads is stopped |
173 | |||
1180 | killagreg | 174 | /* |
175 | |||
176 | 1 rollgyro |
||
177 | 2 yawgyro |
||
178 | 3 accroll |
||
179 | 4 accnick |
||
180 | 5 nickgyro |
||
181 | 6 rollgyro |
||
182 | 7 ubat |
||
183 | 8 acctop |
||
184 | 9 air pressure |
||
185 | 10 nickgyro |
||
186 | 11 rollgyro |
||
187 | 12 yawgyro |
||
188 | 13 accroll |
||
189 | 14 accnick |
||
190 | 15 gyronick |
||
191 | 16 gyroroll |
||
192 | 17 airpressure |
||
193 | */ |
||
194 | |||
195 | |||
196 | #define AD_GYRO_YAW 0 |
||
197 | #define AD_GYRO_ROLL 1 |
||
198 | #define AD_GYRO_NICK 2 |
||
199 | #define AD_AIRPRESS 3 |
||
200 | #define AD_UBAT 4 |
||
201 | #define AD_ACC_TOP 5 |
||
202 | #define AD_ACC_ROLL 6 |
||
203 | #define AD_ACC_NICK 7 |
||
204 | |||
886 | killagreg | 205 | ISR(ADC_vect) |
1 | ingob | 206 | { |
1180 | killagreg | 207 | static uint8_t ad_channel = AD_GYRO_NICK, state = 0; |
208 | static uint16_t gyroyaw, gyroroll, gyronick, accroll, accnick; |
||
209 | static int32_t filtergyronick, filtergyroroll; |
||
886 | killagreg | 210 | static int16_t tmpAirPressure = 0; |
1180 | killagreg | 211 | |
886 | killagreg | 212 | // state machine |
1180 | killagreg | 213 | switch(state++) |
214 | { |
||
215 | case 0: |
||
216 | gyronick = ADC; // get nick gyro voltage 1st sample |
||
217 | ad_channel = AD_GYRO_ROLL; |
||
218 | break; |
||
219 | case 1: |
||
220 | gyroroll = ADC; // get roll gyro voltage 1st sample |
||
221 | ad_channel = AD_GYRO_YAW; |
||
222 | break; |
||
223 | case 2: |
||
224 | gyroyaw = ADC; // get yaw gyro voltage 1st sample |
||
225 | ad_channel = AD_ACC_ROLL; |
||
226 | break; |
||
227 | case 3: |
||
228 | accroll = ADC; // get roll acc voltage 1st sample |
||
229 | ad_channel = AD_ACC_NICK; |
||
1 | ingob | 230 | break; |
1180 | killagreg | 231 | case 4: |
232 | accnick = ADC; // get nick acc voltage 1st sample |
||
233 | ad_channel = AD_GYRO_NICK; |
||
234 | break; |
||
235 | case 5: |
||
236 | gyronick += ADC; // get nick gyro voltage 2nd sample |
||
237 | ad_channel = AD_GYRO_ROLL; |
||
238 | break; |
||
239 | case 6: |
||
240 | gyroroll += ADC; // get roll gyro voltage 2nd sample |
||
241 | ad_channel = AD_UBAT; |
||
242 | break; |
||
243 | case 7: |
||
244 | // get actual UBat (Volts*10) is ADC*30V/1024*10 = ADC/3 |
||
245 | UBat = (3 * UBat + ADC / 3) / 4; // low pass filter updates UBat only to 1 quater with actual ADC value |
||
246 | ad_channel = AD_ACC_TOP; |
||
1 | ingob | 247 | break; |
1180 | killagreg | 248 | case 8: |
249 | AdValueAccZ = ADC; // get plain acceleration in Z direction |
||
250 | AdValueAccTop = (int16_t)ADC - AdBiasAccTop; // get acceleration in Z direction |
||
251 | if(AdValueAccTop > 1) |
||
252 | { |
||
253 | if(AdBiasAccTop < 750) |
||
254 | { |
||
255 | AdBiasAccTop += 0.02; |
||
256 | if(ModelIsFlying < 500) AdBiasAccTop += 0.1; |
||
886 | killagreg | 257 | } |
1180 | killagreg | 258 | } |
259 | else if(AdValueAccTop < -1) |
||
260 | { |
||
261 | if(AdBiasAccTop > 550) |
||
262 | { |
||
263 | AdBiasAccTop -= 0.02; |
||
264 | if(ModelIsFlying < 500) AdBiasAccTop -= 0.1; |
||
886 | killagreg | 265 | } |
1180 | killagreg | 266 | } |
267 | ReadingIntegralTop += AdValueAccTop; // load |
||
268 | ReadingIntegralTop -= ReadingIntegralTop / 1024; // discharge |
||
269 | ad_channel = AD_AIRPRESS; |
||
270 | break; |
||
271 | // case 9 is moved to the end |
||
272 | case 10: |
||
273 | gyronick += ADC; // get nick gyro voltage 3rd sample |
||
274 | ad_channel = AD_GYRO_ROLL; |
||
275 | break; |
||
276 | case 11: |
||
277 | gyroroll += ADC; // get roll gyro voltage 3rd sample |
||
278 | ad_channel = AD_GYRO_YAW; |
||
279 | break; |
||
280 | case 12: |
||
281 | gyroyaw += ADC; // get yaw gyro voltage 2nd sample |
||
282 | if(BoardRelease == 10) AdValueGyroYaw = (gyroyaw + 1) / 2; // analog gain on board 1.0 is 2 times higher |
||
283 | else |
||
284 | if(BoardRelease == 20) AdValueGyroYaw = 2047 - gyroyaw; // 2 times higher than a single sample |
||
285 | else AdValueGyroYaw = gyroyaw; // 2 times higher than a single sample |
||
286 | ad_channel = AD_ACC_ROLL; |
||
287 | break; |
||
288 | case 13: |
||
289 | accroll += ADC; // get roll acc voltage 2nd sample |
||
290 | AdValueAccRoll = AdBiasAccRoll - accroll; // subtract bias |
||
291 | ad_channel = AD_ACC_NICK; |
||
292 | break; |
||
293 | case 14: |
||
294 | accnick += ADC; // get nick acc voltage 2nd sample |
||
295 | AdValueAccNick = accnick - AdBiasAccNick; // subtract bias |
||
296 | ad_channel = AD_GYRO_NICK; |
||
1 | ingob | 297 | break; |
1180 | killagreg | 298 | case 15: |
299 | gyronick += ADC; // get nick gyro voltage 4th sample |
||
300 | if(BoardRelease == 10) gyronick *= 2; // 8 times higer than a single sample, HW gain x2 |
||
301 | else gyronick *= 4; // 16 times higer than a single sample |
||
302 | AdValueGyroNick = gyronick / 8; // 2 times higher than a single sample |
||
303 | filtergyronick = (filtergyronick + gyronick) / 2; //(16 samples)/2 results in a factor of 8 higher than a single sample) see HIRES_GYRO_AMPLIFY |
||
304 | HiResGyroNick = filtergyronick - BiasHiResGyroNick; |
||
305 | FilterHiResGyroNick = (FilterHiResGyroNick + HiResGyroNick) / 2; |
||
306 | ad_channel = AD_GYRO_ROLL; |
||
307 | break; |
||
308 | case 16: |
||
309 | gyroroll += ADC; // get roll gyro voltage 4th sample |
||
310 | if(BoardRelease == 10) gyroroll *= 2; // 8 times higer than a single sample, HW gain x2 |
||
311 | else gyroroll *= 4; // 16 times higer than a single sample |
||
312 | AdValueGyroRoll = gyroroll / 8; // 2 times higher than a single sample |
||
313 | filtergyroroll = (filtergyroroll + gyroroll) / 2; //(16 samples)/2 results in a factor of 8 higher than a single sample) see HIRES_GYRO_AMPLIFY |
||
314 | HiResGyroRoll = filtergyroroll - BiasHiResGyroRoll; |
||
315 | FilterHiResGyroRoll = (FilterHiResGyroRoll + HiResGyroRoll) / 2; |
||
316 | ad_channel = AD_AIRPRESS; |
||
317 | break; |
||
318 | case 17: |
||
319 | state = 0; // restart sequence from beginning |
||
320 | ADReady = 1; // mark |
||
321 | MeasurementCounter++; // increment total measurement counter |
||
322 | // "break;" is missing to enable fall thru case 9 at the end of the sequence |
||
323 | case 9: |
||
324 | tmpAirPressure += ADC; // sum adc values |
||
325 | if(++average_pressure >= 5) // if 5 values are summerized for averaging |
||
326 | { |
||
327 | tmpAirPressure /= 2; |
||
328 | ReadingAirPressure = ADC; // update meassured air pressure |
||
329 | HeightD = (31 * HeightD + (int16_t)FCParam.HeightD * (int16_t)(255 * ExpandBaro + StartAirPressure - tmpAirPressure - ReadingHeight)) / 32; // D-Part = CurrentValue - OldValue |
||
330 | AirPressure = (tmpAirPressure + 7 * AirPressure + 4) / 8; // averaging using history |
||
331 | ReadingHeight = 255 * ExpandBaro + StartAirPressure - AirPressure; |
||
332 | average_pressure = 0; // reset air pressure measurement counter |
||
333 | tmpAirPressure /= 2; |
||
334 | } |
||
335 | ad_channel = AD_GYRO_NICK; |
||
336 | break; |
||
337 | default: |
||
338 | ad_channel = AD_GYRO_NICK; |
||
339 | state = 0; |
||
340 | break; |
||
341 | } |
||
342 | // set adc muxer to next ad_channel |
||
343 | ADMUX = (ADMUX & 0xE0) | ad_channel; |
||
886 | killagreg | 344 | // after full cycle stop further interrupts |
345 | if(state != 0) ADC_Enable(); |
||
1 | ingob | 346 | } |