Subversion Repositories FlightCtrl

Rev

Rev 1114 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1112 thjac 1
/*#######################################################################################
2
Flight Control
3
#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + Copyright (c) 04.2007 Holger Buss
6
// + Nur für den privaten Gebrauch
7
// + www.MikroKopter.com
8
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
10
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
11
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
12
// + bzgl. der Nutzungsbedingungen aufzunehmen.
13
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
14
// + Verkauf von Luftbildaufnahmen, usw.
15
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
17
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
18
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
20
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
21
// + eindeutig als Ursprung verlinkt werden
22
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
24
// + Benutzung auf eigene Gefahr
25
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
26
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
28
// + mit unserer Zustimmung zulässig
29
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
31
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
33
// + this list of conditions and the following disclaimer.
34
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
35
// +     from this software without specific prior written permission.
36
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
37
// +     for non-commercial use (directly or indirectly)
38
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
39
// +     with our written permission
40
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
41
// +     clearly linked as origin
42
// +   * porting to systems other than hardware from www.mikrokopter.de is not allowed
43
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
44
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
47
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52
// +  POSSIBILITY OF SUCH DAMAGE.
53
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
54
 
55
#include "main.h"
56
#include "parameter.h"
57
#include "pitch.h"
58
#include "eeprom.c"
59
 
60
unsigned char h,m,s;
61
volatile unsigned int I2CTimeout = 100;
62
volatile int MesswertNick,MesswertRoll,MesswertGier,MesswertGierBias;
63
int AdNeutralGierBias;
64
int AdNeutralNick = 0,AdNeutralRoll = 0,AdNeutralGier = 0,StartNeutralRoll = 0,StartNeutralNick = 0;
65
int Mittelwert_AccNick, Mittelwert_AccRoll,Mittelwert_AccHoch, NeutralAccX=0, NeutralAccY=0;
66
int NaviAccNick, NaviAccRoll,NaviCntAcc = 0;
67
volatile float NeutralAccZ = 0;
68
unsigned char CosinusNickWinkel = 0, CosinusRollWinkel = 0;
69
long IntegralNick = 0,IntegralNick2 = 0;
70
long IntegralRoll = 0,IntegralRoll2 = 0;
71
long IntegralAccNick = 0,IntegralAccRoll = 0,IntegralAccZ = 0;
72
long Integral_Gier = 0;
73
long Mess_IntegralNick = 0,Mess_IntegralNick2 = 0;
74
long Mess_IntegralRoll = 0,Mess_IntegralRoll2 = 0;
75
long Mess_Integral_Gier = 0,Mess_Integral_Gier2 = 0;
76
long MittelIntegralNick,MittelIntegralRoll,MittelIntegralNick2,MittelIntegralRoll2;
77
volatile long Mess_Integral_Hoch = 0;
78
volatile int  KompassValue = 0;
79
volatile int  KompassStartwert = 0;
80
volatile int  KompassRichtung = 0;
81
unsigned int  KompassSignalSchlecht = 500;
82
unsigned char  MAX_GAS,MIN_GAS;
83
unsigned char Notlandung = 0;
84
unsigned char HoehenReglerAktiv = 0;
85
unsigned char TrichterFlug = 0;
86
long Umschlag180Nick = 250000L, Umschlag180Roll = 250000L;
87
long  ErsatzKompass;
88
int   ErsatzKompassInGrad; // Kompasswert in Grad
89
int   GierGyroFehler = 0;
90
float GyroFaktor;
91
float IntegralFaktor;
92
volatile int  DiffNick,DiffRoll;
93
int  Poti1 = 0, Poti2 = 0, Poti3 = 0, Poti4 = 0;
94
volatile unsigned char Motor_Vorne,Motor_Hinten,Motor_Rechts,Motor_Links, Count;
95
volatile unsigned char SenderOkay = 0;
96
int StickNick = 0,StickRoll = 0,StickGier = 0,StickGas = 0;
97
char MotorenEin = 0;
98
int HoehenWert = 0;
99
int SollHoehe = 0;
100
int LageKorrekturRoll = 0,LageKorrekturNick = 0;
101
float Ki =  FAKTOR_I;
102
unsigned char Looping_Nick = 0,Looping_Roll = 0;
103
unsigned char Looping_Links = 0, Looping_Rechts = 0, Looping_Unten = 0, Looping_Oben = 0;
104
 
105
unsigned char Parameter_Luftdruck_D  = 48;      // Wert : 0-250
106
unsigned char Parameter_MaxHoehe     = 251;      // Wert : 0-250
107
unsigned char Parameter_Hoehe_P      = 16;      // Wert : 0-32
108
unsigned char Parameter_Hoehe_ACC_Wirkung = 58; // Wert : 0-250
109
unsigned char Parameter_KompassWirkung = 64;    // Wert : 0-250
110
unsigned char Parameter_Gyro_P = 150;           // Wert : 10-250
111
unsigned char Parameter_Gyro_I = 150;           // Wert : 0-250
112
unsigned char Parameter_Gier_P = 2;             // Wert : 1-20
113
unsigned char Parameter_I_Faktor = 10;          // Wert : 1-20
114
unsigned char Parameter_UserParam1 = 0;
115
unsigned char Parameter_UserParam2 = 0;
116
unsigned char Parameter_UserParam3 = 0;
117
unsigned char Parameter_UserParam4 = 0;
118
unsigned char Parameter_UserParam5 = 0;
119
unsigned char Parameter_UserParam6 = 0;
120
unsigned char Parameter_UserParam7 = 0;
121
unsigned char Parameter_UserParam8 = 0;
122
unsigned char Parameter_ServoNickControl = 100;
123
unsigned char Parameter_LoopGasLimit = 70;
124
unsigned char Parameter_AchsKopplung1 = 0;
125
unsigned char Parameter_AchsGegenKopplung1 = 0;
126
unsigned char Parameter_DynamicStability = 100;
127
unsigned char Parameter_J16Bitmask;             // for the J16 Output
128
unsigned char Parameter_J16Timing;              // for the J16 Output
129
unsigned char Parameter_J17Bitmask;             // for the J17 Output
130
unsigned char Parameter_J17Timing;              // for the J17 Output
131
unsigned char Parameter_NaviGpsModeControl;     // Parameters for the Naviboard
132
unsigned char Parameter_NaviGpsGain;
133
unsigned char Parameter_NaviGpsP;
134
unsigned char Parameter_NaviGpsI;
135
unsigned char Parameter_NaviGpsD;
136
unsigned char Parameter_NaviGpsACC;
137
unsigned char Parameter_NaviOperatingRadius;
138
unsigned char Parameter_NaviWindCorrection;
139
unsigned char Parameter_NaviSpeedCompensation;
140
unsigned char Parameter_ExternalControl;
141
struct mk_param_struct EE_Parameter;
142
signed int ExternStickNick = 0,ExternStickRoll = 0,ExternStickGier = 0, ExternHoehenValue = -20;
143
int MaxStickNick = 0,MaxStickRoll = 0;
144
unsigned int  modell_fliegt = 0;
145
unsigned char MikroKopterFlags = 0;
146
 
147
void Piep(unsigned char Anzahl)
148
{
149
 while(Anzahl--)
150
 {
151
  if(MotorenEin) return; //auf keinen Fall im Flug!
152
  beeptime = 100;
153
  Delay_ms(250);
154
 }
155
}
156
 
157
//############################################################################
158
//  Nullwerte ermitteln
159
void SetNeutral(void)
160
//############################################################################
161
{
162
        NeutralAccX = 0;
163
        NeutralAccY = 0;
164
        NeutralAccZ = 0;
165
    AdNeutralNick = 0;
166
        AdNeutralRoll = 0;
167
        AdNeutralGier = 0;
168
    AdNeutralGierBias = 0;
169
    Parameter_AchsKopplung1 = 0;
170
    Parameter_AchsGegenKopplung1 = 0;
171
    ExpandBaro = 0;
172
    CalibrierMittelwert();
173
    Delay_ms_Mess(100);
174
        CalibrierMittelwert();
175
    if((EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG))  // Höhenregelung aktiviert?
176
     {
177
      if((MessLuftdruck > 950) || (MessLuftdruck < 750)) SucheLuftruckOffset();
178
     }
179
 
180
     AdNeutralNick= AdWertNick;
181
         AdNeutralRoll= AdWertRoll;
182
         AdNeutralGier= AdWertGier;
183
     AdNeutralGierBias = AdWertGier;
184
     StartNeutralRoll = AdNeutralRoll;
185
     StartNeutralNick = AdNeutralNick;
186
    if(eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_NICK]) > 4)
187
    {
188
      NeutralAccY = abs(Mittelwert_AccRoll) / ACC_AMPLIFY;
189
          NeutralAccX = abs(Mittelwert_AccNick) / ACC_AMPLIFY;
190
          NeutralAccZ = Aktuell_az;
191
    }
192
    else
193
    {
194
      NeutralAccX = (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_NICK]) * 256 + (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_NICK+1]);
195
          NeutralAccY = (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_ROLL]) * 256 + (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_ROLL+1]);
196
          NeutralAccZ = (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_Z]) * 256 + (int)eeprom_read_byte(&EEPromArray[EEPROM_ADR_ACC_Z+1]);
197
    }
198
 
199
        Mess_IntegralNick = 0;
200
    Mess_IntegralNick2 = 0;
201
    Mess_IntegralRoll = 0;
202
    Mess_IntegralRoll2 = 0;
203
    Mess_Integral_Gier = 0;
204
    MesswertNick = 0;
205
    MesswertRoll = 0;
206
    MesswertGier = 0;
207
 Delay_ms_Mess(100);
208
    StartLuftdruck = Luftdruck;
209
    HoeheD = 0;
210
    Mess_Integral_Hoch = 0;
211
    KompassStartwert = KompassValue;
212
    GPS_Neutral();
213
    beeptime = 50;
214
        Umschlag180Nick = ((long) EE_Parameter.WinkelUmschlagNick * 2500L) + 15000L;
215
        Umschlag180Roll = ((long) EE_Parameter.WinkelUmschlagRoll * 2500L) + 15000L;
216
    ExternHoehenValue = 0;
217
    ErsatzKompass = KompassValue * GIER_GRAD_FAKTOR;
218
    GierGyroFehler = 0;
219
    SendVersionToNavi = 1;
220
    LED_Init();
221
    MikroKopterFlags |= FLAG_CALIBRATE;
222
    FromNaviCtrl_Value.Kalman_K = -1;
223
    FromNaviCtrl_Value.Kalman_MaxDrift = EE_Parameter.Driftkomp * 16;
224
    FromNaviCtrl_Value.Kalman_MaxFusion = 32;
225
}
226
 
227
//############################################################################
228
// Bearbeitet die Messwerte
229
void Mittelwert(void)
230
//############################################################################
231
{
232
    static signed long tmpl,tmpl2;
233
    MesswertGier = (signed int) AdNeutralGier - AdWertGier;
234
    MesswertGierBias = (signed int) AdNeutralGierBias - AdWertGier;
235
    MesswertRoll = (signed int) AdWertRoll - AdNeutralRoll;
236
    MesswertNick = (signed int) AdWertNick - AdNeutralNick;
237
 
238
//DebugOut.Analog[26] = MesswertNick;
239
// DebugOut.Analog[28] = MesswertRoll;
240
 
241
// Beschleunigungssensor  ++++++++++++++++++++++++++++++++++++++++++++++++
242
        Mittelwert_AccNick = ((long)Mittelwert_AccNick * 1 + ((ACC_AMPLIFY * (long)AdWertAccNick))) / 2L;
243
        Mittelwert_AccRoll = ((long)Mittelwert_AccRoll * 1 + ((ACC_AMPLIFY * (long)AdWertAccRoll))) / 2L;
244
        Mittelwert_AccHoch = ((long)Mittelwert_AccHoch * 1 + ((long)AdWertAccHoch)) / 2L;
245
    IntegralAccNick += ACC_AMPLIFY * AdWertAccNick;
246
    IntegralAccRoll += ACC_AMPLIFY * AdWertAccRoll;
247
    NaviAccNick    += AdWertAccNick;
248
    NaviAccRoll    += AdWertAccRoll;
249
    NaviCntAcc++;
250
    IntegralAccZ    += Aktuell_az - NeutralAccZ;
251
// Gier  ++++++++++++++++++++++++++++++++++++++++++++++++
252
            ErsatzKompass +=  MesswertGier;
253
            Mess_Integral_Gier +=  MesswertGier;
254
//            Mess_Integral_Gier2 += MesswertGier;
255
                    if(ErsatzKompass >= (360L * GIER_GRAD_FAKTOR)) ErsatzKompass -= 360L * GIER_GRAD_FAKTOR;  // 360° Umschlag
256
                    if(ErsatzKompass < 0)                          ErsatzKompass += 360L * GIER_GRAD_FAKTOR;
257
// Kopplungsanteil  +++++++++++++++++++++++++++++++++++++
258
      if(!Looping_Nick && !Looping_Roll && (EE_Parameter.GlobalConfig & CFG_ACHSENKOPPLUNG_AKTIV))
259
         {
260
            tmpl = (MesswertGierBias * Mess_IntegralNick) / 2048L;
261
            tmpl *= Parameter_AchsKopplung1;  //125
262
            tmpl /= 4096L;
263
            tmpl2 = (MesswertGierBias * Mess_IntegralRoll) / 2048L;
264
            tmpl2 *= Parameter_AchsKopplung1;
265
            tmpl2 /= 4096L;
266
            if(labs(tmpl) > 128 || labs(tmpl2) > 128) TrichterFlug = 1;
267
         }
268
      else  tmpl = tmpl2 = 0;
269
// Roll  ++++++++++++++++++++++++++++++++++++++++++++++++
270
            MesswertRoll += tmpl;
271
            MesswertRoll += (tmpl2*Parameter_AchsGegenKopplung1)/512L; //109
272
            Mess_IntegralRoll2 += MesswertRoll;
273
            Mess_IntegralRoll +=  MesswertRoll - LageKorrekturRoll;
274
            if(Mess_IntegralRoll > Umschlag180Roll)
275
            {
276
             Mess_IntegralRoll  = -(Umschlag180Roll - 25000L);
277
             Mess_IntegralRoll2 = Mess_IntegralRoll;
278
            }
279
            if(Mess_IntegralRoll <-Umschlag180Roll)
280
            {
281
             Mess_IntegralRoll =  (Umschlag180Roll - 25000L);
282
             Mess_IntegralRoll2 = Mess_IntegralRoll;
283
            }
284
            if(AdWertRoll < 15)   MesswertRoll = -1000;
285
            if(AdWertRoll <  7)   MesswertRoll = -2000;
286
            if(PlatinenVersion == 10)
287
                         {
288
              if(AdWertRoll > 1010) MesswertRoll = +1000;
289
              if(AdWertRoll > 1017) MesswertRoll = +2000;
290
                         }
291
                         else
292
                         {
293
              if(AdWertRoll > 2020) MesswertRoll = +1000;
294
              if(AdWertRoll > 2034) MesswertRoll = +2000;
295
                         }
296
// Nick  ++++++++++++++++++++++++++++++++++++++++++++++++
297
            MesswertNick -= tmpl2;
298
            MesswertNick -= (tmpl*Parameter_AchsGegenKopplung1)/512L;
299
            Mess_IntegralNick2 += MesswertNick;
300
            Mess_IntegralNick  += MesswertNick - LageKorrekturNick;
301
 
302
            if(Mess_IntegralNick > Umschlag180Nick)
303
             {
304
              Mess_IntegralNick = -(Umschlag180Nick - 25000L);
305
              Mess_IntegralNick2 = Mess_IntegralNick;
306
             }
307
            if(Mess_IntegralNick <-Umschlag180Nick)
308
            {
309
             Mess_IntegralNick =  (Umschlag180Nick - 25000L);
310
             Mess_IntegralNick2 = Mess_IntegralNick;
311
            }
312
            if(AdWertNick < 15)   MesswertNick = -1000;
313
            if(AdWertNick <  7)   MesswertNick = -2000;
314
            if(PlatinenVersion == 10)
315
                         {
316
              if(AdWertNick > 1010) MesswertNick = +1000;
317
              if(AdWertNick > 1017) MesswertNick = +2000;
318
                         }
319
                         else
320
                         {
321
              if(AdWertNick > 2020) MesswertNick = +1000;
322
              if(AdWertNick > 2034) MesswertNick = +2000;
323
                         }
324
//++++++++++++++++++++++++++++++++++++++++++++++++
325
// ADC einschalten
326
    ANALOG_ON;
327
//++++++++++++++++++++++++++++++++++++++++++++++++
328
 
329
    Integral_Gier  = Mess_Integral_Gier;
330
    IntegralNick = Mess_IntegralNick;
331
    IntegralRoll = Mess_IntegralRoll;
332
    IntegralNick2 = Mess_IntegralNick2;
333
    IntegralRoll2 = Mess_IntegralRoll2;
334
 
335
  if(EE_Parameter.GlobalConfig & CFG_DREHRATEN_BEGRENZER && !Looping_Nick && !Looping_Roll)
336
  {
337
    if(MesswertNick > 200)       MesswertNick += 4 * (MesswertNick - 200);
338
    else if(MesswertNick < -200) MesswertNick += 4 * (MesswertNick + 200);
339
    if(MesswertRoll > 200)       MesswertRoll += 4 * (MesswertRoll - 200);
340
    else if(MesswertRoll < -200) MesswertRoll += 4 * (MesswertRoll + 200);
341
  }
342
    if(Poti1 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI1]] + 110) Poti1++; else if(Poti1 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI1]] + 110 && Poti1) Poti1--;
343
    if(Poti2 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI2]] + 110) Poti2++; else if(Poti2 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI2]] + 110 && Poti2) Poti2--;
344
    if(Poti3 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] + 110) Poti3++; else if(Poti3 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] + 110 && Poti3) Poti3--;
345
    if(Poti4 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI4]] + 110) Poti4++; else if(Poti4 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI4]] + 110 && Poti4) Poti4--;
346
    if(Poti1 < 0) Poti1 = 0; else if(Poti1 > 255) Poti1 = 255;
347
    if(Poti2 < 0) Poti2 = 0; else if(Poti2 > 255) Poti2 = 255;
348
    if(Poti3 < 0) Poti3 = 0; else if(Poti3 > 255) Poti3 = 255;
349
    if(Poti4 < 0) Poti4 = 0; else if(Poti4 > 255) Poti4 = 255;
350
}
351
 
352
//############################################################################
353
// Messwerte beim Ermitteln der Nullage
354
void CalibrierMittelwert(void)
355
//############################################################################
356
{
357
    if(PlatinenVersion == 13) SucheGyroOffset();
358
    // ADC auschalten, damit die Werte sich nicht während der Berechnung ändern
359
        ANALOG_OFF;
360
        MesswertNick = AdWertNick;
361
        MesswertRoll = AdWertRoll;
362
        MesswertGier = AdWertGier;
363
        Mittelwert_AccNick = ACC_AMPLIFY * (long)AdWertAccNick;
364
        Mittelwert_AccRoll = ACC_AMPLIFY * (long)AdWertAccRoll;
365
        Mittelwert_AccHoch = (long)AdWertAccHoch;
366
   // ADC einschalten
367
    ANALOG_ON;
368
    if(Poti1 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI1]] + 110) Poti1++; else if(Poti1 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI1]] + 110 && Poti1) Poti1--;
369
    if(Poti2 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI2]] + 110) Poti2++; else if(Poti2 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI2]] + 110 && Poti2) Poti2--;
370
    if(Poti3 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] + 110) Poti3++; else if(Poti3 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] + 110 && Poti3) Poti3--;
371
    if(Poti4 < PPM_in[EE_Parameter.Kanalbelegung[K_POTI4]] + 110) Poti4++; else if(Poti4 > PPM_in[EE_Parameter.Kanalbelegung[K_POTI4]] + 110 && Poti4) Poti4--;
372
    if(Poti1 < 0) Poti1 = 0; else if(Poti1 > 255) Poti1 = 255;
373
    if(Poti2 < 0) Poti2 = 0; else if(Poti2 > 255) Poti2 = 255;
374
    if(Poti3 < 0) Poti3 = 0; else if(Poti3 > 255) Poti3 = 255;
375
    if(Poti4 < 0) Poti4 = 0; else if(Poti4 > 255) Poti4 = 255;
376
 
377
        Umschlag180Nick = (long) EE_Parameter.WinkelUmschlagNick * 2500L;
378
        Umschlag180Roll = (long) EE_Parameter.WinkelUmschlagRoll * 2500L;
379
}
380
 
381
//############################################################################
382
// Senden der Motorwerte per I2C-Bus
383
void SendMotorData(void)
384
//############################################################################
385
{
386
    DebugOut.Analog[12] = Motor_Vorne;
387
    DebugOut.Analog[13] = Motor_Hinten;
388
    DebugOut.Analog[14] = Motor_Links;
389
    DebugOut.Analog[15] = Motor_Rechts;  
390
 
391
    if(!( MotorenEin && PARAM_ENGINE_ENABLED ) )
392
        {
393
        Motor_Hinten = 0;
394
        Motor_Vorne = 0;
395
        Motor_Rechts = 0;
396
        Motor_Links = 0;
397
        if(MotorTest[0]) Motor_Vorne = MotorTest[0];
398
        if(MotorTest[1]) Motor_Hinten = MotorTest[1];
399
        if(MotorTest[2]) Motor_Links = MotorTest[2];
400
        if(MotorTest[3]) Motor_Rechts = MotorTest[3];
401
        MikroKopterFlags &= ~(FLAG_MOTOR_RUN | FLAG_FLY);
402
        } else MikroKopterFlags |= FLAG_MOTOR_RUN;
403
 
404
    //Start I2C Interrupt Mode
405
    twi_state = 0;
406
    motor = 0;
407
    i2c_start();
408
}
409
 
410
 
411
 
412
//############################################################################
413
// Trägt ggf. das Poti als Parameter ein
414
void ParameterZuordnung(void)
415
//############################################################################
416
{
417
 #define CHK_POTI_MM(b,a,min,max) { if(a > 250) { if(a == 251) b = Poti1; else if(a == 252) b = Poti2; else if(a == 253) b = Poti3; else if(a == 254) b = Poti4;} else b = a; if(b <= min) b = min; else if(b >= max) b = max;}
418
 #define CHK_POTI(b,a,min,max) { if(a > 250) { if(a == 251) b = Poti1; else if(a == 252) b = Poti2; else if(a == 253) b = Poti3; else if(a == 254) b = Poti4;} else b = a; }
419
 CHK_POTI(Parameter_MaxHoehe,EE_Parameter.MaxHoehe,0,255);
420
 CHK_POTI_MM(Parameter_Luftdruck_D,EE_Parameter.Luftdruck_D,0,100);
421
 CHK_POTI_MM(Parameter_Hoehe_P,EE_Parameter.Hoehe_P,0,100);
422
 CHK_POTI(Parameter_Hoehe_ACC_Wirkung,EE_Parameter.Hoehe_ACC_Wirkung,0,255);
423
 CHK_POTI(Parameter_KompassWirkung,EE_Parameter.KompassWirkung,0,255);
424
 CHK_POTI_MM(Parameter_Gyro_P,EE_Parameter.Gyro_P,10,255);
425
 CHK_POTI(Parameter_Gyro_I,EE_Parameter.Gyro_I,0,255);
426
 CHK_POTI(Parameter_I_Faktor,EE_Parameter.I_Faktor,0,255);
427
 CHK_POTI(Parameter_UserParam1,EE_Parameter.UserParam1,0,255);
428
 CHK_POTI(Parameter_UserParam2,EE_Parameter.UserParam2,0,255);
429
 CHK_POTI(Parameter_UserParam3,EE_Parameter.UserParam3,0,255);
430
 CHK_POTI(Parameter_UserParam4,EE_Parameter.UserParam4,0,255);
431
 CHK_POTI(Parameter_UserParam5,EE_Parameter.UserParam5,0,255);
432
 CHK_POTI(Parameter_UserParam6,EE_Parameter.UserParam6,0,255);
433
 CHK_POTI(Parameter_UserParam7,EE_Parameter.UserParam7,0,255);
434
 CHK_POTI(Parameter_UserParam8,EE_Parameter.UserParam8,0,255);
435
 CHK_POTI(Parameter_ServoNickControl,EE_Parameter.ServoNickControl,0,255);
436
 CHK_POTI(Parameter_LoopGasLimit,EE_Parameter.LoopGasLimit,0,255);
437
 CHK_POTI(Parameter_AchsKopplung1,    EE_Parameter.AchsKopplung1,0,255);
438
 CHK_POTI(Parameter_AchsGegenKopplung1,EE_Parameter.AchsGegenKopplung1,0,255);
439
 CHK_POTI(Parameter_DynamicStability,EE_Parameter.DynamicStability,0,255);
440
 CHK_POTI_MM(Parameter_J16Timing,EE_Parameter.J16Timing,1,255);
441
 CHK_POTI_MM(Parameter_J17Timing,EE_Parameter.J17Timing,1,255);
442
 
443
// CHK_POTI(Parameter_NaviGpsModeControl,EE_Parameter.NaviGpsModeControl,0,255);
444
 //CHK_POTI(Parameter_NaviGpsGain,EE_Parameter.NaviGpsGain,0,255);
445
// CHK_POTI(Parameter_NaviGpsP,EE_Parameter.NaviGpsP,0,255);
446
// CHK_POTI(Parameter_NaviGpsI,EE_Parameter.NaviGpsI,0,255);
447
// CHK_POTI(Parameter_NaviGpsD,EE_Parameter.NaviGpsD,0,255);
448
// CHK_POTI(Parameter_NaviGpsACC,EE_Parameter.NaviGpsACC,0,255);
449
// CHK_POTI_MM(Parameter_NaviOperatingRadius,EE_Parameter.NaviOperatingRadius,10,255);
450
// CHK_POTI(Parameter_NaviWindCorrection,EE_Parameter.NaviWindCorrection,0,255);
451
// CHK_POTI(Parameter_NaviSpeedCompensation,EE_Parameter.NaviSpeedCompensation,0,255);
452
 
453
 CHK_POTI(Parameter_ExternalControl,EE_Parameter.ExternalControl,0,255);
454
 
455
 Ki = (float) Parameter_I_Faktor * 0.0001;
456
 MAX_GAS = EE_Parameter.Gas_Max;
457
 MIN_GAS = EE_Parameter.Gas_Min;
458
}
459
 
460
 
461
 
462
//############################################################################
463
//
464
void MotorRegler(void)
465
//############################################################################
466
{
467
         int motorwert,pd_ergebnis,tmp_int;
468
         int GierMischanteil,GasMischanteil;
469
     static long SummeNick=0,SummeRoll=0;
470
     static long sollGier = 0,tmp_long,tmp_long2;
471
     static long IntegralFehlerNick = 0;
472
     static long IntegralFehlerRoll = 0;
473
         static unsigned int RcLostTimer;
474
         static unsigned char delay_neutral = 0;
475
         static unsigned char delay_einschalten = 0,delay_ausschalten = 0;
476
     static char TimerWerteausgabe = 0;
477
     static char NeueKompassRichtungMerken = 0;
478
     static long ausgleichNick, ausgleichRoll;
479
 
480
        Mittelwert();
481
 
482
    GRN_ON;
483
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
484
// Gaswert ermitteln
485
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
486
        GasMischanteil = StickGas;
487
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
488
// Empfang schlecht
489
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
490
   if(SenderOkay < 100)
491
        {
492
        if(!PcZugriff)
493
         {
494
           if(BeepMuster == 0xffff)
495
            {
496
             beeptime = 15000;
497
             BeepMuster = 0x0c00;
498
            }
499
         }
500
        if(RcLostTimer) RcLostTimer--;
501
        else
502
         {
503
          MotorenEin = 0;
504
          Notlandung = 0;
505
         }
506
        ROT_ON;
507
        if(modell_fliegt > 1000)  // wahrscheinlich in der Luft --> langsam absenken
508
            {
509
            GasMischanteil = EE_Parameter.NotGas;
510
            Notlandung = 1;
511
            PPM_diff[EE_Parameter.Kanalbelegung[K_NICK]] = 0;
512
            PPM_diff[EE_Parameter.Kanalbelegung[K_ROLL]] = 0;
513
            PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] = 0;
514
            PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] = 0;
515
            PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] = 0;
516
            }
517
         else MotorenEin = 0;
518
        }
519
        else
520
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
521
// Emfang gut
522
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
523
        if(SenderOkay > 140)
524
            {
525
            Notlandung = 0;
526
            RcLostTimer = EE_Parameter.NotGasZeit * 50;
527
            if(GasMischanteil > 40 && MotorenEin)
528
                {
529
                if(modell_fliegt < 0xffff) modell_fliegt++;
530
                }
531
            if((modell_fliegt < 256))
532
                {
533
                SummeNick = 0;
534
                SummeRoll = 0;
535
                if(modell_fliegt == 250)
536
                 {
537
                  NeueKompassRichtungMerken = 1;
538
                  sollGier = 0;
539
                  Mess_Integral_Gier = 0;
540
//                  Mess_Integral_Gier2 = 0;
541
                 }
542
                } else MikroKopterFlags |= FLAG_FLY;
543
 
544
            if((PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] > 80) && MotorenEin == 0)
545
                {
546
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
547
// auf Nullwerte kalibrieren
548
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
549
                if(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] > 75)  // Neutralwerte
550
                    {
551
                    if(++delay_neutral > 200)  // nicht sofort
552
                        {
553
                        GRN_OFF;
554
                        MotorenEin = 0;
555
                        delay_neutral = 0;
556
                        modell_fliegt = 0;
557
                        if(PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > 70 || abs(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]]) > 70)
558
                        {
559
                         unsigned char setting=1;
560
                         if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] > 70 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] < 70) setting = 1;
561
                         if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] > 70 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > 70) setting = 2;
562
                         if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] < 70 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > 70) setting = 3;
563
                         if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] <-70 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > 70) setting = 4;
564
                         if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] <-70 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] < 70) setting = 5;
565
                         SetActiveParamSetNumber(setting);  // aktiven Datensatz merken
566
                        }
567
//                        else
568
                         if(abs(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]]) < 30 && PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] < -70)
569
                          {
570
                           WinkelOut.CalcState = 1;
571
                           beeptime = 1000;
572
                          }
573
                          else
574
                          {
575
                               ReadParameterSet(GetActiveParamSetNumber(), (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
576
                           if((EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG))  // Höhenregelung aktiviert?
577
                            {
578
                             if((MessLuftdruck > 950) || (MessLuftdruck < 750)) SucheLuftruckOffset();
579
                            }
580
                           SetNeutral();
581
                           Piep(GetActiveParamSetNumber());
582
                         }
583
                        }
584
                    }
585
                 else
586
                if(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] < -75)  // ACC Neutralwerte speichern
587
                    {
588
                    if(++delay_neutral > 200)  // nicht sofort
589
                        {
590
                        GRN_OFF;
591
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_NICK],0xff); // Werte löschen
592
                        MotorenEin = 0;
593
                        delay_neutral = 0;
594
                        modell_fliegt = 0;
595
                        SetNeutral();
596
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_NICK],NeutralAccX / 256); // ACC-NeutralWerte speichern
597
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_NICK+1],NeutralAccX % 256); // ACC-NeutralWerte speichern
598
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_ROLL],NeutralAccY / 256);
599
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_ROLL+1],NeutralAccY % 256);
600
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_Z],(int)NeutralAccZ / 256);
601
                        eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACC_Z+1],(int)NeutralAccZ % 256);
602
                        Piep(GetActiveParamSetNumber());
603
                        }
604
                    }
605
                 else delay_neutral = 0;
606
                }
607
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
608
// Gas ist unten
609
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
610
            if(PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] < 35-120)
611
                {
612
                // Starten
613
                if(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] < -75)
614
                    {
615
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
616
// Einschalten
617
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
618
                    if(++delay_einschalten > 200)
619
                        {
620
                        delay_einschalten = 200;
621
                        modell_fliegt = 1;
622
                        MotorenEin = 1;
623
                        sollGier = 0;
624
                        Mess_Integral_Gier = 0;
625
                        Mess_Integral_Gier2 = 0;
626
                        Mess_IntegralNick = 0;
627
                        Mess_IntegralRoll = 0;
628
                        Mess_IntegralNick2 = IntegralNick;
629
                        Mess_IntegralRoll2 = IntegralRoll;
630
                        SummeNick = 0;
631
                        SummeRoll = 0;
632
                        MikroKopterFlags |= FLAG_START;
633
 
634
                        // Beim Einschalten automatisch kalibrieren
635
                        if( PARAM_CAL_ON_START ) {
636
                                if((EE_Parameter.GlobalConfig & CFG_HOEHENREGELUNG)) {
637
                                        if((MessLuftdruck > 950) || (MessLuftdruck < 750)) {
638
                                                SucheLuftruckOffset();
639
                                        }
640
                                }
641
 
642
                                SetNeutral();
643
                        }
644
                        }
645
                    }
646
                    else delay_einschalten = 0;
647
                //Auf Neutralwerte setzen
648
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
649
// Auschalten
650
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
651
                if(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]] > 75)
652
                    {
653
                    if(++delay_ausschalten > 200)  // nicht sofort
654
                        {
655
                        MotorenEin = 0;
656
                        delay_ausschalten = 200;
657
                        modell_fliegt = 0;
658
                        }
659
                    }
660
                else delay_ausschalten = 0;
661
                }
662
            }
663
 
664
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
665
// neue Werte von der Funke
666
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
667
 if(!NewPpmData-- || Notlandung) {
668
        static int chanNickPrev = 0;
669
        static int chanRollPrev = 0;
670
 
671
        static int stick_nick,stick_roll;
672
 
673
        ParameterZuordnung();
674
 
675
#define MAX_CHAN_VAL 125L
676
#define COS45        7071L              // cos( -45 ) * 10000
677
 
678
        long chanNick = PPM_in[EE_Parameter.Kanalbelegung[K_NICK]];
679
        long chanRoll = PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]];
680
 
681
        int  chanNickDiff;
682
        int  chanRollDiff;
683
 
684
        /* Über Parameter läßt sich zwischen "+" und "X" - Formations
685
         * umschalten (sh. parameter.h)
686
         */
