Exemplo n.º 1
0
void
ao_report(void)
{
	ao_report_state = ao_flight_state;
	for(;;) {
#if HAS_BATTERY_REPORT
		if (ao_flight_state == ao_flight_startup)
			ao_report_battery();
		else
#endif
			ao_report_beep();
		if (ao_flight_state == ao_flight_landed) {
			ao_report_altitude();
#if HAS_FLIGHT
			ao_delay(AO_SEC_TO_TICKS(5));
			continue;
#endif
		}
#if HAS_IGNITE_REPORT
		if (ao_flight_state == ao_flight_idle)
			ao_report_continuity();
		while (ao_flight_state == ao_flight_pad) {
			uint8_t	c;
			ao_report_continuity();
			c = 50;
			while (c-- && ao_flight_state == ao_flight_pad)
				pause(AO_MS_TO_TICKS(100));
		}
#endif

		while (ao_report_state == ao_flight_state)
			ao_sleep(DATA_TO_XDATA(&ao_flight_state));
		ao_report_state = ao_flight_state;
	}
}
Exemplo n.º 2
0
static void ao_log_tiny_data(uint16_t d)
{
	if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
		ao_log_stop();
	if (ao_log_running) {
		ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2);
		ao_log_current_pos += 2;
	}
}
Exemplo n.º 3
0
static void
ao_report_battery(void)
{
	__xdata struct ao_data packet;
	for (;;) {
		ao_data_get(&packet);
		if (packet.adc.v_batt != 0)
			break;
		ao_sleep(DATA_TO_XDATA(&ao_sample_data));
	}
	ao_report_number(ao_battery_decivolt(packet.adc.v_batt));
}
Exemplo n.º 4
0
void
ao_flight(void)
{
	ao_sample_init();
	ao_flight_state = ao_flight_startup;
	for (;;) {

		/*
		 * Process ADC samples, just looping
		 * until the sensors are calibrated.
		 */
		if (!ao_sample())
			continue;

		switch (ao_flight_state) {
		case ao_flight_startup:

			/* Check to see what mode we should go to.
			 *  - Invalid mode if accel cal appears to be out
			 *  - pad mode if we're upright,
			 *  - idle mode otherwise
			 */
#if HAS_ACCEL
			if (ao_config.accel_plus_g == 0 ||
			    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)
			{
				/* Detected an accel value outside -1.5g to 1.5g
				 * (or uncalibrated values), so we go into invalid mode
				 */
				ao_flight_state = ao_flight_invalid;

				/* Turn on packet system in invalid mode on TeleMetrum */
				ao_packet_slave_start();
			} else
#endif
				if (!ao_flight_force_idle
#if HAS_ACCEL
				    && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
#endif
					)
 			{
				/* Set pad mode - we can fly! */
				ao_flight_state = ao_flight_pad;
#if HAS_USB
				/* Disable the USB controller in flight mode
				 * to save power
				 */
				ao_usb_disable();
#endif

#if !HAS_ACCEL
				/* Disable packet mode in pad state on TeleMini */
				ao_packet_slave_stop();
#endif

				/* Turn on telemetry system */
				ao_rdf_set(1);
				ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);

				/* signal successful initialization by turning off the LED */
				ao_led_off(AO_LED_RED);
			} else {
				/* Set idle mode */
 				ao_flight_state = ao_flight_idle;
 
#if HAS_ACCEL
				/* Turn on packet system in idle mode on TeleMetrum */
				ao_packet_slave_start();
#endif

				/* signal successful initialization by turning off the LED */
				ao_led_off(AO_LED_RED);
			}
			/* wakeup threads due to state change */
			ao_wakeup(DATA_TO_XDATA(&ao_flight_state));

			break;
		case ao_flight_pad:

			/* pad to boost:
			 *
			 * barometer: > 20m vertical motion
			 *             OR
			 * accelerometer: > 2g AND velocity > 5m/s
			 *
			 * The accelerometer should always detect motion before
			 * the barometer, but we use both to make sure this
			 * transition is detected. If the device
			 * doesn't have an accelerometer, then ignore the
			 * speed and acceleration as they are quite noisy
			 * on the pad.
			 */
			if (ao_height > AO_M_TO_HEIGHT(20)
#if HAS_ACCEL
			    || (ao_accel > AO_MSS_TO_ACCEL(20) &&
				ao_speed > AO_MS_TO_SPEED(5))
#endif
				)
			{
				ao_flight_state = ao_flight_boost;
				ao_launch_tick = ao_sample_tick;

				/* start logging data */
				ao_log_start();

				/* Increase telemetry rate */
				ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);

				/* disable RDF beacon */
				ao_rdf_set(0);

#if HAS_GPS
				/* Record current GPS position by waking up GPS log tasks */
				ao_wakeup(&ao_gps_data);
				ao_wakeup(&ao_gps_tracking_data);
#endif

				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
			}
			break;
		case ao_flight_boost:

			/* boost to fast:
			 *
			 * accelerometer: start to fall at > 1/4 G
			 *              OR
			 * time: boost for more than 15 seconds
			 *
			 * Detects motor burn out by the switch from acceleration to
			 * deceleration, or by waiting until the maximum burn duration
			 * (15 seconds) has past.
			 */
			if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) ||
			    (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX)
			{
#if HAS_ACCEL
				ao_flight_state = ao_flight_fast;
#else
				ao_flight_state = ao_flight_coast;
#endif
				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
			}
			break;
