Subversion Repositories FlightCtrl

Rev

Rev 1141 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1134 thjac 1
/* pitch_neutral.c
2
 *
3
 * Copyright 2009 Thomas Jachmann
4
 */
5
 
6
#include "main.h"
7
#include "parameter.h"
8
#include "fc.h"
9
#include "altcon.h"
10
#include "pitch.h"
11
#include "pitch_neutral.h"
12
 
1141 thjac 13
#define STATE_INITIALIZE                0x00                    // Initialisierung nach Einschalten der Motoren
14
#define STATE_SETUP                     0x01                    // Kalibrierung des Gas-Sticks
15
#define STATE_SETUP1                    0x02                    //
16
#define STATE_BEGIN                     0x03                    // Startphase
17
#define STATE_BEGIN1                    0x04                    //
1134 thjac 18
#define STATE_INACTIVE                  0x05                    // Manuelle Kontrolle
19
#define STATE_WAIT                      0x06                    // Warten auf Einschalten der Höhenregelung
20
#define STATE_ACTIVATING                0x07                    // Aktivierung der Höhenregelung
21
#define STATE_ACTIVE                    0x08                    // Höhenregelung ist aktiv
22
 
23
 
24
static int      stickValue              = 0;                            // Aktueller Stick-Wert
25
static int      lastStickValue          = 0;                            // Vorheriger Stick-Wert
26
static int      pitchOffset             = 0;                            // Aktueller Grundgaswert in Neutralstellung
1141 thjac 27
static char     state;                                                  // Zustand
1134 thjac 28
static int      temp;
29
 
1141 thjac 30
char            pitchNeutralDiff        = 0;
31
 
32
 
1134 thjac 33
/* Wird verwendet, um das Umschalten auf automatische Höhenregelung
34
 * nach Erreichen der Neutralstellung zu verzögern.
35
 */
36
static int      pitchNeutralTimer       = PITCH_NEUTRAL_TIMER;
37
 
38
 
1141 thjac 39
 
1134 thjac 40
/*
41
 * Berechnet den aktuellen Pitch-Wert für die Regelung
42
 *
1141 thjac 43
 * Funktionsweise:
1134 thjac 44
 *
1141 thjac 45
 * 1. Vor Verwendung der Pitch-Steuerung muß ein Parameter für den Gas-Stick eingestellt werden. Hierzu
46
 *    bewegt man den Roll-Stick ganz nach außen und startet die Motoren. Man befindet sich im Setup-Modus
47
 *    und die Motoren laufen unabhängig vom Gas-Stick im Leerlauf. Im Display auf Seite 12 muß nun der
48
 *    beste Wert für "StickDiff" gefunden werden. Den Wert ändern kann man mit dem Roll-Stick. Man betätigt
49
 *    nun den Gas-Stick nach oben und läßt ihn los, so daß er in die Mittelstellung zurückspringt. Der
50
 *    optimale Wert sorgt dafür, daß das gewollte Loslassen von einer normalen Bewegung unterschieden wird.
51
 *    Jedesmal, wenn die SW das Loslassen als solches erkannt hat, ertönt ein Signal. Dieses darf jedoch
52
 *    nicht ertönen, wenn man den Stick mit normaler Geschwindigkeit in die Mittelstellung zurückbewegt.
53
 *    Wurde ein guter Wert eingestellt, verläßt man den Setup-Modus durch Ausschalten der Motoren. Der
54
 *    ermittelte Wert wird permanent im EEProm gespeichert und muß nicht neu ermittelt werden.
1134 thjac 55
 *
1141 thjac 56
 * 2. Nach dem Einschalten der FC wird die aktuelle Gas-Stick-Position gemerkt und als Kalibrierungswert
57
 *    für die Neutralstellung gespeichert. Somit spielt die korrekte Trimmung des Sticks auf Senderseite
58
 *    keine Rolle.
1134 thjac 59
 *
1141 thjac 60
 * 3. Nach Einschalten der Motoren geht der Stick in Neutralstellung. Diese Stick-Bewegung wird ignoriert
61
 *    und die Motoren drehen mit dem eingestellten MinGas2. Ausgehend von der Neutralstellung wird nun
62
 *    durch Bewegen des Sticks im oberen Bereich das Gas geregelt.
1134 thjac 63
 *
1141 thjac 64
 * 4. Das erstmalige Aktivieren der automatischen Höhenregelung erfolgt durch Loslassen des Sticks im
65
 *    Schwebeflug. Der zuvor aktuelle Stick-Wert wird als Wert in Neutralstellung übernommen und die
66
 *    automatische Höhenregelung sofort aktiviert. Wichtig hierfür ist die unter Punkt 1 vorgenommene
67
 *    Parameterfindung. Stimmt dieser Wert nicht, führt das zur Wegnahme des Gases und somit zum Sinken.
1134 thjac 68
 *
1141 thjac 69
 * 5. Sobald der Stick die Neutralstellung verläßt, wird die automatische Höhenregelung deaktiviert
70
 *    und der vorige Pitch-Wert als Wert der Neutralstellung übernommen. Der Pitch läßt sich nun
71
 *    über den gesamten Stick-Bereich regeln.
72
 *
73
 * 6. Erreicht der Stick ein weiteres Mal die Neutralstellung, wird die automatische Höhenregelung
74
 *    wieder aktiviert, jetzt jedoch immer mit einer zeitlichen Verzögerung. Nur so ist ein
75
 *    ungestörtes manuelles Steuern möglich.
76
 *
77
 * 7. Der Pitch-Wert ist innerhalb der Regelung durch ein konfigurierbares Minimalgas nach unten begrenzt.
78
 *    Dieses Minimalgas kann auf einen sehr niedrigen Wert eingestellt sein. Um im Flug nicht unterhalb
79
 *    eines Wertes zu gelangen, der die Lageregelung außer Funktion setzt, wird ein zweiter Wert für
80
 *    Minimalgas konfiguriert, der greift, sobald erstmalig die automatische Höhenregelung aktiviert wurde.
1134 thjac 81
 */