687
        if( PARAM_X_FORMATION ) {
688
 
689
                chanRoll = -chanRoll;
690
 
691
                // Stick-Koordinatensystem um -45° (rechts) drehen
692
                chanNick *= COS45;
693
                chanRoll *= COS45;
694
 
695
                int chanNickTemp = ( chanNick - chanRoll ) / 10000L;
696
                int chanRollTemp = ( chanRoll + chanNick ) / 10000L;
697
 
698
                chanNick =  chanNickTemp;
699
                chanRoll = -chanRollTemp;
700
 
701
                if (chanNick >  MAX_CHAN_VAL)
702
                        chanNick =  MAX_CHAN_VAL;
703
                if (chanNick < -MAX_CHAN_VAL)
704
                        chanNick = -MAX_CHAN_VAL;
705
                if (chanRoll >  MAX_CHAN_VAL)
706
                        chanRoll =  MAX_CHAN_VAL;
707
                if (chanRoll < -MAX_CHAN_VAL)
708
                        chanRoll = -MAX_CHAN_VAL;      
709
        }
710
 
711
        chanNickDiff = ( ( chanNick - chanNickPrev ) / 3) * 3;
712
        chanRollDiff = ( ( chanRoll - chanRollPrev ) / 3) * 3;
713
 
714
        chanNickPrev = chanNick;
