Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1263 thjac 1
/* pitch_md.c
2
 *
3
 * Copyright 2009 Thomas Jachmann
4
 *
5
 * Die in dieser Quelldatei enthaltenen Algorithmen ermöglichen eine MD-ähnliche Pitch-Steuerung
6
 * für den MK.
7
 */
8
 
9
#include "main.h"
10
#include "parameter.h"
11
#include "fc.h"
12
#include "pitch.h"
13
#include "altcon.h"
14
 
15
 
16
#define STATE_INITIALIZE                0x01                    // Anfangszustand nach Einschalten der Motoren
17
#define STATE_SETUP                     0x02                    // Ermittlung von PARAM_PITCH_MD_HOVER
18
#define STATE_SETUP_HOVER               0x03                    // Konfiguration pitchHover
19
#define STATE_SETUP_STICK_DELTA         0x04                    // Konfiguration pitchNeutralDiff
20
#define STATE_SETUP_STICK_DELTA1        0x05
21
#define STATE_BEGIN                     0x06                    // Anfangszustand für Flugbetrieb
22
#define STATE_BEGIN1                    0x07                    // Anfangszustand für Flugbetrieb
23
#define STATE_READY0                    0x08                    // Manuelle Kontrolle
24
#define STATE_READY                     0x09                    // Manuelle Kontrolle
25
#define STATE_READY1                    0x0a
26
#define STATE_WAIT                      0x0b                    // Warten auf Einschalten der Höhenregelung
27
#define STATE_ACTIVATING                0x0c                    // Aktivierung der Höhenregelung
28
#define STATE_ACTIVE                    0x0d                    // Höhenregelung ist aktiv
29
#define STATE_RESTART                   0x0e                    // Neustart
30
#define STATE_AUTOSTART0                0x0f                    // Autostartsequenz 0
31
#define STATE_AUTOSTART1                0x10                    // Autostartsequenz 1
32
 
33
 
34
static int      lastStickValue          = 0;                    // Vorheriger Stick-Wert
35
static int      actualPitchCount        = 0;                    // Soll-Pitch-Wert
36
static int      targetPitchCount        = 0;                    // Ist-Pitch-Wert
37
static int      pitchOffset;                                    // Aktueller Grundgaswert in Neutralstellung
38
static char     state;                                          // Zustand
39
static int      timer;
40
static int      delay                   = 0;
41
static int      delayCounter            = 0;
42
static int      peakPitchCount;
43
unsigned char   pitchHover              = 0;                    // Schwebegaswert
44
unsigned char   pitchStand              = 0;                    // Standgaswert
45
unsigned char   pitchNeutralDiff        = 0;
46
 
47
 
48
void pitch_md_init( void ) {
49
 
50
    pitchHover       = eeprom_read_byte( &EEPromArray[ EEPROM_ADR_PITCH_MD_HOVER ] );
51
    pitchStand       = pitchHover * PARAM_PITCH_HOVER_PERCENT / 100;
52
 
53
    pitchNeutralDiff = eeprom_read_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ] );
54
}
55
 
56
 