#if HAS_ACCEL
		case ao_flight_fast:
			/*
			 * This is essentially the same as coast,
			 * but the barometer is being ignored as
			 * it may be unreliable.
			 */
			if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED))
			{
				ao_flight_state = ao_flight_coast;
				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
			}
			break;
#endif
		case ao_flight_coast:
			if ((int16_t) (ao_sample_tick - ao_launch_tick) > DESIRED_AUX_TIME) 
			{
				ao_ignite(ao_igniter_main);

			} 
			/* apogee detect: coast to drogue deploy:
			 *
			 * speed: < 0
			 *
			 * Also make sure the model altitude is tracking
			 * the measured altitude reasonably closely; otherwise
			 * we're probably transsonic.
			 */
			if (ao_speed < 0
#if !HAS_ACCEL
			    && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)
#endif
				)
			{
				/* ignite the drogue charge */
				/*ao_ignite(ao_igniter_drogue); */

				/* slow down the telemetry system */
				ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);

				/* Turn the RDF beacon back on */
				ao_rdf_set(1);

				/* and enter drogue state */
				ao_flight_state = ao_flight_drogue;
				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
			}

			break;
		case ao_flight_drogue:

			/* drogue to main deploy:
			 *
			 * barometer: reach main deploy altitude
			 *
			 * Would like to use the accelerometer for this test, but
			 * the orientation of the flight computer is unknown after
			 * drogue deploy, so we ignore it. Could also detect
			 * high descent rate using the pressure sensor to
			 * recognize drogue deploy failure and eject the main
			 * at that point. Perhaps also use the drogue sense lines
			 * to notice continutity?
			 */
			if (ao_height <= ao_config.main_deploy)
			{
				/*ao_ignite(ao_igniter_main);*/

				/*
				 * Start recording min/max height
				 * to figure out when the rocket has landed
				 */

				/* initialize interval values */
				ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;

				ao_interval_min_height = ao_interval_max_height = ao_avg_height;

				ao_flight_state = ao_flight_main;
				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
			}
			break;

			/* fall through... */
		case ao_flight_main:

			/* main to land:
			 *
			 * barometer: altitude stable
			 */

			if (ao_avg_height < ao_interval_min_height)
				ao_interval_min_height = ao_avg_height;
			if (ao_avg_height > ao_interval_max_height)
				ao_interval_max_height = ao_avg_height;

			if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
				if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
				{
					ao_flight_state = ao_flight_landed;

					/* turn off the ADC capture */
					ao_timer_set_adc_interval(0);

					ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
				}
				ao_interval_min_height = ao_interval_max_height = ao_avg_height;
				ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
			}
			break;
		case ao_flight_landed:
			break;
		}
	}
}
Exemplo n.º 5
0
void
ao_log(void)
{
	uint16_t		last_time;
	uint16_t		now;
	enum ao_flight_state	ao_log_tiny_state;
	int32_t			sum;
	int16_t			count;
	uint8_t			ao_log_data;
	uint8_t			ao_log_started = 0;

	ao_storage_setup();

	ao_log_scan();

	ao_log_tiny_state = ao_flight_invalid;
	ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
	sum = 0;
	count = 0;
	ao_log_data = ao_sample_data;
	last_time = ao_time();
	for (;;) {

		/*
		 * Add in pending sample data
		 */
		ao_sleep(DATA_TO_XDATA(&ao_sample_data));
		while (ao_log_data != ao_sample_data) {
			sum += ao_data_pres(&ao_data_ring[ao_log_data]);
			count++;
			ao_log_data = ao_data_ring_next(ao_log_data);
		}
		if (ao_log_running) {
			if (!ao_log_started) {
				ao_log_tiny_start();
				ao_log_started = 1;
			}
			if (ao_flight_state != ao_log_tiny_state) {
				ao_log_tiny_data(ao_flight_state | 0x8000);
				ao_log_tiny_state = ao_flight_state;
				ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT;
#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT
				if (ao_log_tiny_state <= ao_flight_coast)
					ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
#endif
				if (ao_log_tiny_state == ao_flight_landed)
					ao_log_stop();
			}
		}

		/* Stop logging when told to */
		if (!ao_log_running && ao_log_started)
			ao_exit();

		/*
		 * Write out the sample when finished
		 */
		now = ao_time();
		if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) {
			count = sum / count;
			if (ao_log_started)
				ao_log_tiny_data(count);
			else
				ao_log_tiny_queue(count);
			sum = 0;
			count = 0;
			last_time = now;
		}
	}
}