715
        chanRollPrev = chanRoll;
716
 
717
        stick_nick = (stick_nick * 3 + ( (int) chanNick ) * EE_Parameter.Stick_P) / 4;
718
        stick_nick += chanNickDiff * EE_Parameter.Stick_D;
719
        StickNick = stick_nick - GPS_Nick;
720
 
721
        stick_roll = (stick_roll * 3 + ( (int) chanRoll ) * EE_Parameter.Stick_P) / 4;
722
        stick_roll += chanRollDiff * EE_Parameter.Stick_D;
723
        StickRoll = stick_roll - GPS_Roll;
724
 
725
        StickGier = -PPM_in[EE_Parameter.Kanalbelegung[K_GIER]];
726
 
727
        // Gaswert übernehmen
728
        if( pitchNeutral() ) {
729
                StickGas = pitch();
730
        } else {
731
                StickGas  = PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] + 120;
732
        }
733
 
734
        GyroFaktor     = ((float)Parameter_Gyro_P + 10.0) / (256 / STICK_GAIN );
735
        IntegralFaktor = ((float) Parameter_Gyro_I) / (44000 / STICK_GAIN );
736
 
737
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
738
//+ Analoge Steuerung per Seriell
739
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
740
   if(ExternControl.Config & 0x01 && Parameter_ExternalControl > 128)