57
/*
58
 * Berechnet den aktuellen Pitch-Wert für die Regelung
59
 *
60
 * Funktionsweise:
61
 *
62
 * 1. Einmalig muß man das Schwebegas einstellen. Schwebegas ist ein neuer Parameter.
63
 *    Dies tut man durch Betätigen des Roll-Sticks nach links (Vollausschlag) und
64
 *    Starten der Motoren. Nun gibt man soviel Gas (in der oberen Hälfte des Stick-Bereichs), bis der MK
65
 *    kurz über dem Boden schwebt (im Bodeneffekt). Man hält diese Stick-Position solange, bis ein
66
 *    Signal ertönt (ca. 1 Sekunde). Das Signal ist die Bestätigung für die Übernahme des aktuellen Gaswertes
67
 *    als Schwebegas. Der Wert wird dauerhaft gespeichert und kann im LCD-Display des MK-Tool im letzten Bild
68
 *    überprüft werden. Diese Kalibrierung muß mit vollem Akku und nach jeder Gewichtsänderung des MK einmal
69
 *    durchgeführt werden.
70
 *
71
 * 2. Für den Flug startet man die Motoren und läßt den Stick los. Die Motoren laufen im Leerlaufgas.
72
 *
73
 * 3. Man kann nun entweder mit oder ohne Unterstützung der Höhenregelung fliegen.
74
 *
75
 * Mit Unterstützung geht man wie folgt vor:
76
 *
77
 *    Die Startsequenz wird durch Betätigung des Gasknüppels nach oben eingeleitet, bis ein akustisches Signal ertönt.
78
 *    Hierbei drehen die Motoren noch im Leerlauf. Erst nach Rückstellung des Sticks in die Mittelposition beschleunigen
79
 *    die Motoren langsam bis zum unter Punkt 1 eingestellten Schwebegas. Nun schaltet automatisch die Höhenregelung zu
80
 *    und der MK steigt bis auf eine im UserParameter eingestellte Höhe (normalerweise 1 Meter). In Mittelstellung ist
81
 *    nun die Höhenregelung aktiv, im oberen und unteren Stick-Bereich steigt oder sinkt der MK.
82
 *
83
 * Ohne Unterstützung geht man wie folgt vor:
84
 *
85
 *    Man schaltet die Motoren durch Betätigung des Gasknüppels nach oben in das Standgas. Hier reicht ein kurzes Antippen
86
 *    des Sticks. Als Standgas wird 70% des unter Punkt 1 eingestellten Schwebegaswertes angenommen. Nun kann man
87
 *    manuell gesteuert durch Ausnutzung nur der oberen Hälfte des Stick-Bereichs fliegen. Dies entspricht der herkömmlichen
88
 *    Steuerung. Da nur der halbe Stick-Weg zur Verfügung steht, ist der Stick-Weg um die Mittelstellung herum höher aufgelöst.
89
 *    So kann das Gas trotzdem einigermaßen fein gesteuert werden.
90
 *  
91
 * 4. Nach der Landung drückt man den Stick ganz nach unten, bis ein Signal ertönt. Jetzt laufen die Motoren
92
 *    wieder im Leerlaufgas. Man kann nun neu Starten (ab Punkt 3) oder die Motoren ausschalten.
93
 */
94
int pitch_md_value( void ) {
95
 
96
        int register rawStickValue = PPM_in[ EE_Parameter.Kanalbelegung[ K_GAS ] ] - pitch_initialStickValue();
97
        int register stickValue;
98
 
99
        // Sind die Motoren eingeschaltet?
100
        if( MotorenEin ) {
101
 
102
                /* StickValue exponentiell angleichen, da ausgehend von der Neutralstellung
103
                 * nur jeweils die halbe Auflösung nach oben und unten zur Verfügung steht. Bei einer
104
                 * Multiplikation mit 2 ließe sich das Gas im Schwebebereich nicht fein genug einstellen. */
105
                if( rawStickValue > 0 ) {
106
                        stickValue = rawStickValue + ( ( (long) rawStickValue * (long) rawStickValue ) / 150L );
107
                } else {
108
                        stickValue = rawStickValue - ( ( (long) rawStickValue * (long) rawStickValue ) / 150L );
109
                }
110
 
111
                /* Aktuellen Pitch-Wert berechnen. Der Wert ergibt sich aus dem Pitch-Offset
112
                 * zuzüglich dem Stick-Wert. Die folgenden Bedingungen erzeugen einen toten Bereich
113
                 * um die Mittelstellung herum, in dem sich targetPitchCount nicht ändert. So wird
114
                 * ein sanfterer Übergang vom höhengeregelten in den manuell gesteuerten Flug erreicht.
115
                 */
116
                if( stickValue > PARAM_PITCH_STICK_THRESHOLD )
117
                        targetPitchCount = stickValue - PARAM_PITCH_STICK_THRESHOLD + pitchOffset;
118
                else if( stickValue < -PARAM_PITCH_STICK_THRESHOLD )
119
                        targetPitchCount = stickValue + PARAM_PITCH_STICK_THRESHOLD + pitchOffset;
120
                else
121
                        targetPitchCount = pitchOffset;
122
 
123
                switch( state ) {
124
 
125
                        /* Entscheidet über Flugbetrieb oder Setup-Betrieb. Für den Setup-Betrieb
126
                         * muß beim Einschalten der Motoren gleichzeitig der Roll-Stick ganz
127
                         * betätigt werden. Es gilt:
128
                         *
129
                         * Roll-Stick links:  Einstellen des Gas-Stick-Deltas
130
                         * Roll-Stick rechts: Einstellen des Schwebegases
131
                         */
132
                        case STATE_INITIALIZE:
133
 
134
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] > 70 ) {
135
                                        state = STATE_SETUP_HOVER;
136
 
137
                                        // Signalisieren
138
                                        beeptime = 500;
139
 
140
                                } else if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] < -70 ) {
141
                                        state = STATE_SETUP_STICK_DELTA;
142
 
143
                                        // Signalisieren
144
                                        beeptime = 500;
145
 
146
                                } else {
147
                                        state = STATE_RESTART;
148
                                }
