blob: 5fe99b051f0709d4c21ff9651c59a22afa6587bd (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
/*
* Copyright © 2011 Keith Packard <keithp@keithp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef AO_FLIGHT_TEST
#include "ao.h"
#include <ao_data.h>
#endif
/*
* Current sensor values
*/
#ifndef PRES_TYPE
#define PRES_TYPE int32_t
#define ALT_TYPE int32_t
#define ACCEL_TYPE int16_t
#endif
__pdata uint16_t ao_sample_tick; /* time of last data */
__pdata pres_t ao_sample_pres;
__pdata alt_t ao_sample_alt;
__pdata alt_t ao_sample_height;
#if HAS_ACCEL || HAS_ACCEL_REF
__pdata accel_t ao_sample_accel;
#endif
__data uint8_t ao_sample_data;
/*
* Sensor calibration values
*/
__pdata pres_t ao_ground_pres; /* startup pressure */
__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */
#if HAS_ACCEL
__pdata accel_t ao_ground_accel; /* startup acceleration */
__pdata accel_t ao_accel_2g; /* factory accel calibration */
__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */
#endif
static __pdata uint8_t ao_preflight; /* in preflight mode */
static __pdata uint16_t nsamples;
__pdata int32_t ao_sample_pres_sum;
#if HAS_ACCEL
__pdata int32_t ao_sample_accel_sum;
#endif
static void
ao_sample_preflight_add(void)
{
#if HAS_ACCEL
ao_sample_accel_sum += ao_sample_accel;
#endif
ao_sample_pres_sum += ao_sample_pres;
++nsamples;
}
static void
ao_sample_preflight_set(void)
{
#if HAS_ACCEL
ao_ground_accel = ao_sample_accel_sum >> 9;
ao_sample_accel_sum = 0;
#endif
ao_ground_pres = ao_sample_pres_sum >> 9;
ao_ground_height = pres_to_altitude(ao_ground_pres);
nsamples = 0;
ao_sample_pres_sum = 0;
}
static void
ao_sample_preflight(void)
{
/* startup state:
*
* Collect 512 samples of acceleration and pressure
* data and average them to find the resting values
*/
if (nsamples < 512) {
ao_sample_preflight_add();
} else {
#if HAS_ACCEL
ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g;
ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g;
#endif
ao_sample_preflight_set();
ao_preflight = FALSE;
}
}
/*
* While in pad mode, constantly update the ground state by
* re-averaging the data. This tracks changes in orientation, which
* might be caused by adjustments to the rocket on the pad and
* pressure, which might be caused by changes in the weather.
*/
static void
ao_sample_preflight_update(void)
{
if (nsamples < 512)
ao_sample_preflight_add();
else if (nsamples < 1024)
++nsamples;
else
ao_sample_preflight_set();
}
uint8_t
ao_sample(void)
{
ao_wakeup(DATA_TO_XDATA(&ao_sample_data));
ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
while (ao_sample_data != ao_data_head) {
__xdata struct ao_data *ao_data;
/* Capture a sample */
ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data];
ao_sample_tick = ao_data->tick;
ao_data_pres_cook(ao_data);
ao_sample_pres = ao_data_pres(ao_data);
ao_sample_alt = pres_to_altitude(ao_sample_pres);
ao_sample_height = ao_sample_alt - ao_ground_height;
#if HAS_ACCEL || HAS_ACCEL_REF
ao_sample_accel = ao_data_accel_cook(ao_data);
if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
ao_sample_accel = ao_data_accel_invert(ao_sample_accel);
ao_data_set_accel(ao_data, ao_sample_accel);
#endif
if (ao_preflight)
ao_sample_preflight();
else {
if (ao_flight_state < ao_flight_boost)
ao_sample_preflight_update();
ao_kalman();
}
ao_sample_data = ao_data_ring_next(ao_sample_data);
}
return !ao_preflight;
}
void
ao_sample_init(void)
{
ao_config_get();
nsamples = 0;
ao_sample_pres_sum = 0;
ao_sample_pres = 0;
#if HAS_ACCEL
ao_sample_accel_sum = 0;
ao_sample_accel = 0;
#endif
ao_sample_data = ao_data_head;
ao_preflight = TRUE;
}
|