741
    {
742
         StickNick += (int) ExternControl.Nick * (int) EE_Parameter.Stick_P;
743
         StickRoll += (int) ExternControl.Roll * (int) EE_Parameter.Stick_P;
744
         StickGier += ExternControl.Gier;
745
     ExternHoehenValue =  (int) ExternControl.Hight * (int)EE_Parameter.Hoehe_Verstaerkung;
746
     if(ExternControl.Gas < StickGas) StickGas = ExternControl.Gas;
747
    }
748
    if(StickGas < 0) StickGas = 0;
749
 
750
    if(EE_Parameter.GlobalConfig & CFG_HEADING_HOLD) IntegralFaktor =  0;
751
    if(GyroFaktor < 0) GyroFaktor = 0;
752
    if(IntegralFaktor < 0) IntegralFaktor = 0;
753
 
754
    if(abs(StickNick/STICK_GAIN) > MaxStickNick)
755
     {
756
      MaxStickNick = abs(StickNick)/STICK_GAIN;
757
      if(MaxStickNick > 100) MaxStickNick = 100;
758
     }
759
     else MaxStickNick--;
760
    if(abs(StickRoll/STICK_GAIN) > MaxStickRoll)
761
     {
762
      MaxStickRoll = abs(StickRoll)/STICK_GAIN;
763
      if(MaxStickRoll > 100) MaxStickRoll = 100;
764
     }