149
                                break;
150
 
151
                        /* Erlaubt die Ermittlung des Parameters pitchHover. Hierzu wird soviel Gas
152
                         * gegeben, bis der MK kurz vor dem Abheben ist, jedoch noch stabil steht. Um den
153
                         * Gaswert dauerhaft zu speichern, muß der Stick an der Position verweilen, bis
154
                         * der Summer die Übernahme akustisch quittiert. Dann müssen die Motoren wieder
155
                         * ausgeschaltet werden, da dieser Modus nicht für den Flug vorgesehen ist.
156
                         */            
157
                        case STATE_SETUP_HOVER:
158
 
159
                                // Im Setup-Modus soll das Gas spontan reagieren
160
                                actualPitchCount = targetPitchCount;
161
 
162
                                if( rawStickValue < 10 || abs( stickValue - lastStickValue ) > 1 ) {
163
                                        timer = PARAM_TIMER_1S;
164
                                }
165
 
166
                                /* Der Stick befindet sich eindeutig in der oberen Hälfte und wurde
167
                                 * seit dem letzten Zyklus nicht bewegt. */
168
                                else {
169
                                        timer--;
170
 
171
                                        /* Die Verweilzeit ist abgelaufen und der aktuelle Pitch-Wert
172
                                         * entspricht nicht dem bereits gespeicherten Wert. */
173
                                        if( !timer && ( pitchHover != actualPitchCount ) ) {
174
 
175
                                                // Aktuellen Pitch-Wert in Konfiguration übernehmen
176
                                                pitchHover = actualPitchCount;
177
 
178
                                                // Konfiguration dauerhaft speichern
179
                                                eeprom_write_byte( &EEPromArray[ EEPROM_ADR_PITCH_MD_HOVER ], pitchHover );
180
 
181
                                                // Signalisieren
182
                                                beeptime = 500;
183
                                        }
184
                                }
185
                                break;
186
 
187
                        /* Der Stick-Deltawert kann hier konfiguriert werden. Ein Betätigen des Roll-Sticks nach links
188
                         * erhöht den Deltawert um 1, ein Betätigen nach rechts veringert den Wert um 1. Der eingestellte
189
                         * Wert kann mit dem Gas-Stick getestet werden, indem dieser in den oberen Bereich bewegt und dann
190
                         * losgelassen wird. Ertönt dabei ein Signal, wurde die Bewegung erkannt. Es ist dann der richtige
191
                         * Wert gefunden, wenn das Signal beim Loslassen des Gas-Sticks ertönt, beim gesteuerten Bewegen nach
192
                         * unten jedoch nicht. Durch Ausschalten der Motoren (diese laufen während der Konfiguration nicht
193
                         * wirklich) wird der Konfigurationsmodus beendet.
194
                         */