82
int pitch_neutral_value( void ) {
83
 
84
        int register pitchCount = 0;
85
 
1141 thjac 86
        // Sind die Motoren eingeschaltet? Ach ja, im Zustand STATE_SETUP sind die Motoren aus...
1134 thjac 87
        if( MotorenEin ) {
88
 
89
                // Vorigen Stick-Wert merken
90
                lastStickValue = stickValue;
91
 
92
                /* StickValue exponentiell angleichen, da ausgehend von der Neutralstellung
93
                 * nur jeweils die halbe Auflösung nach oben und unten zur Verfügung steht. Bei einer
94
                 * Multiplikation mit 2 ließe sich das Gas im Schwebebereich nicht fein genug einstellen. */
1141 thjac 95
                temp = PPM_in[ EE_Parameter.Kanalbelegung[ K_GAS ] ] - pitch_initialStickValue();
1134 thjac 96
                if( temp > 0 ) {
97
                        temp = temp + ( ( temp * temp ) / 150 );
98
                } else {
99
                        temp = temp - ( ( temp * temp ) / 150 );
100
                }
101
 
1141 thjac 102
                stickValue = temp;
103
 
1134 thjac 104
                /* Aktuellen Pitch-Wert berechnen. Der Wert ergibt sich aus dem Pitch-Offset
105
                 * zuzüglich dem Stick-Wert. */
106
                pitchCount = stickValue + pitchOffset;
107
 
108
                switch( state ) {
1141 thjac 109
 
110
                        /* Entscheidet über Flugbetrieb oder Setup-Betrieb. Für den Setup-Betrieb
111
                         * muß beim Einschalten der Motoren gleichzeitig der Roll-Stick ganz
112
                         * betätigt werden (Richtung ist egal).
113
                         */
114
                        case STATE_INITIALIZE:
115
 
116
                                if( abs( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] ) > 70 ) {
117
                                        state = STATE_SETUP;
118
                                } else {
119
                                        state = STATE_BEGIN;
120
                                }
121
                                break;
122
 
123
                        case STATE_SETUP:
124
                                if( stickValue < PARAM_PITCH_STICK_THRESHOLD &&
125
                                    abs( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] ) < PARAM_PITCH_STICK_THRESHOLD ) {
126
                                        state = STATE_SETUP1;
127
                                }
128
 
129
                                // Im Setup immer mit Leerlaufgas
130
                                pitchCount = 0;
131
 
132
                                break;
133
 
134
                        case STATE_SETUP1:
135
 
136
                                // Roll-Stick nach links
137
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] < -20 ) {
138
                                        if( pitchNeutralDiff < 20 ) {
139
                                                pitchNeutralDiff++;
140
 
141
                                                // Konfiguration dauerhaft speichern
142
                                                eeprom_write_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ], pitchNeutralDiff );