765
     else MaxStickRoll--;
766
    if(Notlandung)  {MaxStickNick = 0; MaxStickRoll = 0;}
767
 
768
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
769
// Looping?
770
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
771
  if((PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] > EE_Parameter.LoopThreshold) && EE_Parameter.BitConfig & CFG_LOOP_LINKS)  Looping_Links = 1;
772
  else
773
   {
774
     {
775
      if((PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] < (EE_Parameter.LoopThreshold - EE_Parameter.LoopHysterese))) Looping_Links = 0;
776
     }
777
   }
778
  if((PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] < -EE_Parameter.LoopThreshold) && EE_Parameter.BitConfig & CFG_LOOP_RECHTS) Looping_Rechts = 1;
779
   else
780
   {
781
   if(Looping_Rechts) // Hysterese
782
     {
783
      if(PPM_in[EE_Parameter.Kanalbelegung[K_ROLL]] > -(EE_Parameter.LoopThreshold - EE_Parameter.LoopHysterese)) Looping_Rechts = 0;
784
     }
785
   }
786
 
787
  if((PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > EE_Parameter.LoopThreshold) && EE_Parameter.BitConfig & CFG_LOOP_OBEN) Looping_Oben = 1;
788
  else
789
   {
790
    if(Looping_Oben)  // Hysterese
791
     {
792
      if((PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] < (EE_Parameter.LoopThreshold - EE_Parameter.LoopHysterese))) Looping_Oben = 0;
793
     }
794
   }
795
  if((PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] < -EE_Parameter.LoopThreshold) && EE_Parameter.BitConfig & CFG_LOOP_UNTEN) Looping_Unten = 1;
796
   else
797
   {
798
    if(Looping_Unten) // Hysterese
799
     {
800
      if(PPM_in[EE_Parameter.Kanalbelegung[K_NICK]] > -(EE_Parameter.LoopThreshold - EE_Parameter.LoopHysterese)) Looping_Unten = 0;
801
     }
802
   }
803
 
804
   if(Looping_Links || Looping_Rechts)   Looping_Roll = 1; else Looping_Roll = 0;
805
   if(Looping_Oben  || Looping_Unten) {Looping_Nick = 1; Looping_Roll = 0; Looping_Links = 0; Looping_Rechts = 0;} else Looping_Nick = 0;
806
  } // Ende neue Funken-Werte
807
 
808
  if(Looping_Roll || Looping_Nick)
809
   {
810
    if(GasMischanteil > EE_Parameter.LoopGasLimit) GasMischanteil = EE_Parameter.LoopGasLimit;
811
   }
812
 
813
 
814
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
815
// Bei Empfangsausfall im Flug
816
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
817
   if(Notlandung)
818
    {
819
     StickGier = 0;
820
     StickNick = 0;
821
     StickRoll = 0;
822
     GyroFaktor     = (float) 100 / (256.0 / STICK_GAIN);
823
     IntegralFaktor = (float) 120 / (44000 / STICK_GAIN);
824
     Looping_Roll = 0;
825
     Looping_Nick = 0;
826
    }
827
 
828
 
829
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
830
// Integrale auf ACC-Signal abgleichen
831
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
832
#define ABGLEICH_ANZAHL 256L
833
 
834
 MittelIntegralNick  += IntegralNick;    // Für die Mittelwertbildung aufsummieren
835
 MittelIntegralRoll  += IntegralRoll;
836
 MittelIntegralNick2 += IntegralNick2;
837
 MittelIntegralRoll2 += IntegralRoll2;
838
 
839
 if(Looping_Nick || Looping_Roll)
840
  {
841
    IntegralAccNick = 0;
842
    IntegralAccRoll = 0;
843
    MittelIntegralNick = 0;
844
    MittelIntegralRoll = 0;
845
    MittelIntegralNick2 = 0;
846
    MittelIntegralRoll2 = 0;
847
    Mess_IntegralNick2 = Mess_IntegralNick;
848
    Mess_IntegralRoll2 = Mess_IntegralRoll;
849
    ZaehlMessungen = 0;
850
    LageKorrekturNick = 0;
851
    LageKorrekturRoll = 0;
852
  }
853
 
854
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
855
  if(!Looping_Nick && !Looping_Roll)
856
  {
857
   long tmp_long, tmp_long2;
858
   if(FromNaviCtrl_Value.Kalman_K != -1)
859
     {
860
      tmp_long = (long)(IntegralNick / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccNick);
861
      tmp_long2 = (long)(IntegralRoll / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccRoll);
862
      tmp_long  = (tmp_long  * FromNaviCtrl_Value.Kalman_K) / (32 * 16);
863
      tmp_long2 = (tmp_long2 * FromNaviCtrl_Value.Kalman_K) / (32 * 16);
864
     if((MaxStickNick > 64) || (MaxStickRoll > 64))
865
      {
866
      tmp_long  /= 2;
867
      tmp_long2 /= 2;
868
      }
869
     if(abs(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]]) > 25)
870
      {
871
      tmp_long  /= 3;
872
      tmp_long2 /= 3;
873
      }
874
      if(tmp_long >  (long) FromNaviCtrl_Value.Kalman_MaxFusion)  tmp_long  = (long) FromNaviCtrl_Value.Kalman_MaxFusion;
875
      if(tmp_long <  (long)-FromNaviCtrl_Value.Kalman_MaxFusion)  tmp_long  = (long)-FromNaviCtrl_Value.Kalman_MaxFusion;
876
      if(tmp_long2 > (long) FromNaviCtrl_Value.Kalman_MaxFusion)  tmp_long2 = (long) FromNaviCtrl_Value.Kalman_MaxFusion;
