the altimeter completes initialization and self test, and decides
which mode to enter next.
</para>
+ <para>
+ Here's a short summary of all of the modes and the beeping (or
+ flashing, in the case of TeleMini v1) that accompanies each
+ mode. In the description of the beeping pattern, “dit” means a
+ short beep while "dah" means a long beep (three times as
+ long). “Brap” means a long dissonant tone.
+ <table frame='all'>
+ <title>AltOS Modes</title>
+ <?dbfo keep-together="always"?>
+ <tgroup cols='4' align='center' colsep='1' rowsep='1'>
+ <colspec align='center' colwidth='*' colname='Mode Name'/>
+ <colspec align='center' colwidth='*' colname='Letter'/>
+ <colspec align='center' colwidth='*' colname='Beeps'/>
+ <colspec align='center' colwidth='*' colname='Description'/>
+ <thead>
+ <row>
+ <entry>Mode Name</entry>
+ <entry>Abbreviation</entry>
+ <entry>Beeps</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Startup</entry>
+ <entry>S</entry>
+ <entry>dit dit dit</entry>
+ <entry>
+ <para>
+ Calibrating sensors, detecting orientation.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Idle</entry>
+ <entry>I</entry>
+ <entry>dit dit</entry>
+ <entry>
+ <para>
+ Ready to accept commands over USB or radio link.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Pad</entry>
+ <entry>P</entry>
+ <entry>dit dah dah dit</entry>
+ <entry>
+ <para>
+ Waiting for launch. Not listening for commands.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Boost</entry>
+ <entry>B</entry>
+ <entry>dah dit dit dit</entry>
+ <entry>
+ <para>
+ Accelerating upwards.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Fast</entry>
+ <entry>F</entry>
+ <entry>dit dit dah dit</entry>
+ <entry>
+ <para>
+ Decellerating, but moving faster than 200m/s.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Coast</entry>
+ <entry>C</entry>
+ <entry>dah dit dah dit</entry>
+ <entry>
+ <para>
+ Decellerating, moving slower than 200m/s
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Drogue</entry>
+ <entry>D</entry>
+ <entry>dah dit dit</entry>
+ <entry>
+ <para>
+ Descending after apogee. Above main height.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Main</entry>
+ <entry>M</entry>
+ <entry>dah dah</entry>
+ <entry>
+ <para>
+ Descending. Below main height.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Landed</entry>
+ <entry>L</entry>
+ <entry>dit dah dit dit</entry>
+ <entry>
+ <para>
+ Stable altitude for at least ten seconds.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Sensor error</entry>
+ <entry>X</entry>
+ <entry>dah dit dit dah</entry>
+ <entry>
+ <para>
+ Error detected during sensor calibration.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
<para>
In flight or “pad” mode, the altimeter engages the flight
- state machine, goes into transmit-only mode to
- send telemetry, and waits for launch to be detected.
- Flight mode is indicated by an “di-dah-dah-dit” (“P” for pad)
- on the beeper or lights, followed by beeps or flashes
- indicating the state of the pyrotechnic igniter continuity.
- One beep/flash indicates apogee continuity, two beeps/flashes
- indicate main continuity, three beeps/flashes indicate both
- apogee and main continuity, and one longer “brap” sound or
- rapidly alternating lights indicates no continuity. For a
+ state machine, goes into transmit-only mode to send telemetry,
+ and waits for launch to be detected. Flight mode is indicated
+ by an “di-dah-dah-dit” (“P” for pad) on the beeper or lights,
+ followed by beeps or flashes indicating the state of the
+ pyrotechnic igniter continuity. One beep/flash indicates
+ apogee continuity, two beeps/flashes indicate main continuity,
+ three beeps/flashes indicate both apogee and main continuity,
+ and one longer “brap” sound which is made by rapidly
+ alternating between two tones indicates no continuity. For a
dual deploy flight, make sure you're getting three beeps or
flashes before launching! For apogee-only or motor eject
flights, do what makes sense.
data from the on-board storage chip after flight, and for
ground testing pyro charges.
</para>
+ <para>
+ In “Idle” and “Pad” modes, once the mode indication
+ beeps/flashes and continuity indication has been sent, if
+ there is no space available to log the flight in on-board
+ memory, the flight computer will emit a warbling tone (much
+ slower than the “no continuity tone”)
+ </para>
+ <para>
+ Here's a summary of all of the “pad” and “idle” mode indications.
+ <table frame='all'>
+ <title>Pad/Idle Indications</title>
+ <?dbfo keep-together="always"?>
+ <tgroup cols='3' align='center' colsep='1' rowsep='1'>
+ <colspec align='center' colwidth='*' colname='Name'/>
+ <colspec align='center' colwidth='*' colname='Beeps'/>
+ <colspec align='center' colwidth='*' colname='Description'/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Beeps</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Neither</entry>
+ <entry>brap</entry>
+ <entry>
+ <para>
+ No continuity detected on either apogee or main
+ igniters.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Apogee</entry>
+ <entry>dit</entry>
+ <entry>
+ <para>
+ Continuity detected only on apogee igniter.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Main</entry>
+ <entry>dit dit</entry>
+ <entry>
+ <para>
+ Continuity detected only on main igniter.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Both</entry>
+ <entry>dit dit dit</entry>
+ <entry>
+ <para>
+ Continuity detected on both igniters.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Storage Full</entry>
+ <entry>warble</entry>
+ <entry>
+ <para>
+ On-board data logging storage is full. This will
+ not prevent the flight computer from safely
+ controlling the flight or transmitting telemetry
+ signals, but no record of the flight will be
+ stored in on-board flash.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+ <para>
+ Once landed, the flight computer will signal that by emitting
+ the “Landed” sound described above, after which it will beep
+ out the apogee height (in meters). Each digit is represented
+ by a sequence of short “dit” beeps, with a pause between
+ digits. A zero digit is represented with one long “dah”
+ beep. The flight computer will continue to report landed mode
+ and beep out the maximum height until turned off.
+ </para>
<para>
One “neat trick” of particular value when TeleMetrum or TeleMega are used with
very large air-frames, is that you can power the board up while the
__pdata uint16_t ao_boost_tick; /* time of launch detect */
__pdata uint16_t ao_motor_number; /* number of motors burned so far */
+#if HAS_IMU
+/* Any sensor can set this to mark the flight computer as 'broken' */
+__xdata uint8_t ao_sensor_errors;
+#endif
+
/*
* track min/max data over a long interval to detect
* resting
ao_config.accel_minus_g == 0 ||
ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP ||
+#if HAS_IMU
+ ao_sensor_errors ||
+#endif
ao_ground_height < -1000 ||
ao_ground_height > 7000)
{
extern __pdata uint16_t ao_boost_tick;
extern __pdata uint16_t ao_motor_number;
+#if HAS_IMU
+extern __xdata uint8_t ao_sensor_errors;
+#endif
+
extern __pdata uint16_t ao_launch_time;
extern __pdata uint8_t ao_flight_force_idle;
{
int16_t diff = test - normal;
- if (diff < MPU6000_ST_ACCEL(16) / 2) {
+ if (diff < MPU6000_ST_ACCEL(16) / 4) {
return 1;
}
- if (diff > MPU6000_ST_ACCEL(16) * 2) {
+ if (diff > MPU6000_ST_ACCEL(16) * 4) {
return 1;
}
return 0;
if (diff < 0)
diff = -diff;
- if (diff < MPU6000_ST_GYRO(2000) / 2) {
+ if (diff < MPU6000_ST_GYRO(2000) / 4) {
return 1;
}
- if (diff > MPU6000_ST_GYRO(2000) * 2) {
+ if (diff > MPU6000_ST_GYRO(2000) * 4) {
return 1;
}
return 0;
ao_panic(AO_PANIC_SELF_TEST_MPU6000);
}
+#define ST_TRIES 10
+
static void
_ao_mpu6000_setup(void)
{
struct ao_mpu6000_sample normal_mode, test_mode;
- int errors =0;
+ int errors;
+ int st_tries;
if (ao_mpu6000_configured)
return;
(MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) |
(MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG));
- /* Configure accelerometer to +/-16G in self-test mode */
- _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG,
- (1 << MPU600_ACCEL_CONFIG_XA_ST) |
- (1 << MPU600_ACCEL_CONFIG_YA_ST) |
- (1 << MPU600_ACCEL_CONFIG_ZA_ST) |
- (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL));
-
- /* Configure gyro to +/- 2000°/s in self-test mode */
- _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG,
- (1 << MPU600_GYRO_CONFIG_XG_ST) |
- (1 << MPU600_GYRO_CONFIG_YG_ST) |
- (1 << MPU600_GYRO_CONFIG_ZG_ST) |
- (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL));
-
- ao_delay(AO_MS_TO_TICKS(200));
- _ao_mpu6000_sample(&test_mode);
-
#if TRIDGE
// read the product ID rev c has 1/2 the sensitivity of rev d
_mpu6000_product_id = _register_read(MPUREG_PRODUCT_ID);
register_write(MPUREG_ACCEL_CONFIG,2<<3);
}
hal.scheduler->delay(1);
-
#endif
- /* Configure accelerometer to +/-16G */
- _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG,
- (0 << MPU600_ACCEL_CONFIG_XA_ST) |
- (0 << MPU600_ACCEL_CONFIG_YA_ST) |
- (0 << MPU600_ACCEL_CONFIG_ZA_ST) |
- (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL));
-
- /* Configure gyro to +/- 2000°/s */
- _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG,
- (0 << MPU600_GYRO_CONFIG_XG_ST) |
- (0 << MPU600_GYRO_CONFIG_YG_ST) |
- (0 << MPU600_GYRO_CONFIG_ZG_ST) |
- (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL));
-
- ao_delay(AO_MS_TO_TICKS(10));
- _ao_mpu6000_sample(&normal_mode);
+ for (st_tries = 0; st_tries < ST_TRIES; st_tries++) {
+ errors = 0;
+
+ /* Configure accelerometer to +/-16G in self-test mode */
+ _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG,
+ (1 << MPU600_ACCEL_CONFIG_XA_ST) |
+ (1 << MPU600_ACCEL_CONFIG_YA_ST) |
+ (1 << MPU600_ACCEL_CONFIG_ZA_ST) |
+ (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL));
+
+ /* Configure gyro to +/- 2000°/s in self-test mode */
+ _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG,
+ (1 << MPU600_GYRO_CONFIG_XG_ST) |
+ (1 << MPU600_GYRO_CONFIG_YG_ST) |
+ (1 << MPU600_GYRO_CONFIG_ZG_ST) |
+ (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL));
+
+ ao_delay(AO_MS_TO_TICKS(200));
+ _ao_mpu6000_sample(&test_mode);
+
+ /* Configure accelerometer to +/-16G */
+ _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG,
+ (0 << MPU600_ACCEL_CONFIG_XA_ST) |
+ (0 << MPU600_ACCEL_CONFIG_YA_ST) |
+ (0 << MPU600_ACCEL_CONFIG_ZA_ST) |
+ (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL));
+
+ /* Configure gyro to +/- 2000°/s */
+ _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG,
+ (0 << MPU600_GYRO_CONFIG_XG_ST) |
+ (0 << MPU600_GYRO_CONFIG_YG_ST) |
+ (0 << MPU600_GYRO_CONFIG_ZG_ST) |
+ (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL));
+
+ ao_delay(AO_MS_TO_TICKS(200));
+ _ao_mpu6000_sample(&normal_mode);
- errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x");
- errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y");
- errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z");
-
- errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x");
- errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y");
- errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z");
+ errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x");
+ errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y");
+ errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z");
+
+ errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x");
+ errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y");
+ errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z");
+ if (!errors)
+ break;
+ }
- if (errors)
- ao_panic(AO_PANIC_SELF_TEST_MPU6000);
+ if (st_tries == ST_TRIES)
+ ao_sensor_errors = 1;
/* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */
_ao_mpu6000_reg_write(MPU6000_CONFIG,
stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES);
/* Disable the interface */
- stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN);
+ stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN);
ao_arch_release_interrupts();
}
#define AO_MPU6000_INT_PORT (&stm_gpioc)
#define AO_MPU6000_INT_PIN 13
#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1)
+#define HAS_IMU 1
/*
* mma655x
#define AO_MPU6000_SPI_BUS AO_SPI_1_PE13_PE14_PE15
#define AO_MPU6000_SPI_CS_PORT (&stm_gpiod)
#define AO_MPU6000_SPI_CS_PIN 2
-
-#define HAS_HIGHG_ACCEL 1
+#define HAS_IMU 1
/*
* mma655x