Subversion Repositories FlightCtrl

Rev

Rev 838 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 838 Rev 966
Line 37... Line 37...
37
extern int Theta45;
37
extern int Theta45;
38
extern int Phi45;
38
extern int Phi45;
Line 39... Line 39...
39
 
39
 
40
typedef struct
40
typedef struct
41
{
41
{
42
        uint8_t STATE;
42
  uint8_t STATE;
43
        uint16_t DRDY;
43
  uint16_t DRDY;
44
        uint8_t AXIS;
44
  uint8_t AXIS;
45
        int16_t x_axis;
45
  int16_t x_axis;
46
        int16_t y_axis;
46
  int16_t y_axis;
47
        int16_t z_axis;
47
  int16_t z_axis;
Line 48... Line 48...
48
} MM3_working_t;
48
} MM3_working_t;
49
 
49
 
50
 
50
 
51
// MM3 State Machine
51
// MM3 State Machine
52
#define MM3_STATE_RESET                         0
52
#define MM3_STATE_RESET           0
53
#define MM3_STATE_START_TRANSFER        1
53
#define MM3_STATE_START_TRANSFER  1
54
#define MM3_STATE_WAIT_DRDY                     2
54
#define MM3_STATE_WAIT_DRDY       2
55
#define MM3_STATE_DRDY                          3
55
#define MM3_STATE_DRDY            3
56
#define MM3_STATE_BYTE2                         4
56
#define MM3_STATE_BYTE2           4
57
 
57
 
58
#define MM3_X_AXIS              0x01
58
#define MM3_X_AXIS  0x01
59
#define MM3_Y_AXIS              0x02
59
#define MM3_Y_AXIS  0x02
60
#define MM3_Z_AXIS              0x03
60
#define MM3_Z_AXIS  0x03
61
 
61
 
62
 
62
 
63
#define MM3_PERIOD_32   0x00
63
#define MM3_PERIOD_32   0x00
64
#define MM3_PERIOD_64   0x10
64
#define MM3_PERIOD_64   0x10
65
#define MM3_PERIOD_128  0x20
65
#define MM3_PERIOD_128  0x20
66
#define MM3_PERIOD_256  0x30
66
#define MM3_PERIOD_256  0x30
67
#define MM3_PERIOD_512  0x40
67
#define MM3_PERIOD_512  0x40
Line 68... Line 68...
68
#define MM3_PERIOD_1024 0x50
68
#define MM3_PERIOD_1024 0x50
Line 76... Line 76...
76
/***************************************************/
76
/***************************************************/
77
/*       Read Parameter from EEPROM as byte        */
77
/*       Read Parameter from EEPROM as byte        */
78
/***************************************************/
78
/***************************************************/
79
uint8_t GetParamByte(uint8_t param_id)
79
uint8_t GetParamByte(uint8_t param_id)
80
{
80
{
81
        return eeprom_read_byte(&EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id]);
81
  return eeprom_read_byte(&EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id]);
82
}
82
}
Line 83... Line 83...
83
 
83
 
84
/***************************************************/
84
/***************************************************/
85
/*       Write Parameter to EEPROM as byte         */
85
/*       Write Parameter to EEPROM as byte         */
86
/***************************************************/
86
/***************************************************/
87
void SetParamByte(uint8_t param_id, uint8_t value)
87
void SetParamByte(uint8_t param_id, uint8_t value)
88
{
88
{
89
        eeprom_write_byte(&EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id], value);
89
  eeprom_write_byte(&EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id], value);
Line 90... Line 90...
90
}
90
}
91
 
91
 
92
/***************************************************/
92
/***************************************************/
93
/*       Read Parameter from EEPROM as word        */
93
/*       Read Parameter from EEPROM as word        */
94
/***************************************************/
94
/***************************************************/
95
uint16_t GetParamWord(uint8_t param_id)
95
uint16_t GetParamWord(uint8_t param_id)
96
{
96
{
Line 97... Line 97...
97
        return eeprom_read_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id]);
97
  return eeprom_read_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id]);
98
}
98
}
99
 
99
 