877
      if(tmp_long2 < (long)-FromNaviCtrl_Value.Kalman_MaxFusion)  tmp_long2 = (long)-FromNaviCtrl_Value.Kalman_MaxFusion;
878
     }
879
     else
880
     {
881
      tmp_long = (long)(IntegralNick / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccNick);
882
      tmp_long2 = (long)(IntegralRoll / EE_Parameter.GyroAccFaktor - (long)Mittelwert_AccRoll);
883
      tmp_long /= 16;
884
      tmp_long2 /= 16;
885
     if((MaxStickNick > 64) || (MaxStickRoll > 64))
886
      {
887
      tmp_long  /= 3;
888
      tmp_long2 /= 3;
889
      }
890
     if(abs(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]]) > 25)
891
      {
892
      tmp_long  /= 3;
893
      tmp_long2 /= 3;
894
      }
895
 #define AUSGLEICH 32
896
      if(tmp_long >  AUSGLEICH)  tmp_long  = AUSGLEICH;
897
      if(tmp_long < -AUSGLEICH)  tmp_long  =-AUSGLEICH;
898
      if(tmp_long2 > AUSGLEICH)  tmp_long2 = AUSGLEICH;
899
      if(tmp_long2 <-AUSGLEICH)  tmp_long2 =-AUSGLEICH;
900
     }
901
 
902
    Mess_IntegralNick -= tmp_long;
903
    Mess_IntegralRoll -= tmp_long2;
904
  }
905
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
906
 if(ZaehlMessungen >= ABGLEICH_ANZAHL)
907
 {
908
  static int cnt = 0;
909
  static char last_n_p,last_n_n,last_r_p,last_r_n;
910
  static long MittelIntegralNick_Alt,MittelIntegralRoll_Alt;
911
  if(!Looping_Nick && !Looping_Roll && !TrichterFlug)
912
  {
913
    MittelIntegralNick  /= ABGLEICH_ANZAHL;
914
    MittelIntegralRoll  /= ABGLEICH_ANZAHL;
915
        IntegralAccNick = (EE_Parameter.GyroAccFaktor * IntegralAccNick) / ABGLEICH_ANZAHL;
916
        IntegralAccRoll = (EE_Parameter.GyroAccFaktor * IntegralAccRoll) / ABGLEICH_ANZAHL;
917
    IntegralAccZ    = IntegralAccZ / ABGLEICH_ANZAHL;
918
#define MAX_I 0//(Poti2/10)
919
// Nick ++++++++++++++++++++++++++++++++++++++++++++++++
920
    IntegralFehlerNick = (long)(MittelIntegralNick - (long)IntegralAccNick);
921
    ausgleichNick = IntegralFehlerNick / EE_Parameter.GyroAccAbgleich;
922
// Roll ++++++++++++++++++++++++++++++++++++++++++++++++
923
    IntegralFehlerRoll = (long)(MittelIntegralRoll - (long)IntegralAccRoll);
924
    ausgleichRoll = IntegralFehlerRoll / EE_Parameter.GyroAccAbgleich;
925
 
926
    LageKorrekturNick = ausgleichNick / ABGLEICH_ANZAHL;
927
    LageKorrekturRoll = ausgleichRoll / ABGLEICH_ANZAHL;
928
 
929
   if(((MaxStickNick > 64) || (MaxStickRoll > 64) || (abs(PPM_in[EE_Parameter.Kanalbelegung[K_GIER]]) > 25)) && (FromNaviCtrl_Value.Kalman_K == -1))
930
    {
931
     LageKorrekturNick /= 2;
932
     LageKorrekturRoll /= 2;
933
    }
934
 
935
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
936
// Gyro-Drift ermitteln
937
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
938
    MittelIntegralNick2 /= ABGLEICH_ANZAHL;
939
    MittelIntegralRoll2 /= ABGLEICH_ANZAHL;
940
    tmp_long  = IntegralNick2 - IntegralNick;
941
    tmp_long2 = IntegralRoll2 - IntegralRoll;
942
    //DebugOut.Analog[25] = MittelIntegralRoll2 / 26;
943
 
944
    IntegralFehlerNick = tmp_long;
945
    IntegralFehlerRoll = tmp_long2;
946
    Mess_IntegralNick2 -= IntegralFehlerNick;
947
    Mess_IntegralRoll2 -= IntegralFehlerRoll;
948
 
949
//    IntegralFehlerNick = (IntegralFehlerNick * 1 + tmp_long) / 2;
950
//    IntegralFehlerRoll = (IntegralFehlerRoll * 1 + tmp_long2) / 2;
951
    if(GierGyroFehler > ABGLEICH_ANZAHL/2) { AdNeutralGier++; AdNeutralGierBias++; }
952
    if(GierGyroFehler <-ABGLEICH_ANZAHL/2) { AdNeutralGier--; AdNeutralGierBias--; }
953
 
954
DebugOut.Analog[22] = MittelIntegralRoll / 26;
955
//DebugOut.Analog[24] = GierGyroFehler;
956
    GierGyroFehler = 0;
957
 
958
 
959
/*DebugOut.Analog[17] = IntegralAccNick / 26;
960
DebugOut.Analog[18] = IntegralAccRoll / 26;
961
DebugOut.Analog[19] = IntegralFehlerNick;// / 26;
962
DebugOut.Analog[20] = IntegralFehlerRoll;// / 26;
963
*/
964
//DebugOut.Analog[21] = MittelIntegralNick / 26;
965
//MittelIntegralRoll = MittelIntegralRoll;
966
//DebugOut.Analog[28] = ausgleichNick;
967
/*
968
DebugOut.Analog[29] = ausgleichRoll;
969
DebugOut.Analog[30] = LageKorrekturRoll * 10;
970
*/
971
 
972
#define FEHLER_LIMIT  (ABGLEICH_ANZAHL * 4)
973
#define FEHLER_LIMIT2 (ABGLEICH_ANZAHL * 16)
974
#define BEWEGUNGS_LIMIT 20000
975
// Nick +++++++++++++++++++++++++++++++++++++++++++++++++
976
        cnt = 1;// + labs(IntegralFehlerNick) / 4096;
977
        if(labs(MittelIntegralNick_Alt - MittelIntegralNick) < BEWEGUNGS_LIMIT || (FromNaviCtrl_Value.Kalman_MaxDrift > 3*16))
978
        {
979
        if(IntegralFehlerNick >  FEHLER_LIMIT2)
980
         {
981
           if(last_n_p)
982
           {
983
            cnt += labs(IntegralFehlerNick) / FEHLER_LIMIT2;
984
            ausgleichNick = IntegralFehlerNick / 8;
985
            if(ausgleichNick > 5000) ausgleichNick = 5000;
986
            LageKorrekturNick += ausgleichNick / ABGLEICH_ANZAHL;
987
           }
988
           else last_n_p = 1;
989
         } else  last_n_p = 0;
990
        if(IntegralFehlerNick < -FEHLER_LIMIT2)
991
         {
992
           if(last_n_n)
993
            {
994
             cnt += labs(IntegralFehlerNick) / FEHLER_LIMIT2;
995
             ausgleichNick = IntegralFehlerNick / 8;
996
             if(ausgleichNick < -5000) ausgleichNick = -5000;
997
             LageKorrekturNick += ausgleichNick / ABGLEICH_ANZAHL;
998
            }
999
           else last_n_n = 1;
1000
         } else  last_n_n = 0;
1001
        }
1002
        else
1003
        {
1004
         cnt = 0;
1005
         KompassSignalSchlecht = 1000;
1006
        }
1007
        if(cnt > EE_Parameter.Driftkomp) cnt = EE_Parameter.Driftkomp;
1008
        if(cnt * 16 > FromNaviCtrl_Value.Kalman_MaxDrift) cnt = FromNaviCtrl_Value.Kalman_MaxDrift/16;
1009
        if(IntegralFehlerNick >  FEHLER_LIMIT)   AdNeutralNick += cnt;
1010
        if(IntegralFehlerNick < -FEHLER_LIMIT)   AdNeutralNick -= cnt;
1011
 
1012
// Roll +++++++++++++++++++++++++++++++++++++++++++++++++
1013
        cnt = 1;// + labs(IntegralFehlerNick) / 4096;
1014
 
1015
        ausgleichRoll = 0;
1016
        if(labs(MittelIntegralRoll_Alt - MittelIntegralRoll) < BEWEGUNGS_LIMIT || (FromNaviCtrl_Value.Kalman_MaxDrift > 3*16))
1017
        {
1018
        if(IntegralFehlerRoll >  FEHLER_LIMIT2)
1019
         {
1020
           if(last_r_p)
1021
           {
1022
            cnt += labs(IntegralFehlerRoll) / FEHLER_LIMIT2;
1023
            ausgleichRoll = IntegralFehlerRoll / 8;
1024
            if(ausgleichRoll > 5000) ausgleichRoll = 5000;
1025
            LageKorrekturRoll += ausgleichRoll / ABGLEICH_ANZAHL;
1026
           }
1027
           else last_r_p = 1;
1028
         } else  last_r_p = 0;
1029
        if(IntegralFehlerRoll < -FEHLER_LIMIT2)
1030
         {
1031
           if(last_r_n)
1032
           {
1033
            cnt += labs(IntegralFehlerRoll) / FEHLER_LIMIT2;
1034
            ausgleichRoll = IntegralFehlerRoll / 8;
1035
            if(ausgleichRoll < -5000) ausgleichRoll = -5000;
1036
            LageKorrekturRoll += ausgleichRoll / ABGLEICH_ANZAHL;
1037
           }
1038
           else last_r_n = 1;
1039
         } else  last_r_n = 0;
1040
        } else
1041
        {
1042
         cnt = 0;
1043
         KompassSignalSchlecht = 1000;
1044
        }
1045
        if(cnt > EE_Parameter.Driftkomp) cnt = EE_Parameter.Driftkomp;
1046
        if(cnt * 16 > FromNaviCtrl_Value.Kalman_MaxDrift) cnt = FromNaviCtrl_Value.Kalman_MaxDrift/16;
1047
        if(IntegralFehlerRoll >  FEHLER_LIMIT)   AdNeutralRoll += cnt;
1048
        if(IntegralFehlerRoll < -FEHLER_LIMIT)   AdNeutralRoll -= cnt;
1049
  }
1050
  else
1051
  {
1052
   LageKorrekturRoll = 0;
1053
   LageKorrekturNick = 0;
1054
   TrichterFlug = 0;
1055
  }
1056
 
1057
  if(!IntegralFaktor) { LageKorrekturRoll = 0; LageKorrekturNick = 0;} // z.B. bei HH
1058
// +++++++++++++++++++++++++++++++++++++++++++++++++++++
1059
   MittelIntegralNick_Alt = MittelIntegralNick;
1060
   MittelIntegralRoll_Alt = MittelIntegralRoll;
1061
// +++++++++++++++++++++++++++++++++++++++++++++++++++++
1062
    IntegralAccNick = 0;
1063
    IntegralAccRoll = 0;
1064
    IntegralAccZ = 0;
1065
    MittelIntegralNick = 0;
1066
    MittelIntegralRoll = 0;
1067
    MittelIntegralNick2 = 0;
1068
    MittelIntegralRoll2 = 0;
1069
    ZaehlMessungen = 0;
1070
 }