143
 
144
                                                // Signalisieren
145
                                                beeptime = 500;
146
 
147
                                                state    = STATE_SETUP;
148
                                        }
149
                                }
150
 
151
                                // Roll-Stick nach rechts
152
                                if( PPM_in[ EE_Parameter.Kanalbelegung[ K_ROLL ] ] > 20 ) {
153
                                        if( pitchNeutralDiff > 0 ) {
154
                                                pitchNeutralDiff--;
155
 
156
                                                // Konfiguration dauerhaft speichern
157
                                                eeprom_write_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ], pitchNeutralDiff );
158
 
159
                                                // Signalisieren
160
                                                beeptime = 500;
161
 
162
                                                state    = STATE_SETUP;
163
                                        }
164
                                }
165
 
166
                                if( ( lastStickValue > PARAM_PITCH_STICK_THRESHOLD ) &&
167
                                    ( lastStickValue - stickValue >= pitchNeutralDiff ) ) {
168
 
169
                                        state    = STATE_SETUP;
170
 
171
                                        // Signalisieren
172
                                        beeptime = 500;
173
                                }
174
 
175
                                // Im Setup immer mit Leerlaufgas
176
                                pitchCount = 0;
177
 
178
                                break;
179
 
1134 thjac 180
                        case STATE_BEGIN:
181
 
182
                                // Schnelles Bewegen aus dem oberen Bereich des Sticks in Neutralstellung
183
                                if( ( lastStickValue > PARAM_PITCH_STICK_THRESHOLD ) &&
1141 thjac 184
                                    ( lastStickValue - stickValue >= pitchNeutralDiff ) ) {
1134 thjac 185
 
186
                                        pitchOffset       = lastStickValue;
187
 
1141 thjac 188
                                        state             = STATE_BEGIN1;
1134 thjac 189
                                        pitchNeutralTimer = PITCH_NEUTRAL_TIMER;
190
                                }
191
                                break;
192
 
1141 thjac 193
                        case STATE_BEGIN1:
1134 thjac 194
 
195
                                // Während der Initialisierung das Gas konstant halten
196
                                pitchCount = pitchOffset;
197
 
198
                                pitchNeutralTimer--;
199
 
200
                                /* Läuft der Timer ab, bevor der Stick die Neutralstellung erreicht,
201
                                 * wird die Aktion nicht als "schnelles Bewegen in Neutralstellung"
202
                                 * gedeutet. */
203
                                if( !pitchNeutralTimer ) {
204
                                        pitchOffset = 0;
205
                                        state       = STATE_BEGIN;
206
                                }
207
 
208
                                // Ist die Neutralstellung erreicht?
209
                                if( abs( stickValue ) <= PARAM_PITCH_STICK_THRESHOLD ) {
1141 thjac 210
                                        state = STATE_ACTIVATING;
1134 thjac 211
                                }
212
                                break;
213
 
214
                        /* Die Höhenregelung ist per Konfiguration aktiviert, jedoch befindet
215
                         * sich der Stick außerhalb des als Neutralstellung anerkannten
216
                         * Wertebereiches. Es wird manuell geregelt. */
217
                        case STATE_INACTIVE:
218
 
219
                                // Ist ein Restart zulässig?
220
                                if( PARAM_PITCH_RESTART_ENABLED ) {
221
 
222
                                        /* Wenn der Gashebel ganz unten steht, Timer für Reduzierung des Minimalgaswertes
223
                                         * starten. Hierfür wird die Variable pitchNeutralTimer verwendet. */
224
                                        if( PPM_in[ EE_Parameter.Kanalbelegung[ K_GAS ] ] > 35 - 120 ) {
225
                                                pitchNeutralTimer = PITCH_MIN2_TIMER;
226
                                        } else {
227
                                                pitchNeutralTimer--;
228
 
229
                                                /* Gashebel steht seit PITCH_MIN2_TIMER ganz unten; jetzt erfolgt die Initialisierung. */
230
                                                if( !pitchNeutralTimer ) {
231
                                                        state       = STATE_BEGIN;
232
                                                        pitchOffset = 0;
233
 
234
                                                        // Signalisieren
235
                                                        beeptime    = 500;
236
                                                }
237
                                        }
238
                                }