100
/***************************************************/
100
/***************************************************/
101
/*       Write Parameter to EEPROM as word         */
101
/*       Write Parameter to EEPROM as word         */
102
/***************************************************/
102
/***************************************************/
103
void SetParamWord(uint8_t param_id, uint16_t value)
103
void SetParamWord(uint8_t param_id, uint16_t value)
Line 104... Line 104...
104
{
104
{
105
        eeprom_write_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id], value);
105
  eeprom_write_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id], value);
106
}
106
}
107
 
107
 
108
/*********************************************/
108
/*********************************************/
109
/*  Initialize Interface to MM3 Compass      */
109
/*  Initialize Interface to MM3 Compass      */
110
/*********************************************/
110
/*********************************************/
111
void MM3_Init(void)
111
void MM3_Init(void)
112
{
112
{
113
        uint8_t sreg = SREG;
113
  uint8_t sreg = SREG;
114
 
114
 
115
        cli();
115
  cli();
116
 
116
 
117
        // Configure Pins for SPI
117
  // Configure Pins for SPI
118
        // set SCK (PB7), MOSI (PB5) as output
118
  // set SCK (PB7), MOSI (PB5) as output
119
        DDRB |= (1<<DDB7)|(1<<DDB5);
119
  DDRB |= (1<<DDB7)|(1<<DDB5);
120
        // set MISO (PB6) as input
120
  // set MISO (PB6) as input
121
        DDRB &= ~(1<<DDB6);
121
  DDRB &= ~(1<<DDB6);
122
 
122
 
123
        // Output Pins PC4->MM3_SS ,PC5->MM3_RESET
123
  // Output Pins PC4->MM3_SS ,PC5->MM3_RESET
124
        DDRC |= (1<<DDC4)|(1<<DDC5);
124
  DDRC |= (1<<DDC4)|(1<<DDC5);
125
        // set pins permanent to low
125
  // set pins permanent to low
126
        PORTC &= ~((1<<PORTC4)|(1<<PORTC5));
126
  PORTC &= ~((1<<PORTC4)|(1<<PORTC5));
127
 
127
 
128
        // Initialize SPI-Interface
128
  // Initialize SPI-Interface
129
        // Enable interrupt (SPIE=1)
129
  // Enable interrupt (SPIE=1)
130
        // Enable SPI bus (SPE=1)
130
  // Enable SPI bus (SPE=1)
131
        // MSB transmitted first (DORD = 0)
131
  // MSB transmitted first (DORD = 0)
132
        // Master SPI Mode (MSTR=1)
132
  // Master SPI Mode (MSTR=1)
133
        // Clock polarity low when idle (CPOL=0)
133
  // Clock polarity low when idle (CPOL=0)
134
        // Clock phase sample at leading edge (CPHA=0)
134
  // Clock phase sample at leading edge (CPHA=0)
135
        // Clock rate = SYSCLK/128 (SPI2X=0, SPR1=1, SPR0=1) 20MHz/128 = 156.25kHz
135
  // Clock rate = SYSCLK/128 (SPI2X=0, SPR1=1, SPR0=1) 20MHz/128 = 156.25kHz
136
        SPCR = (1<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(1<<SPR1)|(1<<SPR0);
136
  SPCR = (1<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(1<<SPR1)|(1<<SPR0);
137
        SPSR &= ~(1<<SPI2X);
137
  SPSR &= ~(1<<SPI2X);
138
 
138
 
139
    // Init Statemachine
139
  // Init Statemachine
140
        MM3.AXIS = MM3_X_AXIS;
140
  MM3.AXIS = MM3_X_AXIS;
141
        MM3.STATE = MM3_STATE_RESET;
141
  MM3.STATE = MM3_STATE_RESET;
142
 
142
 
143
        // Read calibration from EEprom
143
  // Read calibration from EEprom
144
        MM3_calib.X_off = (int16_t)GetParamWord(PID_MM3_X_OFF);
144
  MM3_calib.X_off = (int16_t)GetParamWord(PID_MM3_X_OFF);
145
        MM3_calib.Y_off = (int16_t)GetParamWord(PID_MM3_Y_OFF);
145
  MM3_calib.Y_off = (int16_t)GetParamWord(PID_MM3_Y_OFF);
146
        MM3_calib.Z_off = (int16_t)GetParamWord(PID_MM3_Z_OFF);
146
  MM3_calib.Z_off = (int16_t)GetParamWord(PID_MM3_Z_OFF);
147
        MM3_calib.X_range = (int16_t)GetParamWord(PID_MM3_X_RANGE);
147
  MM3_calib.X_range = (int16_t)GetParamWord(PID_MM3_X_RANGE);
148
        MM3_calib.Y_range = (int16_t)GetParamWord(PID_MM3_Y_RANGE);
148
  MM3_calib.Y_range = (int16_t)GetParamWord(PID_MM3_Y_RANGE);
149
        MM3_calib.Z_range = (int16_t)GetParamWord(PID_MM3_Z_RANGE);
149
  MM3_calib.Z_range = (int16_t)GetParamWord(PID_MM3_Z_RANGE);
150
 
150
 
Line 151... Line 151...
151
        MM3_Timeout = 0;
151
  MM3_Timeout = 0;
152
 
152
 
153
        SREG = sreg;
153
  SREG = sreg;
154
}
154
}
155
 
155
 
156
/*********************************************/
156
/*********************************************/
157
/*  Get Data from MM3                        */
157
/*  Get Data from MM3                        */
158
/*********************************************/
158
/*********************************************/
159
void MM3_Update(void) // called every 102.4 µs by timer 0 ISR
159
void MM3_Update(void) // called every 102.4 µs by timer 0 ISR
160
{
160
{
161
        switch (MM3.STATE)
161
  switch (MM3.STATE)
162
        {
162
  {
163
        case MM3_STATE_RESET:
163
  case MM3_STATE_RESET:
164
                PORTC &= ~(1<<PORTC4); // select slave
164
    PORTC &= ~(1<<PORTC4); // select slave
165
                PORTC |= (1<<PORTC5);   // PC5 to High, MM3 Reset
165
    PORTC |= (1<<PORTC5);       // PC5 to High, MM3 Reset
166
                MM3.STATE = MM3_STATE_START_TRANSFER;
166
    MM3.STATE = MM3_STATE_START_TRANSFER;
167
                return;
167
    return;
168
 
168
   
169
        case MM3_STATE_START_TRANSFER:
169
  case MM3_STATE_START_TRANSFER:
170
                PORTC &= ~(1<<PORTC5);  // PC4 auf Low (was 102.4 µs at high level)
170
    PORTC &= ~(1<<PORTC5);      // PC4 auf Low (was 102.4 µs at high level)
171
                // write to SPDR triggers automatically the transfer MOSI MISO
171
    // write to SPDR triggers automatically the transfer MOSI MISO
172
                // MM3 Period, + AXIS code
172
    // MM3 Period, + AXIS code
173
                switch(MM3.AXIS)
173
    switch(MM3.AXIS)
174
                {
174
    {
175
                case MM3_X_AXIS:
175
    case MM3_X_AXIS:
176
                        SPDR = MM3_PERIOD_256 + MM3_X_AXIS;
176
      SPDR = MM3_PERIOD_256 + MM3_X_AXIS;
177
                        break;
177
      break;
178
                case MM3_Y_AXIS:
178
    case MM3_Y_AXIS:
179
                        SPDR = MM3_PERIOD_256 + MM3_Y_AXIS;
179
      SPDR = MM3_PERIOD_256 + MM3_Y_AXIS;
180
                        break;
180
      break;
181
                case MM3_Z_AXIS:
181
    case MM3_Z_AXIS:
182
            SPDR = MM3_PERIOD_256 + MM3_Z_AXIS;
182
      SPDR = MM3_PERIOD_256 + MM3_Z_AXIS;
183
                        break;
183
      break;
184
                default:
184
    default:
185
                        MM3.AXIS = MM3_X_AXIS;
185
      MM3.AXIS = MM3_X_AXIS;
186
                        MM3.STATE = MM3_STATE_RESET;
186
      MM3.STATE = MM3_STATE_RESET;
187
                        return;
187
      return;
188
                }
188
    }
189
 
189
   
190
                // DRDY line is not connected, therefore
190
    // DRDY line is not connected, therefore
191
                // wait before reading data back
191
    // wait before reading data back
192
                MM3.DRDY = SetDelay(8); // wait 8ms for data ready
192
    MM3.DRDY = SetDelay(8); // wait 8ms for data ready
193
                MM3.STATE = MM3_STATE_WAIT_DRDY;
193
    MM3.STATE = MM3_STATE_WAIT_DRDY;
194
                return;
194
    return;
195
 
195
   
196
        case MM3_STATE_WAIT_DRDY:
196
    case MM3_STATE_WAIT_DRDY:
197
                if (CheckDelay(MM3.DRDY))
197
      if (CheckDelay(MM3.DRDY))
198
                {
198
      {
199
                        // write something into SPDR to trigger data reading
199
        // write something into SPDR to trigger data reading
200
                        SPDR = 0x00;
200
        SPDR = 0x00;
Line 201... Line 201...
201
                        MM3.STATE = MM3_STATE_DRDY;
201
        MM3.STATE = MM3_STATE_DRDY;
202
                }
202
      }
203
                return;
203
      return;
204
        }
204
  }
205
}
205
}
206
 
206
 
207
/*********************************************/
207
/*********************************************/
208
/*  Interrupt SPI transfer complete          */
208
/*  Interrupt SPI transfer complete          */
209
/*********************************************/
209
/*********************************************/
210
ISR(SPI_STC_vect)
210
ISR(SPI_STC_vect)
211
{
211
{
212
        static int8_t tmp;
212
  static int8_t tmp;
213
        int16_t value;
213
  int16_t value;
214
 
214
 
215
        switch (MM3.STATE)
215
  switch (MM3.STATE)
216
        {
216
  {
217
        // 1st byte received
217
    // 1st byte received
218
        case MM3_STATE_DRDY:
218
  case MM3_STATE_DRDY:
219
                tmp = SPDR;     // store 1st byte
219
    tmp = SPDR;     // store 1st byte
220
                SPDR = 0x00;    // trigger transfer of 2nd byte
220
    SPDR = 0x00;        // trigger transfer of 2nd byte
221
                MM3.STATE = MM3_STATE_BYTE2;
221
    MM3.STATE = MM3_STATE_BYTE2;
222
                return;
222
    return;
223
 
223
   
224
        case MM3_STATE_BYTE2:           // 2nd byte received
224
  case MM3_STATE_BYTE2:         // 2nd byte received
225
                value = (int16_t)tmp;   // combine the 1st and 2nd byte to a word
225
    value = (int16_t)tmp;       // combine the 1st and 2nd byte to a word
226
                value <<= 8;            // shift 1st byte to MSB-Position
226
    value <<= 8;                // shift 1st byte to MSB-Position
227
                value |= (int16_t)SPDR; // add 2nd byte
227
    value |= (int16_t)SPDR;     // add 2nd byte
228
 
228
   
229
                if(abs(value) < MAX_AXIS_VALUE)         // ignore spikes
229
    if(abs(value) < MAX_AXIS_VALUE)             // ignore spikes
230
                {
230
    {
231
                        switch (MM3.AXIS)
231
      switch (MM3.AXIS)
232
                        {
232
      {
233
                        case MM3_X_AXIS:
233
      case MM3_X_AXIS:
234
                                MM3.x_axis = value;
234
        MM3.x_axis = value;
235
                                MM3.AXIS = MM3_Y_AXIS;
235
        MM3.AXIS = MM3_Y_AXIS;
236
                                break;
236
        break;
237
                        case MM3_Y_AXIS:
237
      case MM3_Y_AXIS:
238
                                MM3.y_axis = value;
238
        MM3.y_axis = value;
239
                                MM3.AXIS = MM3_Z_AXIS;
239
        MM3.AXIS = MM3_Z_AXIS;
240
                                break;
240
        break;
241
                        case MM3_Z_AXIS:
241
      case MM3_Z_AXIS:
242
                                MM3.z_axis = value;
242
        MM3.z_axis = value;
243
                                MM3.AXIS = MM3_X_AXIS;
243
        MM3.AXIS = MM3_X_AXIS;
244
                                break;
244
        break;
245
                        default:
245
      default:
246
                                MM3.AXIS = MM3_X_AXIS;
246
        MM3.AXIS = MM3_X_AXIS;
247
                                break;
247
        break;
248
                        }
248
      }
249
                }
249
    }
250
       
250
   
251
                PORTC |= (1<<PORTC4); // deselect slave
251
    PORTC |= (1<<PORTC4); // deselect slave
252
                MM3.STATE = MM3_STATE_RESET;
252
    MM3.STATE = MM3_STATE_RESET;
253
                // Update timeout is called every 102.4 µs.
253
    // Update timeout is called every 102.4 µs.
254
                // It takes 2 cycles to write a measurement data request for one axis and
254
    // It takes 2 cycles to write a measurement data request for one axis and
255
                // at at least 8 ms / 102.4 µs = 79 cycles to read the requested data back.
255
    // at at least 8 ms / 102.4 µs = 79 cycles to read the requested data back.
256
                // I.e. 81 cycles * 102.4 µs = 8.3ms per axis.
256
    // I.e. 81 cycles * 102.4 µs = 8.3ms per axis.
257
                // The two function accessing the MM3 Data - MM3_Calibrate() and MM3_Heading() -
257
    // The two function accessing the MM3 Data - MM3_Calibrate() and MM3_Heading() -
258
                // decremtent the MM3_Timeout every 100 ms.
258
    // decremtent the MM3_Timeout every 100 ms.
259
                // incrementing the counter by 1 every 8.3 ms is sufficient to avoid a timeout.
259
    // incrementing the counter by 1 every 8.3 ms is sufficient to avoid a timeout.
260
                if ((MM3.x_axis != MM3.y_axis) || (MM3.x_axis != MM3.z_axis) || (MM3.y_axis != MM3.z_axis))
260
    if ((MM3.x_axis != MM3.y_axis) || (MM3.x_axis != MM3.z_axis) || (MM3.y_axis != MM3.z_axis))
261
                {       // if all axis measurements give diffrent readings the data should be valid
261
    {   // if all axis measurements give diffrent readings the data should be valid
262
                        if(MM3_Timeout < 20) MM3_Timeout++;
262
      if(MM3_Timeout < 20) MM3_Timeout++;
263
                }
263
    }
264
                else // something is very strange here
264
    else // something is very strange here
265
                {
265
    {
266
                        if(MM3_Timeout ) MM3_Timeout--;
266
      if(MM3_Timeout ) MM3_Timeout--;
267
                }
267
    }
Line 268... Line 268...
268
                return;
268
    return;
269
 
269
   
270
        default:
270
  default:
271
                return;
271
    return;
272
        }
272
  }
273
}
273
}
274
 
274
 
275
 
275
 
276
 
276
 
277
/*********************************************/
277
/*********************************************/
278
/*  Calibrate Compass                        */
278
/*  Calibrate Compass                        */
279
/*********************************************/
279
/*********************************************/
280
void MM3_Calibrate(void)
280
void MM3_Calibrate(void)
281
{
281
{
282
        static uint8_t debugcounter = 0;
282
  static uint8_t debugcounter = 0;
283
        int16_t x_min = 0, x_max = 0, y_min = 0, y_max = 0, z_min = 0, z_max = 0;
283
  int16_t x_min = 0, x_max = 0, y_min = 0, y_max = 0, z_min = 0, z_max = 0;
284
        uint8_t measurement = 50, beeper = 0;
284
  uint8_t measurement = 50, beeper = 0;
285
        uint16_t timer;
285
  uint16_t timer;
286
 
286
 
287
        GRN_ON;
287
  GRN_ON;
288
        ROT_OFF;
288
  ROT_OFF;
289
       
289
 
290
        x_max = -16000;
290
  x_max = -16000;
291
        x_min =  16000;
291
  x_min =  16000;
292
        y_max = -16000;
292
  y_max = -16000;
293
        y_min =  16000;
293
  y_min =  16000;
294
        z_max = -16000;
294
  z_max = -16000;
295
        z_min =  16000;
295
  z_min =  16000;
296
 
296
 
297
        // get maximum and minimum reading of all axis
297
  // get maximum and minimum reading of all axis
298
        while (measurement)
298
  while (measurement)
299
        {
299
  {
300
                if (MM3.x_axis > x_max) x_max = MM3.x_axis;
300
    if (MM3.x_axis > x_max) x_max = MM3.x_axis;
301
                else if (MM3.x_axis < x_min) x_min = MM3.x_axis;
301
    else if (MM3.x_axis < x_min) x_min = MM3.x_axis;
302
 
302
   
303
                if (MM3.y_axis > y_max) y_max = MM3.y_axis;
303
    if (MM3.y_axis > y_max) y_max = MM3.y_axis;
304
                else if (MM3.y_axis < y_min) y_min = MM3.y_axis;
304
    else if (MM3.y_axis < y_min) y_min = MM3.y_axis;
305
 
305
   
306
                if (MM3.z_axis > z_max) z_max = MM3.z_axis;
306
    if (MM3.z_axis > z_max) z_max = MM3.z_axis;
307
                else if (MM3.z_axis < z_min) z_min = MM3.z_axis;
307
    else if (MM3.z_axis < z_min) z_min = MM3.z_axis;
308
 
308
   
309
                if (!beeper)
309
    if (!beeper)
310
                {
310
    {
311
                        ROT_FLASH;
311
      ROT_FLASH;
312
                        GRN_FLASH;
312
      GRN_FLASH;
313
                        beeper = 50;
313
      beeper = 50;
314
                }
314
    }
315
                beeper--;
315
    beeper--;
316
 
316
   
317
                // loop with period of 10 ms / 100 Hz
317
    // loop with period of 10 ms / 100 Hz
318
                timer = SetDelay(10);
318
    timer = SetDelay(10);
319
                while(!CheckDelay(timer));
319
    while(!CheckDelay(timer));
320
 
320
   
321
                if(debugcounter++ > 30)
321
    if(debugcounter++ > 30)
322
                {
322
    {
323
                        printf("\n\rXMin:%4d, XMax:%4d, YMin:%4d, YMax:%4d, ZMin:%4d, ZMax:%4d",x_min,x_max,y_min,y_max,z_min,z_max);
323
      printf("\n\rXMin:%4d, XMax:%4d, YMin:%4d, YMax:%4d, ZMin:%4d, ZMax:%4d",x_min,x_max,y_min,y_max,z_min,z_max);
324
                        debugcounter = 0;
324
      debugcounter = 0;
325
                }
325
    }
326
 
326
   
327
                // If thrust is less than 100, stop calibration with a delay of 0.5 seconds
327
    // If thrust is less than 100, stop calibration with a delay of 0.5 seconds
328
                if (PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] < 100) measurement--;
328
    if (PPM_in[EE_Parameter.Kanalbelegung[K_GAS]] < 100) measurement--;
329
        }
329
  }
330
 
330
 
331
        // Rage of all axis
331
  // Rage of all axis
332
        MM3_calib.X_range = (x_max - x_min);
332
  MM3_calib.X_range = (x_max - x_min);
333
        MM3_calib.Y_range = (y_max - y_min);
333
  MM3_calib.Y_range = (y_max - y_min);
334
        MM3_calib.Z_range = (z_max - z_min);
334
  MM3_calib.Z_range = (z_max - z_min);
335
 
335
 
336
        // Offset of all axis
336
  // Offset of all axis
337
        MM3_calib.X_off = (x_max + x_min) / 2;
337
  MM3_calib.X_off = (x_max + x_min) / 2;
338
        MM3_calib.Y_off = (y_max + y_min) / 2;
338
  MM3_calib.Y_off = (y_max + y_min) / 2;
339
        MM3_calib.Z_off = (z_max + z_min) / 2;
339
  MM3_calib.Z_off = (z_max + z_min) / 2;
Line 340... Line 340...
340
 
340
 
341
        // save to EEProm
341
  // save to EEProm
342
        SetParamWord(PID_MM3_X_OFF,   (uint16_t)MM3_calib.X_off);
342
  SetParamWord(PID_MM3_X_OFF,   (uint16_t)MM3_calib.X_off);
343
        SetParamWord(PID_MM3_Y_OFF,   (uint16_t)MM3_calib.Y_off);
343
  SetParamWord(PID_MM3_Y_OFF,   (uint16_t)MM3_calib.Y_off);
344
        SetParamWord(PID_MM3_Z_OFF,   (uint16_t)MM3_calib.Z_off);
344
  SetParamWord(PID_MM3_Z_OFF,   (uint16_t)MM3_calib.Z_off);
345
        SetParamWord(PID_MM3_X_RANGE, (uint16_t)MM3_calib.X_range);
345
  SetParamWord(PID_MM3_X_RANGE, (uint16_t)MM3_calib.X_range);
346
        SetParamWord(PID_MM3_Y_RANGE, (uint16_t)MM3_calib.Y_range);
346
  SetParamWord(PID_MM3_Y_RANGE, (uint16_t)MM3_calib.Y_range);
347
        SetParamWord(PID_MM3_Z_RANGE, (uint16_t)MM3_calib.Z_range);
347
  SetParamWord(PID_MM3_Z_RANGE, (uint16_t)MM3_calib.Z_range);
348
}
348
}
349
 
349
 
350
 
350
 
351
/*********************************************/
351
/*********************************************/
352
/*  Calculate north direction (heading)      */
352
/*  Calculate north direction (heading)      */
353
/*********************************************/
353
/*********************************************/
354
int16_t MM3_Heading(void)
354
int16_t MM3_Heading(void)
355
{
355
{
356
        int32_t sin_pitch, cos_pitch, sin_roll, cos_roll, sin_yaw, cos_yaw;
356
  int32_t sin_pitch, cos_pitch, sin_roll, cos_roll, sin_yaw, cos_yaw;
357
        int32_t  Hx, Hy, Hz, Hx_corr, Hy_corr;
357
  int32_t  Hx, Hy, Hz, Hx_corr, Hy_corr;
358
        int16_t angle;
358
  int16_t angle;
359
    int16_t heading;
359
  int16_t heading;
360
 
360
 
361
        if (MM3_Timeout)
361
  if (MM3_Timeout)
362
        {
362
  {
363
        // Offset correction and normalization (values of H are +/- 512)
363
    // Offset correction and normalization (values of H are +/- 512)
364
        Hx = (((int32_t)(MM3.x_axis - MM3_calib.X_off)) * 1024) / (int32_t)MM3_calib.X_range;
364
    Hx = (((int32_t)(MM3.x_axis - MM3_calib.X_off)) * 1024) / (int32_t)MM3_calib.X_range;
365
        Hy = (((int32_t)(MM3.y_axis - MM3_calib.Y_off)) * 1024) / (int32_t)MM3_calib.Y_range;
365
    Hy = (((int32_t)(MM3.y_axis - MM3_calib.Y_off)) * 1024) / (int32_t)MM3_calib.Y_range;
366
        Hz = (((int32_t)(MM3.z_axis - MM3_calib.Z_off)) * 1024) / (int32_t)MM3_calib.Z_range;
366
    Hz = (((int32_t)(MM3.z_axis - MM3_calib.Z_off)) * 1024) / (int32_t)MM3_calib.Z_range;
367
 
367
   
368
 
368
   
369
        // Compensate the angle of the MM3-arrow to the head of the MK by a yaw rotation transformation
369
    // Compensate the angle of the MM3-arrow to the head of the MK by a yaw rotation transformation
370
    // assuming the MM3 board is mounted parallel to the frame.
370
    // assuming the MM3 board is mounted parallel to the frame.
371
    // User Param 4 is used to define the positive angle from the MM3-arrow to the MK heading
371
    // User Param 4 is used to define the positive angle from the MM3-arrow to the MK heading
372
    // in a top view counter clockwise direction.
372
    // in a top view counter clockwise direction.
373
    // North is in opposite direction of the small arrow on the MM3 board.
373
    // North is in opposite direction of the small arrow on the MM3 board.
374
    // Therefore 180 deg must be added to that angle.
374
    // Therefore 180 deg must be added to that angle.
375
        angle = ((int16_t)180);
375
    angle = ((int16_t)180);
376
        // wrap angle to interval of 0°- 359°
376
    // wrap angle to interval of 0°- 359°
377
        angle += 360;
377
    angle += 360;
378
        angle %= 360;
378
    angle %= 360;
379
        sin_yaw = (int32_t)(c_sin_8192(angle));
379
    sin_yaw = (int32_t)(c_sin_8192(angle));
380
        cos_yaw = (int32_t)(c_cos_8192(angle));
380
    cos_yaw = (int32_t)(c_cos_8192(angle));
381
 
381
   
382
        Hx_corr = Hx;
382
    Hx_corr = Hx;
383
        Hy_corr = Hy;
383
    Hy_corr = Hy;
384
 
384
   
385
        // rotate
385
    // rotate
386
        Hx = (Hx_corr * cos_yaw - Hy_corr  * sin_yaw) / 8192;
386
    Hx = (Hx_corr * cos_yaw - Hy_corr  * sin_yaw) / 8192;
387
        Hy = (Hx_corr * sin_yaw + Hy_corr  * cos_yaw) / 8192;
387
    Hy = (Hx_corr * sin_yaw + Hy_corr  * cos_yaw) / 8192;
388
 
388
   
389
#ifdef USE_Extended_MM3_Measurement_Model
389
#ifdef USE_Extended_MM3_Measurement_Model
390
        /* Normalize the values to be in the same range as the accelerations  */
390
    /* Normalize the values to be in the same range as the accelerations  */
391
        MM3_Hx = Hx / 51.2F;
391
    MM3_Hx = Hx / 51.2F;
392
        MM3_Hy = Hy / 51.2F;
392
    MM3_Hy = Hy / 51.2F;
393
        MM3_Hz = Hz / 51.2F;
393
    MM3_Hz = Hz / 51.2F;
394
#endif
394
#endif
395
 
395
   
396
    // tilt compensation
396
    // tilt compensation
397
 
397
   
398
        // calibration factor for transforming Gyro Integrals to angular degrees
398
    // calibration factor for transforming Gyro Integrals to angular degrees
399
 
399
   
400
        // calculate sinus cosinus of pitch and tilt angle
400
    // calculate sinus cosinus of pitch and tilt angle
401
        //angle = (status. IntegralPitch/div_factor);
401
    //angle = (status. IntegralPitch/div_factor);
402
        angle = (status.iTheta10 / 10);
402
    angle = (status.iTheta10 / 10);
403
        angle = 0;
403
    angle = 0;
404
        sin_pitch = (int32_t)(c_sin_8192(angle));
404
    sin_pitch = (int32_t)(c_sin_8192(angle));
405
        cos_pitch = (int32_t)(c_cos_8192(angle));
405
    cos_pitch = (int32_t)(c_cos_8192(angle));
406
 
406
   
-
 
407
    //angle = (IntegralRoll/div_factor);
-
 
408
    angle = (status.iPhi10/10);
-
 
409
    angle = 0;
-
 
410
    sin_roll = (int32_t)(c_sin_8192(angle));
-
 
411
    cos_roll = (int32_t)(c_cos_8192(angle));
-
 
412
   
407
        //angle = (IntegralRoll/div_factor);
413
    Hx_corr = (Hx * cos_pitch -  Hz * sin_pitch) / 8192;
408
        angle = (status.iPhi10/10);
414
    Hy_corr = (Hy * cos_roll +  Hz * sin_roll) / 8192;
409
        angle = 0;
415
   
410
        sin_roll = (int32_t)(c_sin_8192(angle));
416
    // calculate Heading
411
        cos_roll = (int32_t)(c_cos_8192(angle));
417
    heading = c_atan2(Hy_corr, Hx_corr);
412
 
418
   
413
        Hx_corr = (Hx * cos_pitch -  Hz * sin_pitch) / 8192;
419
#if 0
414
        Hy_corr = (Hy * cos_roll +  Hz * sin_roll) / 8192;
420
    DebugOut.Analog[3] =  Hx;
415
 
421
    DebugOut.Analog[4]  = Hy;
416
        // calculate Heading
422
    DebugOut.Analog[5]  = Hz;
417
        heading = c_atan2(Hy_corr, Hx_corr);
423
#endif
418
 
424
   
419
    // atan returns angular range from -180 deg to 180 deg in counter clockwise notation
425
    // atan returns angular range from -180 deg to 180 deg in counter clockwise notation