1071
//DebugOut.Analog[31] = StickRoll / (26*IntegralFaktor);
1072
 
1073
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1074
//  Gieren
1075
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1076
//    if(GasMischanteil < 35) { if(StickGier > 10) StickGier = 10; else if(StickGier < -10) StickGier = -10;};
1077
    if(abs(StickGier) > 15) // war 35
1078
     {
1079
      KompassSignalSchlecht = 1000;
1080
      if(!(EE_Parameter.GlobalConfig & CFG_KOMPASS_FIX))
1081
       {
1082
         NeueKompassRichtungMerken = 1;
1083
        };
1084
     }
1085
    tmp_int  = (long) EE_Parameter.Gier_P * ((long)StickGier * abs(StickGier)) / 512L; // expo  y = ax + bx²
1086
    tmp_int += (EE_Parameter.Gier_P * StickGier) / 4;
1087
    sollGier = tmp_int;
1088
    Mess_Integral_Gier -= tmp_int;
1089
    if(Mess_Integral_Gier > 50000) Mess_Integral_Gier = 50000;  // begrenzen
1090
    if(Mess_Integral_Gier <-50000) Mess_Integral_Gier =-50000;
1091
 
1092
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1093
//  Kompass
1094
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1095
//DebugOut.Analog[29] = (MaxStickNick + MaxStickRoll);
1096
 
1097
    if(KompassValue && (EE_Parameter.GlobalConfig & CFG_KOMPASS_AKTIV))
1098
     {
1099
       int w,v,r,fehler,korrektur;
1100
       w = abs(IntegralNick /512); // mit zunehmender Neigung den Einfluss drosseln
1101
       v = abs(IntegralRoll /512);
1102
       if(v > w) w = v; // grösste Neigung ermitteln
1103
       korrektur = w / 8 + 1;
1104
       fehler = ((540 + KompassValue - (ErsatzKompass/GIER_GRAD_FAKTOR)) % 360) - 180;
1105
           if(NeueKompassRichtungMerken)
1106
            {
1107
                 fehler = 0;
1108
                 ErsatzKompass = KompassValue * GIER_GRAD_FAKTOR;
1109
                }
1110
       if(!KompassSignalSchlecht && w < 25)
1111
        {
1112
        GierGyroFehler += fehler;
1113
        if(NeueKompassRichtungMerken)
1114
         {
1115
          beeptime = 200;
1116
//         KompassStartwert = KompassValue;
1117
          KompassStartwert = (ErsatzKompass/GIER_GRAD_FAKTOR);
1118
          NeueKompassRichtungMerken = 0;
1119
         }
1120
        }
1121
       ErsatzKompass += (fehler * 8) / korrektur;
1122
       w = (w * Parameter_KompassWirkung) / 32;           // auf die Wirkung normieren
1123
       w = Parameter_KompassWirkung - w;                  // Wirkung ggf drosseln
1124
       if(w >= 0)
1125
        {
1126
          if(!KompassSignalSchlecht)
1127
          {
1128
           v = 64 + ((MaxStickNick + MaxStickRoll)) / 8;
1129
           r = ((540 + (ErsatzKompass/GIER_GRAD_FAKTOR) - KompassStartwert) % 360) - 180;
1130
//           r = KompassRichtung;
1131
           v = (r * w) / v;  // nach Kompass ausrichten
1132
           w = 3 * Parameter_KompassWirkung;
1133
           if(v > w) v = w; // Begrenzen
1134
           else
1135
           if(v < -w) v = -w;
1136
           Mess_Integral_Gier += v;
1137
          }
1138
          if(KompassSignalSchlecht) KompassSignalSchlecht--;
1139
        }
1140
        else KompassSignalSchlecht = 500; // so lange das Signal taub stellen --> ca. 1 sek
1141
     }
1142
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1143
 
1144
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1145
//  Debugwerte zuordnen
1146
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1147
  if(!TimerWerteausgabe--)
1148
   {
1149
    TimerWerteausgabe = 24;
1150
 
1151
    DebugOut.Analog[0] = IntegralNick / EE_Parameter.GyroAccFaktor;
1152
    DebugOut.Analog[1] = IntegralRoll / EE_Parameter.GyroAccFaktor;
1153
    DebugOut.Analog[2] = Mittelwert_AccNick;
1154
    DebugOut.Analog[3] = Mittelwert_AccRoll;
1155
    DebugOut.Analog[4] = MesswertGier;
1156
    DebugOut.Analog[5] = HoehenWert;
1157
    DebugOut.Analog[6] = (Mess_Integral_Hoch / 512);
1158
    DebugOut.Analog[8] = KompassValue;
1159
    DebugOut.Analog[9] = UBat;
1160
    DebugOut.Analog[11] = ErsatzKompass / GIER_GRAD_FAKTOR;
1161
    DebugOut.Analog[10] = SenderOkay;
1162
    //DebugOut.Analog[16] = Mittelwert_AccHoch;
1163
    DebugOut.Analog[17] = FromNaviCtrl_Value.Distance;
1164
    DebugOut.Analog[18] = (int)FromNaviCtrl_Value.OsdBar;
1165
    DebugOut.Analog[19] = WinkelOut.CalcState;
1166
    DebugOut.Analog[20] = ServoValue;
1167
//    DebugOut.Analog[27] = (int)FromNaviCtrl_Value.Kalman_MaxDrift;
1168
//    DebugOut.Analog[29] = (int)FromNaviCtrl_Value.Kalman_K;
1169
//    DebugOut.Analog[30] = GPS_Nick;
1170
//    DebugOut.Analog[31] = GPS_Roll;
1171
 
1172
 
1173
//    DebugOut.Analog[19] -= DebugOut.Analog[19]/128;
1174
//    if(DebugOut.Analog[19] > 0) DebugOut.Analog[19]--; else DebugOut.Analog[19]++;
1175
 
1176
/*    DebugOut.Analog[16] = motor_rx[0];
1177
    DebugOut.Analog[17] = motor_rx[1];
1178
    DebugOut.Analog[18] = motor_rx[2];
1179
    DebugOut.Analog[19] = motor_rx[3];
1180
    DebugOut.Analog[20] = motor_rx[0] + motor_rx[1] + motor_rx[2] + motor_rx[3];
1181
    DebugOut.Analog[20] /= 14;
1182
    DebugOut.Analog[21] = motor_rx[4];
1183
    DebugOut.Analog[22] = motor_rx[5];
1184
    DebugOut.Analog[23] = motor_rx[6];
1185
    DebugOut.Analog[24] = motor_rx[7];
1186
    DebugOut.Analog[25] = motor_rx[4] + motor_rx[5] + motor_rx[6] + motor_rx[7];
1187
*/
1188
//    DebugOut.Analog[9] = MesswertNick;
1189
//    DebugOut.Analog[9] = SollHoehe;
1190
//    DebugOut.Analog[10] = Mess_Integral_Gier / 128;
1191
//    DebugOut.Analog[11] = KompassStartwert;
1192
//    DebugOut.Analog[10] = Parameter_Gyro_I;
1193
//    DebugOut.Analog[10] = EE_Parameter.Gyro_I;
1194
//    DebugOut.Analog[9] = KompassRichtung;
1195
//    DebugOut.Analog[10] = GasMischanteil;
1196
//    DebugOut.Analog[3] = HoeheD * 32;
1197
//    DebugOut.Analog[4] = hoehenregler;
1198
  }