195
                        case STATE_SETUP_STICK_DELTA:
196
                                if( stickValue < PARAM_PITCH_STICK_THRESHOLD &&
197
                                    abs( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] ) < PARAM_PITCH_STICK_THRESHOLD ) {
198
                                        state = STATE_SETUP_STICK_DELTA1;
199
                                }
200
 
201
                                // Im Setup immer mit Leerlaufgas
202
                                targetPitchCount = 0;
203
 
204
                                break;
205
 
206
                        case STATE_SETUP_STICK_DELTA1:
207
 
208
                                // Roll-Stick nach links erhöht den Deltawert
209
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] < -20 ) {
210
                                        if( pitchNeutralDiff < 20 ) {
211
                                                pitchNeutralDiff++;
212
 
213
                                                // Konfiguration dauerhaft speichern
214
                                                eeprom_write_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ], pitchNeutralDiff );
215
 
216
                                                // Signalisieren
217
                                                beeptime = 500;
218
 
219
                                                state    = STATE_SETUP_STICK_DELTA;
220
                                        }
221
                                }
222
 
223
                                // Roll-Stick nach rechts verringert den Deltawert
224
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] > 20 ) {
225
                                        if( pitchNeutralDiff > 0 ) {
226
                                                pitchNeutralDiff--;
227
 
228
                                                // Konfiguration dauerhaft speichern
229
                                                eeprom_write_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ], pitchNeutralDiff );
230
 
231
                                                // Signalisieren
232
                                                beeptime = 500;
233
 
234
                                                state    = STATE_SETUP_STICK_DELTA;
235
                                        }
236
                                }
237
 
238
                                if( ( lastStickValue > PARAM_PITCH_STICK_THRESHOLD ) &&
239
                                    ( lastStickValue - stickValue >= pitchNeutralDiff ) ) {
240
 
241
                                        state    = STATE_SETUP_STICK_DELTA;
242
 
243
                                        // Signalisieren
244
                                        beeptime = 500;
245
                                }
246
 
247
                                // Im Setup immer mit Leerlaufgas
248
                                targetPitchCount = 0;
249
 
250
                                break;
251
 
252
                        /* In diesem Zustand steht der MK am Boden und die Motoren laufen auf Leerlaufgas. Ein
253
                         * kurzes Auslenken des Sticks nach oben schaltet in das Standgas über.
254
                         */
255
                        case STATE_BEGIN:
256
 
257
                                // Stick ist oberhalb der Neutralstellung
258
                                if( rawStickValue > PARAM_PITCH_STICK_THRESHOLD ) {
259
                                        pitchOffset = pitchStand;
260
 
261
                                        // Vollausschlag bedeutet: Einleitung der Autostartsequenz
262
                                        if( rawStickValue > 80 ) {
263
                                                state = STATE_AUTOSTART0;
264
 
265
                                                // Signalisieren
266
                                                beeptime = 500;
267
                                        }
268
 
269
                                        /* In diesem Zustand darf Standgas nicht überschritten werden, damit
270
                                         * der MK nicht aus diesem Status heraus abhebt.
271
                                         */
272
                                        if( targetPitchCount > pitchStand ) {
273
                                                targetPitchCount = pitchStand;
274
                                        }
275
 
276
                                // Erst im Status weitergehen, wenn Stick nicht mehr oberhalb der Neutralstellung
277
                                } else if( pitchOffset == pitchStand ) {
278
                                        state = STATE_BEGIN1;
279
                                }
280
 
281
                                break;
282
 
283
                        // MK soll erst abheben, weil sonst die Höhenregelung am Boden schon greift
284
                        case STATE_BEGIN1:
285
 
286
                                // Jetzt kann abgehoben werden