239
 
240
                                // Min2-Gas einstellen für Lageregelung bei Minimalgas
241
                                if( pitchCount < PARAM_PITCH_MIN2 ) {
242
                                        pitchCount = PARAM_PITCH_MIN2;
243
                                }
244
 
245
                                // Stick ist innerhalb der Neutralstellung
246
                                if( abs( stickValue ) < PARAM_PITCH_STICK_THRESHOLD ) {
247
 
248
                                        // Timer neu setzen
249
                                        pitchNeutralTimer = PITCH_NEUTRAL_TIMER;
250
                                        state             = STATE_WAIT;
251
                                }
252
                                break;
253
 
254
                        /* Der Stick ist in den für die Neutralstellung gültigen Wertebereich
255
                         * gelangt. Nun darf innerhalb einer bestimmten Zeit keine Stick-Bewegung
256
                         * erfolgen, um die automatische Höhenregelung zu aktivieren. */
257
                        case STATE_WAIT:
258
 
259
                                /* Stick ist innerhalb der Neutralstellung und
260
                                   Stick-Differenzial ist < 2 */
261
                                if( abs( stickValue ) < PARAM_PITCH_STICK_THRESHOLD &&
262
                                    lastStickValue == stickValue ) {
263
 
264
                                        pitchNeutralTimer--;
265
 
266
                                        if( !pitchNeutralTimer ) {
267
                                                state = STATE_ACTIVATING;
268
                                        }
269
 
270
                                // Aktivierungskriterium nicht erfüllt, zurück in INACTIVE
271
                                } else {
272
                                        state = STATE_INACTIVE;
273
                                }
274
                                break;
275
 
276
                        /* Die automatische Höhenregelung wird jetzt aktiviert. Der aktuelle
277
                         * Luftdruck wird gespeichert und notwendige Werte für den Regler
278
                         * werden initialisiert. */
279
                        case STATE_ACTIVATING:
280
 
281
                                // Höhenregler starten
282
                                altcon_start();
283
 
284
                                state = STATE_ACTIVE;
285
 
286
                                break;
287
 
288
                        /* Die automatische Höhenregelung ist aktiv. */                
289
                        case STATE_ACTIVE:
290
 
291
                                // Stick ist außerhalb der Neutralstellung
292
                                if( abs( stickValue ) > PARAM_PITCH_STICK_THRESHOLD ) {
293
                                        pitchOffset -= altcon_avgerror() / 4;
294
                                        pitchCount   = stickValue + pitchOffset;
295
 
296
                                        // Höhenregler abschalten
297
                                        altcon_stop();
298
 
299
                                        state        = STATE_INACTIVE;
300
                                }
301
                                break;
302
                }
303
 
304
        // Motoren sind aus
305
        } else {
306
 
307
                /* Nach dem Einschalten der Motoren darf pitchOffset keinen hohen Wert haben,
308
                 * da der Kopter sonst sofort hochschießen würde.
309
                 */
310
                pitchCount  = 0;
311
                pitchOffset = 0;
312
                stickValue  = 0;
1141 thjac 313
                state       = STATE_INITIALIZE;
1134 thjac 314
        }
315
 
316
        if( pitchOffset < 0 )
317
                pitchOffset = 0;
318
 
319
        // Pitch-Wert darf nicht < 0 sein
320
        if( pitchCount < 0 ) {
321
                pitchCount = 0;
322
        }
323
 
324
        // pitchCount als Debug-Wert rausschreiben
325
        DebugOut.Analog[26] = stickValue;
326
        DebugOut.Analog[28] = pitchCount;
327
        DebugOut.Analog[29] = pitchOffset;
328
 
329
        return pitchCount;
330
}
1157 krheinwald 331
 
332
void pitch_neutral_init( void ) {
333
 
334
        printf("\r\npitch_mk_init()");
335
 
336
        pitchNeutralDiff = eeprom_read_byte( &EEPromArray[ EEPROM_ADR_PITCH_NEUTRAL_DIFF ] );
337
 
338
        pitchValueFP = pitch_neutral_value;
339
}
340