1199
 
1200
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1201
//  Drehgeschwindigkeit und -winkel zu einem Istwert zusammenfassen
1202
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1203
 
1204
    if(Looping_Nick) MesswertNick = MesswertNick * GyroFaktor;
1205
    else             MesswertNick = IntegralNick * IntegralFaktor + MesswertNick * GyroFaktor;
1206
    if(Looping_Roll) MesswertRoll = MesswertRoll * GyroFaktor;
1207
    else             MesswertRoll = IntegralRoll * IntegralFaktor + MesswertRoll * GyroFaktor;
1208
    MesswertGier =   MesswertGier * (2 * GyroFaktor) + Integral_Gier * IntegralFaktor / 2;
1209
 
1210
    DebugOut.Analog[21] = MesswertNick;
1211
    DebugOut.Analog[22] = MesswertRoll;
1212
 
1213
    // Maximalwerte abfangen
1214
    #define MAX_SENSOR  (4096*STICK_GAIN)
1215
    if(MesswertNick >  MAX_SENSOR) MesswertNick =  MAX_SENSOR;
1216
    if(MesswertNick < -MAX_SENSOR) MesswertNick = -MAX_SENSOR;
1217
    if(MesswertRoll >  MAX_SENSOR) MesswertRoll =  MAX_SENSOR;
1218
    if(MesswertRoll < -MAX_SENSOR) MesswertRoll = -MAX_SENSOR;
1219
    if(MesswertGier >  MAX_SENSOR) MesswertGier =  MAX_SENSOR;
1220
    if(MesswertGier < -MAX_SENSOR) MesswertGier = -MAX_SENSOR;
1221
 
1222
        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                
1223
        // Gas-Mischanteil
1224
        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                
1225
 
1226
        // Zur besseren Auflösung hochskalieren
1227
        GasMischanteil *= STICK_GAIN;
1228
 
1229
        // Fehlerwert der Höhenregelung einmischen
1230
        GasMischanteil -= altitudeController();
1231
 
1232
        // Mindestens auf Minimalgas stellen
1233
        if( GasMischanteil < MIN_GAS )
1234
                GasMischanteil = MIN_GAS;
1235
 
1236
        // Begrenzung des Gasmischanteils auf MAX_GAS - 20 (Reserve für Motoren)
1237
        if( GasMischanteil > ( MAX_GAS - 20 ) * STICK_GAIN )
1238
                GasMischanteil = ( MAX_GAS - 20 ) * STICK_GAIN;
1239
 
1240
        DebugOut.Analog[7] = GasMischanteil;
1241
 
1242
        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                
1243
        // Gier-Anteil
1244
        // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                
1245
 
1246
    GierMischanteil = MesswertGier - ( sollGier * STICK_GAIN );     // Regler für Gier
1247
 
1248
        #define MIN_GIERGAS  ( 40 * STICK_GAIN )  // unter diesem Gaswert trotzdem Gieren
1249
 
1250
        // Reduzierten Gieranteil berechnen
1251
        if( GasMischanteil < MIN_GIERGAS ) {
1252
                GierMischanteil = ( GierMischanteil * GasMischanteil ) / MIN_GIERGAS;
1253
        }
1254
 
1255
        // Gieranteil darf nicht größer als der halbe Gasanteil sein
1256
        if( GierMischanteil >  ( GasMischanteil >> 1 ) )
1257
                GierMischanteil =    GasMischanteil >> 1;
1258
        if( GierMischanteil < -( GasMischanteil >> 1 ) )
1259
                GierMischanteil = -( GasMischanteil >> 1 );
1260
 
1261
    tmp_int = MAX_GAS * STICK_GAIN;
1262
 
1263
        // Gieranteil darf die Gasreserve nicht überschreiten
1264
    if( GierMischanteil >  ( ( tmp_int - GasMischanteil ) ) )
1265
                GierMischanteil =  ( ( tmp_int - GasMischanteil ) );
1266
    if( GierMischanteil < -( ( tmp_int - GasMischanteil ) ) )
1267
                GierMischanteil = -( ( tmp_int - GasMischanteil ) );
1268
 
1269
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1270
// Nick-Achse
1271
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1272
    DiffNick = MesswertNick - StickNick;        // Differenz bestimmen
1273
    if(IntegralFaktor) SummeNick += IntegralNick * IntegralFaktor - StickNick; // I-Anteil bei Winkelregelung
1274
    else  SummeNick += DiffNick; // I-Anteil bei HH
1275
    if(SummeNick >  (STICK_GAIN * 16000L)) SummeNick =  (STICK_GAIN * 16000L);
1276
    if(SummeNick < -(16000L * STICK_GAIN)) SummeNick = -(16000L * STICK_GAIN);
1277
    pd_ergebnis = DiffNick + Ki * SummeNick; // PI-Regler für Nick
1278
    // Motor Vorn
1279
    tmp_int = (long)((long)Parameter_DynamicStability * (long)(GasMischanteil + abs(GierMischanteil)/2)) / 64;
1280
    if(pd_ergebnis >  tmp_int) pd_ergebnis =  tmp_int;
1281
    if(pd_ergebnis < -tmp_int) pd_ergebnis = -tmp_int;
1282
 
1283
    motorwert = GasMischanteil + pd_ergebnis + GierMischanteil;   // Mischer
1284
    motorwert /= STICK_GAIN;
1285
        if ((motorwert < 0)) motorwert = 0;
1286
        else if(motorwert > MAX_GAS)        motorwert = MAX_GAS;
1287
        if (motorwert < MIN_GAS)            motorwert = MIN_GAS;
1288
        Motor_Vorne = motorwert;
1289
    // Motor Heck
1290
        motorwert = GasMischanteil - pd_ergebnis + GierMischanteil;
1291
    motorwert /= STICK_GAIN;
1292
        if ((motorwert < 0)) motorwert = 0;
1293
        else if(motorwert > MAX_GAS)        motorwert = MAX_GAS;
1294
        if (motorwert < MIN_GAS)            motorwert = MIN_GAS;
1295
        Motor_Hinten = motorwert;
1296
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1297
// Roll-Achse
1298
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1299
        DiffRoll = MesswertRoll - StickRoll;    // Differenz bestimmen
1300
    if(IntegralFaktor) SummeRoll += IntegralRoll * IntegralFaktor - StickRoll;// I-Anteil bei Winkelregelung
1301
    else                 SummeRoll += DiffRoll;  // I-Anteil bei HH
1302
    if(SummeRoll >  (STICK_GAIN * 16000L)) SummeRoll =  (STICK_GAIN * 16000L);
1303
    if(SummeRoll < -(16000L * STICK_GAIN)) SummeRoll = -(16000L * STICK_GAIN);
1304
    pd_ergebnis = DiffRoll + Ki * SummeRoll;    // PI-Regler für Roll
1305
    tmp_int = (long)((long)Parameter_DynamicStability * (long)(GasMischanteil + abs(GierMischanteil)/2)) / 64;
1306
    if(pd_ergebnis >  tmp_int) pd_ergebnis =  tmp_int;
1307
    if(pd_ergebnis < -tmp_int) pd_ergebnis = -tmp_int;
1308
    // Motor Links
1309
    motorwert = GasMischanteil + pd_ergebnis - GierMischanteil;
1310
    motorwert /= STICK_GAIN;
1311
        if ((motorwert < 0)) motorwert = 0;
1312
        else if(motorwert > MAX_GAS)            motorwert = MAX_GAS;
1313
        if (motorwert < MIN_GAS)            motorwert = MIN_GAS;
1314
    Motor_Links = motorwert;
1315
    // Motor Rechts
1316
        motorwert = GasMischanteil - pd_ergebnis - GierMischanteil;
1317
    motorwert /= STICK_GAIN;
1318
        if ((motorwert < 0)) motorwert = 0;
1319
        else if(motorwert > MAX_GAS)            motorwert = MAX_GAS;
1320
        if (motorwert < MIN_GAS)            motorwert = MIN_GAS;
1321
    Motor_Rechts = motorwert;
1322
   // +++++++++++++++++++++++++++++++++++++++++++++++
1323
}
1324