287
                                if( rawStickValue > PARAM_PITCH_STICK_THRESHOLD ) {
288
 
289
                                        // Begrenzung der Pitch-Beschleunigung nach dem Start
290
                                        delay = PARAM_PITCH_MD_DELAY1;
291
 
292
                                        state = STATE_READY0;
293
 
294
                                // Knüppel unterhalb der Neutralstellung bewirkt einen sofortigen Neustart
295
                                } else if( rawStickValue < -PARAM_PITCH_STICK_THRESHOLD ) {
296
 
297
                                        state = STATE_RESTART;
298
                                }
299
 
300
                                break;
301
 
302
                        /* Automatischer Start: Warten, bis Standgas erreicht ist, dann auf Schwebegas gehen und
303
                         * die Sollhöhe setzen.
304
                         */
305
                        case STATE_AUTOSTART0:
306
 
307
                                // Standgas darf in diesem Zustand nicht überschritten werden
308
                                if( targetPitchCount > pitchStand ) {
309
                                        targetPitchCount = pitchStand;
310
                                }
311
 
312
                                if( rawStickValue < PARAM_PITCH_STICK_THRESHOLD ) {
313
 
314
                                        // Knüppel unterhalb der Neutralstellung bewirkt einen sofortigen Neustart
315
                                        if( rawStickValue < -PARAM_PITCH_STICK_THRESHOLD ) {
316
                                                state = STATE_RESTART;
317
                                        }
318
 
319
                                        // Standgas muß erreicht sein, bevor die Startsequenz weiterläuft
320
                                        if( targetPitchCount >= pitchStand ) {
321
 
322
                                                // Jetzt auf Schwebegas übergehen (etwas mehr als eingestellt)
323
                                                pitchOffset = pitchHover;
324
 
325
                                                delay = PARAM_PITCH_MD_DELAY_AUTOSTART;
326
 
327
                                                // Einstellen der zu erreichenden Flughöhe über Grund
328
                                                altcon_lock();
329
                                                altcon_inc( PARAM_PITCH_AUTOSTART_ALT );
330
                                                altcon_start();
331
 
332
                                                state = STATE_AUTOSTART1;
333
                                        }
334
                                }
335
 
336
                                // Begrenzung der Pitch-Beschleunigung beim Autostart
337
                                delay = PARAM_PITCH_MD_DELAY_AUTOSTART;
338
 
339
                                break;
340
 
341
                        /* Wenn das Schwebegas erreicht wurde, kann davon ausgegangen werden, daß der MK
342
                         * nicht mehr am Boden steht.
343
                         */
344
                        case STATE_AUTOSTART1:
345
 
346
                                if( targetPitchCount >= pitchHover ) {
347
                                        delay = PARAM_PITCH_MD_DELAY2;
348
                                        state = STATE_ACTIVATING;
349
 
350
                                        // Signalisieren
351
                                        beeptime = 500;
352
                                }
353
 
354
                                // Eine Bewegung des Gasknüppels bricht die Autostartsequenz ab
355
                                if( abs( rawStickValue ) > PARAM_PITCH_STICK_THRESHOLD ) {
356
 
357
                                        // Höhenregler deaktivieren
358
                                        altcon_stop();
359
 
360
                                        pitchOffset     -= altcon_avgerror() / 4;
361
                                        targetPitchCount = pitchOffset;
362
                                        state            = STATE_READY;
363
                                }
364
 
365
                                break;
366
 
367
                        /* Die Motoren laufen jetzt mindestens mit Standgas. Der MK ist bereit zum Abheben.
368
                         */
369
                        case STATE_READY0:
370
 
371
                                /* Wenn der Gashebel ganz unten steht, Timer für Restart der Pitch-Regelung
372
                                 * starten. Hierfür wird die Variable pitchNeutralTimer verwendet. */
373
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_GAS ] ] > 35 - 120 ) {
374
                                        timer = PITCH_MIN2_TIMER;
375
                                } else {
376
                                        timer--;
377
 
378
                                        /* Gashebel steht seit PITCH_MIN2_TIMER ganz unten; jetzt erfolgt die Initialisierung. */
379
                                        if( !timer ) {
380
                                                state = STATE_RESTART;
381
                                        }
382
                                }
383
 
