Subversion Repositories FlightCtrl

Rev

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
}