384
                                /* Übergang in den höhengeregelten Flug durch:
385
                                 * 1. Schnelles Bewegen des Sticks in Richtung Mittelstellung
386
                                 *    oder
387
                                 * 2. langsames Bewegen des Sticks in Mittelstellung */
388
                                if( ( ( lastStickValue > PARAM_PITCH_STICK_THRESHOLD ) &&
389
                                      ( lastStickValue - stickValue >= pitchNeutralDiff ) ) ||
390
                                    ( ( lastStickValue < PARAM_PITCH_STICK_THRESHOLD ) &&
391
                                        PARAM_PITCH_SOFT_ACTIVATING ) ) {
392
 
393
                                        // Aktuelle Höhe festhalten (aktiviert noch nicht den Regler)
394
                                        altcon_lock();
395
 
396
                                        // Höhe vorübergehend merken und beibehalten
397
                                        peakPitchCount = lastStickValue;
398
 
399
                                        state          = STATE_READY1;
400
                                        timer          = PITCH_NEUTRAL_TIMER;
401
                                        delay          = PARAM_PITCH_MD_DELAY2;
402
                                }
403
 
404
                                break;
405
 
406
                        case STATE_READY:
407
 
408
                                /* Wenn der Gashebel ganz unten steht, Timer für Restart der Pitch-Regelung
409
                                 * starten. Hierfür wird die Variable pitchNeutralTimer verwendet. */
410
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_GAS ] ] > 35 - 120 ) {
411
                                        timer = PITCH_MIN2_TIMER;
412
                                } else {
413
                                        timer--;
414
 
415
                                        /* Gashebel steht seit PITCH_MIN2_TIMER ganz unten; jetzt erfolgt die Initialisierung. */
416
                                        if( !timer ) {
417
                                                state = STATE_RESTART;
418
                                        }
419
                                }
420
 
421
                                // Stick ist innerhalb der Neutralstellung
422
                                if( abs( rawStickValue ) < PARAM_PITCH_STICK_THRESHOLD ) {
423
 
424
                                        // Aktuelle Höhe festhalten (aktiviert noch nicht den Regler)
425
                                        altcon_lock();
426
 
427
                                        // Timer neu setzen
428
                                        timer = PITCH_NEUTRAL_TIMER;
429
 
430
                                        state = STATE_WAIT;
431
                                }
432
                                break;
433
 
434
                        /* Hier wird die Zeit gemessen, in der der Stick nach dem Loslassen
435
                         * bis zur Neutralstellung benötigt. Bei Überschreiten der Zeit
436
                         * wird die Höhenregelung nicht aktiviert.
437
                         */
438
                        case STATE_READY1:
439
 
440
                                // Gas wird konstant gehalten
441
                                targetPitchCount = peakPitchCount + pitchOffset;
442
 
443
                                timer--;
444
 
445
                                /* Läuft der Timer ab, bevor der Stick die Neutralstellung erreicht,
446
                                 * wird die Aktion nicht als "schnelles Bewegen in Neutralstellung"
447
                                 * gedeutet. */
448
 
449
                                if( !timer ) {
450
                                        state = STATE_READY0;
451
                                }
452
 
453
                                // Ist die Neutralstellung erreicht?
454
                                if( rawStickValue < PARAM_PITCH_STICK_THRESHOLD ) {
455
 
456
                                        pitchOffset = targetPitchCount;
457
 
458
                                        // Aktivierung des Höhenreglers mit der zuvor gemerkten Sollhöhe
459
                                        altcon_start();
460
 
461
                                        // Signalisieren
462
                                        beeptime = 500;
463
 
464
                                        state = STATE_ACTIVE;
465
                                }
466
                                break;
467
 
468
                        /* Der Stick ist in den für die Neutralstellung gültigen Wertebereich
469
                         * gelangt. Nun darf innerhalb einer bestimmten Zeit keine Stick-Bewegung
470
                         * erfolgen, um die automatische Höhenregelung zu aktivieren. */
471
                        case STATE_WAIT:
472
 
473
                                /* Stick ist innerhalb der Neutralstellung und
474
                                   Stick-Differenzial ist < 2 */
475
                                if( abs( rawStickValue ) < PARAM_PITCH_STICK_THRESHOLD &&
476
                                    abs( stickValue - lastStickValue ) < 2 ) {
477
 
478
                                        timer--;
479
 
480
                                        if( !timer ) {
481
                                                state = STATE_ACTIVATING;
482
                                        }
483
 
484
                                // Aktivierungskriterium nicht erfüllt, zurück in INACTIVE
485
                                } else {
486
                                        state = STATE_READY;
487
                                }
488
                                break;
489
 
490
                        /* Die automatische Höhenregelung wird jetzt aktiviert.
491
                         */
492
                        case STATE_ACTIVATING:
493
 
494
                                /* Nach Aktivierung der Höhenregelung soll sich der Gaswert nicht mehr
495
                                 * ändern. */
496
                                actualPitchCount = targetPitchCount;
497
                                pitchOffset      = targetPitchCount;
498
 
499
                                // Aktivierung des Höhenreglers mit der zuvor gemerkten Sollhöhe
500
                                altcon_start();
501
 
502
                                // Einschalten der Höhenregelung signalisieren
503
                                beeptime = 500;
504
 
505
                                state = STATE_ACTIVE;
506
                                break;
507
 
508
                        /* Die automatische Höhenregelung ist aktiv. */                
509
                        case STATE_ACTIVE:
510
 
511
                                targetPitchCount = pitchOffset;
512
 
513
                                // Stick ist außerhalb der Neutralstellung
514
                                if( abs( rawStickValue ) > PARAM_PITCH_STICK_THRESHOLD ) {
515
 
516
                                        // Höhenregler deaktivieren
517
                                        altcon_stop();
518
 
519
                                        // Ausschalten der Höhenregelung signalisieren
520
                                        beeptime = 500;
521
 
522
                                        pitchOffset     -= altcon_avgerror() / 4;
523
                                        targetPitchCount = pitchOffset;
524
                                        state            = STATE_READY;
525
                                }
526
                                break;
527
 
528
                        /* Neustart nach dem Flug oder vor Start. */
529
                        case STATE_RESTART:
530
 
531
                                // Begrenzung der Pitch-Beschleunigung am Boden
532
                                delay = PARAM_PITCH_MD_DELAY0;
533
 
534
                                pitchOffset      = 0;
535
                                targetPitchCount = 0;
536
 
537
                                // Folgezustand
538
                                state = STATE_BEGIN;
539
 
540
                                break;
541
                }
542
 
543
        // Motoren sind aus
544
        } else {
545
 
546
                /* Nach dem Einschalten der Motoren wird pitchOffset auf PARAM_PITCH_OVER gesetzt.
547
                 */
548
                actualPitchCount = 0;
549
                targetPitchCount = 0;
550
                pitchOffset      = 0;
551
                stickValue       = 0;
552
                state            = STATE_INITIALIZE;
553
        }
554
 
555
        /* Durch die Sollwertvorgabe kann hier eine einstellbare Trägheit auf dem Pitch-Wert
556
         * abgebildet werden. */
557
        int pitchDelta = targetPitchCount - actualPitchCount;
558
 
559
        if( pitchDelta > delay )
560
                pitchDelta = delay;
561
        if( pitchDelta < -delay )
562
                pitchDelta = -delay;
563
 
564
        if( !delayCounter ) {
565
                actualPitchCount += pitchDelta;
566
                delayCounter      = 5;
567
        }
568
 
569
        delayCounter--;
570
 
571
        if( actualPitchCount < 0 )
572
                actualPitchCount = 0;
573
 
574
        // Vorigen Stick-Wert merken
575
        lastStickValue = stickValue;
576
 
577
        DebugOut.Analog[25] = pitchOffset;
578
        DebugOut.Analog[26] = stickValue;
579
 
580
        return actualPitchCount;
581
}