Example #1
0
static enum opahrs_result opahrs_msg_v1_send_req(const struct opahrs_msg_v1 *req)
{
	int32_t rc;
	struct opahrs_msg_v1 link_rx;

	for (uint8_t retries = 0; retries < 20; retries++) {
		struct opahrs_msg_v1 *rsp = &link_rx;

		if ((rc = opahrs_msg_txrx((const uint8_t *)req, (uint8_t *) rsp, sizeof(*rsp))) < 0) {
			return OPAHRS_RESULT_FAILED;
		}

		/* Make sure we got a sane response by checking the magic */
		if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
			return OPAHRS_RESULT_FAILED;
		}

		switch (rsp->head.type) {
		case OPAHRS_MSG_TYPE_LINK:
			switch (rsp->payload.link.state) {
			case OPAHRS_MSG_LINK_STATE_BUSY:
			case OPAHRS_MSG_LINK_STATE_INACTIVE:
				/* Wait for a small delay and retry */
#ifdef PIOS_INCLUDE_FREERTOS
				vTaskDelay(MS2TICKS(1));
#else
				PIOS_DELAY_WaitmS(20);
#endif
				continue;
			case OPAHRS_MSG_LINK_STATE_READY:
				/* Peer was ready when we Tx'd so they have now Rx'd our message */
				return OPAHRS_RESULT_OK;
			}
			break;
		case OPAHRS_MSG_TYPE_USER_V0:
		case OPAHRS_MSG_TYPE_USER_V1:
			/* Wait for a small delay and retry */
#ifdef PIOS_INCLUDE_FREERTOS
			vTaskDelay(MS2TICKS(1));
#else
			PIOS_DELAY_WaitmS(50);
#endif
			continue;
		}
	}

	return OPAHRS_RESULT_TIMEOUT;
}
Example #2
0
File: led.c Project: mneumann/sixo
/***********************************************************************
 *  FUNCTION:       LEDOk
 *  DESCRIPTION:    let the white led be an acknowledge:
 *                  600 ms permanent ON
 *  PARAMETER:      -
 *  RETURN:         -
 *  COMMENT:        #ifdef HW_LEDRYW:   - uses white LED for BMW version
 *                  #else               - uses lower led in green mode
 *********************************************************************** */
void LEDOk(void)
{
    MESSAGE msg;

#ifdef HW_LEDRYW /* WE USE WHITE OK LED */
    LED_MSG_MS(msg, LED_FLASH, LED_ON, 1, 0);       /* set led ON now! */
    MsgQPostMsg(msg, MSGQ_PRIO_LOW);
    LED_MSG_MS(msg, LED_FLASH, LED_OFF, 0, 1);      /* switch off led after 600 ms */
    SetTimerMsg(msg, MS2TICKS(600));
#else            /* WE USE GREEN DUAL LED */
    LED_MSG_MS(msg, LED1, LED_GREEN, 1, 0);         /* set led ON now! */
    MsgQPostMsg(msg, MSGQ_PRIO_LOW);
    LED_MSG_MS(msg, LED1, LED_OFF, 0, 1);           /* switch off led after 600 ms */
    SetTimerMsg(msg, MS2TICKS(600));
#endif
}
Example #3
0
/**
 *
 * @brief   Suspends execution of current thread at least for specified time.
 *
 * @param[in] time_ms      time in milliseconds to suspend thread execution
 *
 */
void PIOS_Thread_Sleep(uint32_t time_ms)
{
	if (time_ms == PIOS_THREAD_TIMEOUT_MAX)
		vTaskDelay(portMAX_DELAY);
	else
		vTaskDelay((portTickType)MS2TICKS(time_ms));
}
Example #4
0
File: led.c Project: mneumann/sixo
/***********************************************************************
 *  FUNCTION:       LEDEsc
 *  DESCRIPTION:    let the red led be an error indicator:
 *                  1000 ms duration pulsed with 100 ms ON / 100 ms OFF
 *  PARAMETER:      -
 *  RETURN:         -
 *  COMMENT:        #ifdef HW_LEDRYW: - uses red LED for BMW version
 *                  #else             - uses lower led in red mode
 *********************************************************************** */
void LEDEsc(void)
{
    MESSAGE msg;

#ifdef HW_LEDRYW /* WE USE RED ESC LED */
    LED_MSG_MS(msg, LED_OIL, LED_ON, 100, 100);         /* set led ON now! */
    MsgQPostMsg(msg, MSGQ_PRIO_LOW);
    LED_MSG_MS(msg, LED_OIL, LED_OFF, 0, 1);            /* switch off led after 1000 ms */
    SetTimerMsg(msg, MS2TICKS(1000));
#else            /* WE USE RED DUAL LED */
    LED_MSG_MS(msg, LED1, LED_RED, 100, 100);           /* set led ON now! */
    MsgQPostMsg(msg, MSGQ_PRIO_LOW);
    LED_MSG_MS(msg, LED1, LED_OFF, 0, 1);               /* switch off led after 1000 ms */
    SetTimerMsg(msg, MS2TICKS(1000));
#endif
}
Example #5
0
/**
 *
 * @brief   Takes binary semaphore.
 *
 * @param[in] sema         pointer to instance of @p struct pios_semaphore
 * @param[in] timeout_ms   timeout for acquiring the lock in milliseconds
 *
 * @returns true on success or false on timeout or failure
 *
 */
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
{
	PIOS_Assert(sema != NULL);

#if defined(PIOS_INCLUDE_FREERTOS)
	portTickType timeout_ticks;
	if (timeout_ms == PIOS_SEMAPHORE_TIMEOUT_MAX)
		timeout_ticks = portMAX_DELAY;
	else
		timeout_ticks = MS2TICKS(timeout_ms);

	return xSemaphoreTake(sema->sema_handle, timeout_ticks) == pdTRUE;
#else
	uint32_t start = PIOS_DELAY_GetRaw();

	uint32_t temp_sema_count;
	do {
		PIOS_IRQ_Disable();
		if ((temp_sema_count = sema->sema_count) != 0)
			--sema->sema_count;
		PIOS_IRQ_Enable();
	} while (temp_sema_count == 0 &&
		PIOS_DELAY_DiffuS(start) < timeout_ms * 1000);

	return temp_sema_count != 0;
#endif
}
/* void sync(int): synchronize an interval by given ms-value */
void SystemSync(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
	static portTickType lastSysTime;
	if ((lastSysTime == 0) || (Param[0]->Val->Integer == 0)) {
		lastSysTime = xTaskGetTickCount();
	}
	if (Param[0]->Val->Integer > 0) {
		vTaskDelayUntil(&lastSysTime, MS2TICKS(Param[0]->Val->Integer));
	}
}
Example #7
0
/**
 *
 * @brief   Locks a non recursive mutex.
 *
 * @param[in] mtx          pointer to instance of @p struct pios_mutex
 * @param[in] timeout_ms   timeout for acquiring the lock in milliseconds
 *
 * @returns true on success or false on timeout or failure
 *
 */
bool PIOS_Mutex_Lock(struct pios_mutex *mtx, uint32_t timeout_ms)
{
	PIOS_Assert(mtx != NULL);

	portTickType timeout_ticks;
	if (timeout_ms == PIOS_MUTEX_TIMEOUT_MAX)
		timeout_ticks = portMAX_DELAY;
	else
		timeout_ticks = MS2TICKS(timeout_ms);

	return xSemaphoreTake(mtx->mtx_handle, timeout_ticks) == pdTRUE;
}
Example #8
0
enum opahrs_result PIOS_OPAHRS_resync(void)
{
	struct opahrs_msg_v1 req;
	struct opahrs_msg_v1 rsp;

	enum opahrs_result rc = OPAHRS_RESULT_FAILED;

	opahrs_msg_v1_init_link_tx(&req, OPAHRS_MSG_LINK_TAG_NOP);

	PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
#ifdef PIOS_INCLUDE_FREERTOS
	vTaskDelay(MS2TICKS(1));
#else
	PIOS_DELAY_WaitmS(20);
#endif

	for (uint32_t i = 0; i < sizeof(req); i++) {
		/* Tx a shortened (by one byte) message to walk through all byte positions */
		opahrs_msg_v1_init_rx(&rsp);
		PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, (uint8_t *) & req, (uint8_t *) & rsp, sizeof(req) - 1, NULL);

		/* Good magic means we're sync'd */
		if ((rsp.head.magic == OPAHRS_MSG_MAGIC_HEAD) && (rsp.tail.magic == OPAHRS_MSG_MAGIC_TAIL)) {
			/* We need to shift out one more byte to compensate for the short tx */
			PIOS_SPI_TransferByte(PIOS_OPAHRS_SPI, 0x00);
			rc = OPAHRS_RESULT_OK;
			break;
		}
#ifdef PIOS_INCLUDE_FREERTOS
		vTaskDelay(MS2TICKS(1));
#else
		PIOS_DELAY_WaitmS(10);
#endif
	}

	PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
	//vTaskDelay(MS2TICKS(5));

	return rc;
}
Example #9
0
static int32_t opahrs_msg_txrx(const uint8_t * tx, uint8_t * rx, uint32_t len)
{
	int32_t rc;

	PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
#ifdef PIOS_INCLUDE_FREERTOS
	vTaskDelay(MS2TICKS(1));
#else
	PIOS_DELAY_WaitmS(20);
#endif
	rc = PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, tx, rx, len, NULL);
	PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
	return (rc);
}
Example #10
0
static enum opahrs_result opahrs_msg_v1_recv_rsp(enum opahrs_msg_v1_tag tag, struct opahrs_msg_v1 *rsp)
{
	struct opahrs_msg_v1 link_tx;

	opahrs_msg_v1_init_link_tx(&link_tx, OPAHRS_MSG_LINK_TAG_NOP);

	for (uint8_t retries = 0; retries < 20; retries++) {
		if (opahrs_msg_txrx((const uint8_t *)&link_tx, (uint8_t *) rsp, sizeof(*rsp)) < 0) {
			return OPAHRS_RESULT_FAILED;
		}

		/* Make sure we got a sane response by checking the magic */
		if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
			return OPAHRS_RESULT_FAILED;
		}

		switch (rsp->head.type) {
		case OPAHRS_MSG_TYPE_LINK:
			switch (rsp->payload.link.state) {
			case OPAHRS_MSG_LINK_STATE_BUSY:
				/* Wait for a small delay and retry */
#ifdef PIOS_INCLUDE_FREERTOS
				vTaskDelay(MS2TICKS(1));
#else
				PIOS_DELAY_WaitmS(20);
#endif
				continue;
			case OPAHRS_MSG_LINK_STATE_INACTIVE:
			case OPAHRS_MSG_LINK_STATE_READY:
				/* somehow, we've missed our response */
				return OPAHRS_RESULT_FAILED;
			}
			break;
		case OPAHRS_MSG_TYPE_USER_V0:
			/* This isn't the type we expected */
			return OPAHRS_RESULT_FAILED;
			break;
		case OPAHRS_MSG_TYPE_USER_V1:
			if (rsp->payload.user.t == tag) {
				return OPAHRS_RESULT_OK;
			} else {
				return OPAHRS_RESULT_FAILED;
			}
			break;
		}
	}

	return OPAHRS_RESULT_TIMEOUT;
}
Example #11
0
/**
 * Module thread, should not return.
 */
static void exampleTask(void *parameters)
{
	ExampleSettingsData settings;
	ExampleObject2Data data;
	int32_t step;
	portTickType lastSysTime;

	// Main task loop
	lastSysTime = xTaskGetTickCount();
	while (1) {
		// Update settings with latest value
		ExampleSettingsGet(&settings);

		// Get the object data
		ExampleObject2Get(&data);

		// Determine how to update the data
		if (settings.StepDirection == EXAMPLESETTINGS_STEPDIRECTION_UP) {
			step = settings.StepSize;
		} else {
			step = -settings.StepSize;
		}

		// Update the data
		data.Field1 += step;
		data.Field2 += step;
		data.Field3 += step;
		data.Field4[0] += step;
		data.Field4[1] += step;

		// Update the ExampleObject, after this function is called
		// notifications to any other modules listening to that object
		// will be sent and the GCS object will be updated through the
		// telemetry link. All operations will take place asynchronously
		// and the following call will return immediately.
		ExampleObject2Set(&data);

		// Since this module executes at fixed time intervals, we need to
		// block the task until it is time for the next update.
		// The settings field is in ms, to convert to RTOS ticks we need
		// to use the MS2TICKS macro.
		vTaskDelayUntil(&lastSysTime, MS2TICKS(settings.UpdatePeriod));
	}
}
Example #12
0
/**
 *
 * @brief   Suspends execution of current thread for a regular interval.
 *
 * @param[in] previous_ms  pointer to system time of last execution,
 *                         must have been initialized with PIOS_Thread_Systime() on first invocation
 * @param[in] increment_ms time of regular interval in milliseconds
 *
 */
void PIOS_Thread_Sleep_Until(uint32_t *previous_ms, uint32_t increment_ms)
{
	portTickType temp = MS2TICKS(*previous_ms);
	vTaskDelayUntil(&temp, (portTickType)MS2TICKS(increment_ms));
	*previous_ms = TICKS2MS(temp);
}
Example #13
0
File: GPS.c Project: 1heinz/TauLabs
static void gpsTask(void *parameters)
{
	portTickType xDelay = MS2TICKS(GPS_COM_TIMEOUT_MS);
	uint32_t timeNowMs = TICKS2MS(xTaskGetTickCount());

	GPSPositionData gpsposition;
	uint8_t	gpsProtocol;

	ModuleSettingsGPSDataProtocolGet(&gpsProtocol);

#if defined(PIOS_GPS_PROVIDES_AIRSPEED)
	gps_airspeed_initialize();
#endif

	timeOfLastUpdateMs = timeNowMs;
	timeOfLastCommandMs = timeNowMs;


#if !defined(PIOS_GPS_MINIMAL)
	switch (gpsProtocol) {
#if defined(PIOS_INCLUDE_GPS_UBX_PARSER)
		case MODULESETTINGS_GPSDATAPROTOCOL_UBX:
		{
			uint8_t gpsAutoConfigure;
			ModuleSettingsGPSAutoConfigureGet(&gpsAutoConfigure);

			if (gpsAutoConfigure == MODULESETTINGS_GPSAUTOCONFIGURE_TRUE) {

				// Wait for power to stabilize before talking to external devices
				vTaskDelay(MS2TICKS(1000));

				// Runs through a number of possible GPS baud rates to
				// configure the ublox baud rate. This uses a NMEA string
				// so could work for either UBX or NMEA actually. This is
				// somewhat redundant with updateSettings below, but that
				// is only called on startup and is not an issue.
				ModuleSettingsGPSSpeedOptions baud_rate;
				ModuleSettingsGPSSpeedGet(&baud_rate);
				ubx_cfg_set_baudrate(gpsPort, baud_rate);

				vTaskDelay(MS2TICKS(1000));

				ubx_cfg_send_configuration(gpsPort, gps_rx_buffer);
			}
		}
			break;
#endif
	}
#endif /* PIOS_GPS_MINIMAL */

	GPSPositionGet(&gpsposition);
	// Loop forever
	while (1)
	{
		uint8_t c;

		// This blocks the task until there is something on the buffer
		while (PIOS_COM_ReceiveBuffer(gpsPort, &c, 1, xDelay) > 0)
		{
			int res;
			switch (gpsProtocol) {
#if defined(PIOS_INCLUDE_GPS_NMEA_PARSER)
				case MODULESETTINGS_GPSDATAPROTOCOL_NMEA:
					res = parse_nmea_stream (c,gps_rx_buffer, &gpsposition, &gpsRxStats);
					break;
#endif
#if defined(PIOS_INCLUDE_GPS_UBX_PARSER)
				case MODULESETTINGS_GPSDATAPROTOCOL_UBX:
					res = parse_ubx_stream (c,gps_rx_buffer, &gpsposition, &gpsRxStats);
					break;
#endif
				default:
					res = NO_PARSER; // this should not happen
					break;
			}

			if (res == PARSER_COMPLETE) {
				timeNowMs = TICKS2MS(xTaskGetTickCount());
				timeOfLastUpdateMs = timeNowMs;
				timeOfLastCommandMs = timeNowMs;
			}
		}

		// Check for GPS timeout
		timeNowMs = TICKS2MS(xTaskGetTickCount());
		if ((timeNowMs - timeOfLastUpdateMs) >= GPS_TIMEOUT_MS) {
			// we have not received any valid GPS sentences for a while.
			// either the GPS is not plugged in or a hardware problem or the GPS has locked up.
			uint8_t status = GPSPOSITION_STATUS_NOGPS;
			GPSPositionStatusSet(&status);
			AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_ERROR);
		} else {
			// we appear to be receiving GPS sentences OK, we've had an update
			//criteria for GPS-OK taken from this post
			if (gpsposition.PDOP < 3.5f && 
			    gpsposition.Satellites >= 7 &&
			    (gpsposition.Status == GPSPOSITION_STATUS_FIX3D ||
			         gpsposition.Status == GPSPOSITION_STATUS_DIFF3D)) {
				AlarmsClear(SYSTEMALARMS_ALARM_GPS);
			} else if (gpsposition.Status == GPSPOSITION_STATUS_FIX3D ||
			           gpsposition.Status == GPSPOSITION_STATUS_DIFF3D)
						AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_WARNING);
					else
						AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_CRITICAL);
		}

	}
}
Example #14
0
void baro_airspeedGetAnalog(BaroAirspeedData *baroAirspeedData, portTickType *lastSysTime, uint8_t airspeedSensorType, int8_t airspeedADCPin)
{
	//Wait until our turn
	vTaskDelayUntil(lastSysTime, MS2TICKS(SAMPLING_DELAY_MS_MPXV));

	//Ensure that the ADC pin is properly configured
	if(airspeedADCPin <0){ //It's not, so revert to former sensor type
		baroAirspeedData->BaroConnected = BAROAIRSPEED_BAROCONNECTED_FALSE;

		return;
	}

	//Calibrate sensor by averaging zero point value //THIS SHOULD NOT BE DONE IF THERE IS AN IN-AIR RESET. HOW TO DETECT THIS?
	if (calibrationCount < CALIBRATION_IDLE_MS/SAMPLING_DELAY_MS_MPXV) { //First let sensor warm up and stabilize.
		calibrationCount++;
		return;
	} else if (calibrationCount <= (CALIBRATION_IDLE_MS + CALIBRATION_COUNT_MS)/SAMPLING_DELAY_MS_MPXV) { //Then compute the average.
		calibrationCount++; /*DO NOT MOVE FROM BEFORE sensorCalibration=... LINE, OR ELSE WILL HAVE DIVIDE BY ZERO */

		uint16_t sensorCalibration;
		if(airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002){
		sensorCalibration=PIOS_MPXV7002_Calibrate(airspeedADCPin, calibrationCount-CALIBRATION_IDLE_MS/SAMPLING_DELAY_MS_MPXV);
		PIOS_MPXV7002_UpdateCalibration(sensorCalibration); //This makes sense for the user if the initial calibration was not good and the user does not wish to reboot.
		}
		else if(airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV5004){
		sensorCalibration=PIOS_MPXV5004_Calibrate(airspeedADCPin, calibrationCount-CALIBRATION_IDLE_MS/SAMPLING_DELAY_MS_MPXV);
		PIOS_MPXV5004_UpdateCalibration(sensorCalibration); //This makes sense for the user if the initial calibration was not good and the user does not wish to reboot.
		}


		baroAirspeedData->BaroConnected = BAROAIRSPEED_BAROCONNECTED_TRUE;

		//Set settings UAVO. The airspeed UAVO is set elsewhere in the function.
		if (calibrationCount == (CALIBRATION_IDLE_MS + CALIBRATION_COUNT_MS)/SAMPLING_DELAY_MS_MPXV)
		AirspeedSettingsZeroPointSet(&sensorCalibration);

		return;
	}

	//Get CAS
	float calibratedAirspeed=0;
	if(airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002){
		calibratedAirspeed = PIOS_MPXV7002_ReadAirspeed(airspeedADCPin);
		if (calibratedAirspeed < 0) //This only occurs when there's a bad ADC reading.
		return;

		//Get sensor value, just for telemetry purposes.
		//This is a silly waste of resources, and should probably be removed at some point in the future.
		//At this time, PIOS_MPXV7002_Measure() should become a static function and be removed from the header file.
		//
		//Moreover, due to the way the ADC driver is currently written, this code will return 0 more often than
		//not. This is something that will have to change on the ADC side of things.
		baroAirspeedData->SensorValue=PIOS_MPXV7002_Measure(airspeedADCPin);

	}
	else if(airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV5004){
		calibratedAirspeed = PIOS_MPXV5004_ReadAirspeed(airspeedADCPin);
		if (calibratedAirspeed < 0) //This only occurs when there's a bad ADC reading.
		return;

		//Get sensor value, just for telemetry purposes.
		//This is a silly waste of resources, and should probably be removed at some point in the future.
		//At this time, PIOS_MPXV7002_Measure() should become a static function and be removed from the header file.
		//
		//Moreover, due to the way the ADC driver is currently written, this code will return 0 more often than
		//not. This is something that will have to change on the ADC side of things.
		baroAirspeedData->SensorValue=PIOS_MPXV5004_Measure(airspeedADCPin);

	}
	//Filter CAS
	float alpha=SAMPLING_DELAY_MS_MPXV/(SAMPLING_DELAY_MS_MPXV + ANALOG_BARO_AIRSPEED_TIME_CONSTANT_MS); //Low pass filter.
	float filteredAirspeed = calibratedAirspeed*(alpha) + baroAirspeedData->CalibratedAirspeed*(1.0f-alpha);

	//Set two values, one for the UAVO airspeed sensor reading, and the other for the GPS corrected one
	baroAirspeedData->CalibratedAirspeed = filteredAirspeed;

}
Example #15
0
void baro_airspeedGetAnalog(BaroAirspeedData *baroAirspeedData, portTickType *lastSysTime, uint8_t airspeedSensorType, int8_t airspeedADCPin)
{
	/* Do nothing when driver support not compiled. */
	vTaskDelayUntil(lastSysTime, MS2TICKS(1000));
}
Example #16
0
/**
 * System task, periodically executes every SYSTEM_UPDATE_PERIOD_MS
 */
static void systemTask(void *parameters)
{
	portTickType lastSysTime;
	uint16_t prev_tx_count = 0;
	uint16_t prev_rx_count = 0;
	bool first_time = true;

	/* create all modules thread */
	MODULE_TASKCREATE_ALL;

	if (mallocFailed) {
		/* We failed to malloc during task creation,
		 * system behaviour is undefined.  Reset and let
		 * the BootFault code recover for us.
		 */
		PIOS_SYS_Reset();
	}

	// Initialize vars
	idleCounter = 0;
	idleCounterClear = 0;
	lastSysTime = xTaskGetTickCount();

	// Main system loop
	while (1) {

		// Flash the heartbeat LED
#if defined(PIOS_LED_HEARTBEAT)
		PIOS_LED_Toggle(PIOS_LED_HEARTBEAT);
#endif	/* PIOS_LED_HEARTBEAT */

		// Update the PipXstatus UAVO
		OPLinkStatusData oplinkStatus;
		uint32_t pairID;
		OPLinkStatusGet(&oplinkStatus);
		OPLinkSettingsPairIDGet(&pairID);

		// Get the other device stats.
		PIOS_RFM2B_GetPairStats(pios_rfm22b_id, oplinkStatus.PairIDs, oplinkStatus.PairSignalStrengths, OPLINKSTATUS_PAIRIDS_NUMELEM);

		// Get the stats from the radio device
		struct rfm22b_stats radio_stats;
		PIOS_RFM22B_GetStats(pios_rfm22b_id, &radio_stats);

		// Update the status
		oplinkStatus.DeviceID = PIOS_RFM22B_DeviceID(pios_rfm22b_id);
		oplinkStatus.RxGood = radio_stats.rx_good;
		oplinkStatus.RxCorrected = radio_stats.rx_corrected;
		oplinkStatus.RxErrors = radio_stats.rx_error;
		oplinkStatus.RxMissed = radio_stats.rx_missed;
		oplinkStatus.RxFailure = radio_stats.rx_failure;
		oplinkStatus.TxDropped = radio_stats.tx_dropped;
		oplinkStatus.TxResent = radio_stats.tx_resent;
		oplinkStatus.TxFailure = radio_stats.tx_failure;
		oplinkStatus.Resets = radio_stats.resets;
		oplinkStatus.Timeouts = radio_stats.timeouts;
		oplinkStatus.RSSI = radio_stats.rssi;
		oplinkStatus.AFCCorrection = radio_stats.afc_correction;
		oplinkStatus.LinkQuality = radio_stats.link_quality;
		if (first_time)
			first_time = false;
		else
		{
			uint16_t tx_count = radio_stats.tx_byte_count;
			uint16_t rx_count = radio_stats.rx_byte_count;
			uint16_t tx_bytes = (tx_count < prev_tx_count) ? (0xffff - prev_tx_count + tx_count) : (tx_count - prev_tx_count);
			uint16_t rx_bytes = (rx_count < prev_rx_count) ? (0xffff - prev_rx_count + rx_count) : (rx_count - prev_rx_count);
			oplinkStatus.TXRate = (uint16_t)((float)(tx_bytes * 1000) / SYSTEM_UPDATE_PERIOD_MS);
			oplinkStatus.RXRate = (uint16_t)((float)(rx_bytes * 1000) / SYSTEM_UPDATE_PERIOD_MS);
			prev_tx_count = tx_count;
			prev_rx_count = rx_count;
		}
		oplinkStatus.TXSeq = radio_stats.tx_seq;
		oplinkStatus.RXSeq = radio_stats.rx_seq;
		oplinkStatus.LinkState = radio_stats.link_state;
		if (radio_stats.link_state == OPLINKSTATUS_LINKSTATE_CONNECTED)
			LINK_LED_ON;
		else
			LINK_LED_OFF;

		// Update the object
		OPLinkStatusSet(&oplinkStatus);

		// Wait until next period
		vTaskDelayUntil(&lastSysTime, MS2TICKS(SYSTEM_UPDATE_PERIOD_MS));
	}
}
Example #17
0
static void SensorsTask(void *parameters)
{
	AlarmsClear(SYSTEMALARMS_ALARM_SENSORS);
	
//	HomeLocationData homeLocation;
//	HomeLocationGet(&homeLocation);
//	homeLocation.Latitude = 0;
//	homeLocation.Longitude = 0;
//	homeLocation.Altitude = 0;
//	homeLocation.Be[0] = 26000;
//	homeLocation.Be[1] = 400;
//	homeLocation.Be[2] = 40000;
//	homeLocation.Set = HOMELOCATION_SET_TRUE;
//	HomeLocationSet(&homeLocation);


	PIOS_SENSORS_SetMaxGyro(500);
	// Main task loop
	while (1) {
		PIOS_WDG_UpdateFlag(PIOS_WDG_SENSORS);

		SystemSettingsData systemSettings;
		SystemSettingsGet(&systemSettings);

		switch(systemSettings.AirframeType) {
			case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING:
			case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON:
			case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL:
				sensor_sim_type = MODEL_AIRPLANE;
				break;
			case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX:
			case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP:
			case SYSTEMSETTINGS_AIRFRAMETYPE_VTOL:
			case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA:
			case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO:
				sensor_sim_type = MODEL_QUADCOPTER;
				break;
			case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLECAR:
				sensor_sim_type = MODEL_CAR;
				break;
			default:
				sensor_sim_type = MODEL_AGNOSTIC;
		}
		
		static int i;
		i++;
		if (i % 5000 == 0) {
			//float dT = PIOS_DELAY_DiffuS(last_time) / 10.0e6;
			//fprintf(stderr, "Sensor relative timing: %f\n", dT);
		}
		
		sensors_count++;

		switch(sensor_sim_type) {
			case CONSTANT:
				simulateConstant();
				break;
			case MODEL_AGNOSTIC:
				simulateModelAgnostic();
				break;
			case MODEL_QUADCOPTER:
				simulateModelQuadcopter();
				break;
			case MODEL_AIRPLANE:
				simulateModelAirplane();
				break;
			case MODEL_CAR:
				simulateModelCar();
		}

		vTaskDelay(MS2TICKS(2));

	}
}
/* void delay(int): sleep for given ms-value */
void SystemDelay(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
	if (Param[0]->Val->Integer > 0) {
		vTaskDelay(MS2TICKS(Param[0]->Val->Integer));
	}
}
Example #19
0
/**
 * Module thread, should not return.
 */
static void altitudeHoldTask(void *parameters)
{
	bool engaged = false;

	AltitudeHoldDesiredData altitudeHoldDesired;
	StabilizationDesiredData stabilizationDesired;
	AltitudeHoldSettingsData altitudeHoldSettings;

	UAVObjEvent ev;
	struct pid velocity_pid;

	// Listen for object updates.
	AltitudeHoldDesiredConnectQueue(queue);
	AltitudeHoldSettingsConnectQueue(queue);
	FlightStatusConnectQueue(queue);

	AltitudeHoldSettingsGet(&altitudeHoldSettings);
	pid_configure(&velocity_pid, altitudeHoldSettings.VelocityKp,
		          altitudeHoldSettings.VelocityKi, 0.0f, 1.0f);

	AlarmsSet(SYSTEMALARMS_ALARM_ALTITUDEHOLD, SYSTEMALARMS_ALARM_OK);

	// Main task loop
	const uint32_t dt_ms = 5;
	const float dt_s = dt_ms * 0.001f;
	uint32_t timeout = dt_ms;

	while (1) {
		if ( xQueueReceive(queue, &ev, MS2TICKS(timeout)) != pdTRUE ) {

		} else if (ev.obj == FlightStatusHandle()) {

			uint8_t flight_mode;
			FlightStatusFlightModeGet(&flight_mode);

			if (flight_mode == FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD && !engaged) {
				// Copy the current throttle as a starting point for integral
				StabilizationDesiredThrottleGet(&velocity_pid.iAccumulator);
				velocity_pid.iAccumulator *= 1000.0f; // pid library scales up accumulator by 1000
				engaged = true;
			} else if (flight_mode != FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD)
				engaged = false;

			// Run loop at 20 Hz when engaged otherwise just slowly wait for it to be engaged
			timeout = engaged ? dt_ms : 100;

		} else if (ev.obj == AltitudeHoldDesiredHandle()) {
			AltitudeHoldDesiredGet(&altitudeHoldDesired);
		} else if (ev.obj == AltitudeHoldSettingsHandle()) {
			AltitudeHoldSettingsGet(&altitudeHoldSettings);

			pid_configure(&velocity_pid, altitudeHoldSettings.VelocityKp,
				          altitudeHoldSettings.VelocityKi, 0.0f, 1.0f);
		}

		// When engaged compute altitude controller output
		if (engaged) {
			float position_z, velocity_z, altitude_error;

			PositionActualDownGet(&position_z);
			VelocityActualDownGet(&velocity_z);
			position_z = -position_z; // Use positive up convention
			velocity_z = -velocity_z; // Use positive up convention

			// Compute the altitude error
			altitude_error = altitudeHoldDesired.Altitude - position_z;

			// Velocity desired is from the outer controller plus the set point
			float velocity_desired = altitude_error * altitudeHoldSettings.PositionKp + altitudeHoldDesired.ClimbRate;
			float throttle_desired = pid_apply_antiwindup(&velocity_pid, 
			                    velocity_desired - velocity_z,
			                    0, 1.0f, // positive limits since this is throttle
			                    dt_s);

			if (altitudeHoldSettings.AttitudeComp == ALTITUDEHOLDSETTINGS_ATTITUDECOMP_TRUE) {
				// Throttle desired is at this point the mount desired in the up direction, we can
				// account for the attitude if desired
				AttitudeActualData attitudeActual;
				AttitudeActualGet(&attitudeActual);

				// Project a unit vector pointing up into the body frame and
				// get the z component
				float fraction = attitudeActual.q1 * attitudeActual.q1 -
				                 attitudeActual.q2 * attitudeActual.q2 -
				                 attitudeActual.q3 * attitudeActual.q3 +
				                 attitudeActual.q4 * attitudeActual.q4;

				// Dividing by the fraction remaining in the vertical projection will
				// attempt to compensate for tilt. This acts like the thrust is linear
				// with the output which isn't really true. If the fraction is starting
				// to go negative we are inverted and should shut off throttle
				throttle_desired = (fraction > 0.1f) ? (throttle_desired / fraction) : 0.0f;
			}

			StabilizationDesiredGet(&stabilizationDesired);
			stabilizationDesired.Throttle = bound_min_max(throttle_desired, 0.0f, 1.0f);
			stabilizationDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_ROLL] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
			stabilizationDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_PITCH] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
			stabilizationDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK;
			stabilizationDesired.Roll = altitudeHoldDesired.Roll;
			stabilizationDesired.Pitch = altitudeHoldDesired.Pitch;
			stabilizationDesired.Yaw = altitudeHoldDesired.Yaw;
			StabilizationDesiredSet(&stabilizationDesired);
		}

	}
}
Example #20
0
void os_sleep_ms(int ms)
{
	tm_wkafter(MS2TICKS(ms));
}
Example #21
0
/**
 *
 * @brief   Retrieves an item from the front of a queue.
 *
 * @param[in] queuep       pointer to instance of @p struct pios_queue
 * @param[in] itemp        pointer to item which will be retrieved
 * @param[in] timeout_ms   timeout for retrieving item from queue in milliseconds
 *
 * @returns true on success or false on timeout or failure
 *
 */
bool PIOS_Queue_Receive(struct pios_queue *queuep, void *itemp, uint32_t timeout_ms)
{
	return xQueueReceive((xQueueHandle)queuep->queue_handle, itemp, MS2TICKS(timeout_ms)) == pdTRUE;
}
Example #22
0
/**
 * Main task. It does not return.
 */
static void batteryTask(void * parameters)
{
	const float dT = SAMPLE_PERIOD_MS / 1000.0f;

	settingsUpdatedCb(NULL);

	// Main task loop
	portTickType lastSysTime;
	lastSysTime = xTaskGetTickCount();
	while (true) {
		vTaskDelayUntil(&lastSysTime, MS2TICKS(SAMPLE_PERIOD_MS));

		FlightBatteryStateData flightBatteryData;
		FlightBatterySettingsData batterySettings;
		float energyRemaining;

		if (battery_settings_updated) {
			battery_settings_updated = false;
			FlightBatterySettingsGet(&batterySettings);

			voltageADCPin = batterySettings.VoltagePin;
			if (voltageADCPin == FLIGHTBATTERYSETTINGS_VOLTAGEPIN_NONE)
				voltageADCPin = -1;

			currentADCPin = batterySettings.CurrentPin;
			if (currentADCPin == FLIGHTBATTERYSETTINGS_CURRENTPIN_NONE)
				currentADCPin = -1;
		}

		//calculate the battery parameters
		if (voltageADCPin >= 0) {
			flightBatteryData.Voltage = ((float) PIOS_ADC_GetChannelVolt(voltageADCPin)) / batterySettings.SensorCalibrationFactor[FLIGHTBATTERYSETTINGS_SENSORCALIBRATIONFACTOR_VOLTAGE] * 1000.0f +
							batterySettings.SensorCalibrationOffset[FLIGHTBATTERYSETTINGS_SENSORCALIBRATIONOFFSET_VOLTAGE]; //in Volts
		} else {
			flightBatteryData.Voltage = 0; //Dummy placeholder value. This is in case we get another source of battery current which is not from the ADC
		}

		if (currentADCPin >= 0) {
			flightBatteryData.Current = ((float) PIOS_ADC_GetChannelVolt(currentADCPin)) / batterySettings.SensorCalibrationFactor[FLIGHTBATTERYSETTINGS_SENSORCALIBRATIONFACTOR_CURRENT] * 1000.0f +
							batterySettings.SensorCalibrationOffset[FLIGHTBATTERYSETTINGS_SENSORCALIBRATIONOFFSET_CURRENT]; //in Amps
			if (flightBatteryData.Current > flightBatteryData.PeakCurrent)
				flightBatteryData.PeakCurrent = flightBatteryData.Current; //in Amps
		} else { //If there's no current measurement, we still need to assign one. Make it negative, so it can never trigger an alarm
			flightBatteryData.Current = -1; //Dummy placeholder value. This is in case we get another source of battery current which is not from the ADC
		}

		flightBatteryData.ConsumedEnergy += (flightBatteryData.Current * dT * 1000.0f / 3600.0f); //in mAh

		//Apply a 2 second rise time low-pass filter to average the current
		float alpha = 1.0f - dT / (dT + 2.0f);
		flightBatteryData.AvgCurrent = alpha * flightBatteryData.AvgCurrent + (1 - alpha) * flightBatteryData.Current; //in Amps

		energyRemaining = batterySettings.Capacity - flightBatteryData.ConsumedEnergy; // in mAh
		if (flightBatteryData.AvgCurrent > 0)
			flightBatteryData.EstimatedFlightTime = (energyRemaining / (flightBatteryData.AvgCurrent * 1000.0f)) * 3600.0f; //in Sec
		else
			flightBatteryData.EstimatedFlightTime = 9999;

		//generate alarms where needed...
		if ((flightBatteryData.Voltage <= 0) && (flightBatteryData.Current <= 0)) {
			//FIXME: There's no guarantee that a floating ADC will give 0. So this
			// check might fail, even when there's nothing attached.
			AlarmsSet(SYSTEMALARMS_ALARM_BATTERY, SYSTEMALARMS_ALARM_ERROR);
			AlarmsSet(SYSTEMALARMS_ALARM_FLIGHTTIME, SYSTEMALARMS_ALARM_ERROR);
		} else {
			// FIXME: should make the timer alarms user configurable
			if (flightBatteryData.EstimatedFlightTime < 30)
				AlarmsSet(SYSTEMALARMS_ALARM_FLIGHTTIME, SYSTEMALARMS_ALARM_CRITICAL);
			else if (flightBatteryData.EstimatedFlightTime < 120)
				AlarmsSet(SYSTEMALARMS_ALARM_FLIGHTTIME, SYSTEMALARMS_ALARM_WARNING);
			else
				AlarmsClear(SYSTEMALARMS_ALARM_FLIGHTTIME);

			// FIXME: should make the battery voltage detection dependent on battery type.
			/*Not so sure. Some users will want to run their batteries harder than others, so it should be the user's choice. [KDS]*/
			if (flightBatteryData.Voltage < batterySettings.VoltageThresholds[FLIGHTBATTERYSETTINGS_VOLTAGETHRESHOLDS_ALARM])
				AlarmsSet(SYSTEMALARMS_ALARM_BATTERY, SYSTEMALARMS_ALARM_CRITICAL);
			else if (flightBatteryData.Voltage < batterySettings.VoltageThresholds[FLIGHTBATTERYSETTINGS_VOLTAGETHRESHOLDS_WARNING])
				AlarmsSet(SYSTEMALARMS_ALARM_BATTERY, SYSTEMALARMS_ALARM_WARNING);
			else
				AlarmsClear(SYSTEMALARMS_ALARM_BATTERY);
		}

		FlightBatteryStateSet(&flightBatteryData);
	}
}
Example #23
0
/**
 *
 * @brief   Appends an item to a queue.
 *
 * @param[in] queuep       pointer to instance of @p struct pios_queue
 * @param[in] itemp        pointer to item which will be appended to the queue
 * @param[in] timeout_ms   timeout for appending item to queue in milliseconds
 *
 * @returns true on success or false on timeout or failure
 *
 */
bool PIOS_Queue_Send(struct pios_queue *queuep, const void *itemp, uint32_t timeout_ms)
{
	return xQueueSendToBack((xQueueHandle)queuep->queue_handle, itemp, MS2TICKS(timeout_ms)) == pdTRUE;
}
Example #24
0
/**
 * Module thread, should not return.
 */
static void vtolPathFollowerTask(void *parameters)
{
	SystemSettingsData systemSettings;
	FlightStatusData flightStatus;

	portTickType lastUpdateTime;
	
	VtolPathFollowerSettingsConnectCallback(SettingsUpdatedCb);
	PathDesiredConnectCallback(SettingsUpdatedCb);
	
	VtolPathFollowerSettingsGet(&guidanceSettings);
	PathDesiredGet(&pathDesired);
	
	// Main task loop
	lastUpdateTime = xTaskGetTickCount();
	while (1) {

		// Conditions when this runs:
		// 1. Must have VTOL type airframe
		// 2. Flight mode is PositionHold and PathDesired.Mode is Endpoint  OR
		//    FlightMode is PathPlanner and PathDesired.Mode is Endpoint or Path

		SystemSettingsGet(&systemSettings);
		if ( (systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_VTOL) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_QUADP) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_QUADX) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_HEXA) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_HEXAX) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_HEXACOAX) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_OCTO) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_OCTOV) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXP) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXX) &&
			(systemSettings.AirframeType != SYSTEMSETTINGS_AIRFRAMETYPE_TRI) )
		{
			AlarmsSet(SYSTEMALARMS_ALARM_PATHFOLLOWER,SYSTEMALARMS_ALARM_WARNING);
			vTaskDelay(1000);
			continue;
		}

		// Continue collecting data if not enough time
		vTaskDelayUntil(&lastUpdateTime, MS2TICKS(guidanceSettings.UpdatePeriod));

		// Convert the accels into the NED frame
		updateNedAccel();
		
		FlightStatusGet(&flightStatus);

		// Check the combinations of flightmode and pathdesired mode
		switch(flightStatus.FlightMode) {
			/* This combination of RETURNTOHOME and HOLDPOSITION looks strange but
			 * is correct.  RETURNTOHOME mode uses HOLDPOSITION with the position
			 * set to home */
			case FLIGHTSTATUS_FLIGHTMODE_RETURNTOHOME:
				if (pathDesired.Mode == PATHDESIRED_MODE_HOLDPOSITION) {
					updateEndpointVelocity();
					updateVtolDesiredAttitude();
				} else {
					AlarmsSet(SYSTEMALARMS_ALARM_PATHFOLLOWER,SYSTEMALARMS_ALARM_ERROR);
				}
				break;
			case FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD:
				if (pathDesired.Mode == PATHDESIRED_MODE_HOLDPOSITION) {
					updateEndpointVelocity();
					updateVtolDesiredAttitude();
				} else {
					AlarmsSet(SYSTEMALARMS_ALARM_PATHFOLLOWER,SYSTEMALARMS_ALARM_ERROR);
				}
				break;
			case FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER:
				if (pathDesired.Mode == PATHDESIRED_MODE_FLYENDPOINT ||
					pathDesired.Mode == PATHDESIRED_MODE_HOLDPOSITION) {
					updateEndpointVelocity();
					updateVtolDesiredAttitude();
				} else if (pathDesired.Mode == PATHDESIRED_MODE_FLYVECTOR ||
					pathDesired.Mode == PATHDESIRED_MODE_FLYCIRCLELEFT ||
					pathDesired.Mode == PATHDESIRED_MODE_FLYCIRCLERIGHT) {
					updatePathVelocity();
					updateVtolDesiredAttitude();
				} else {
					AlarmsSet(SYSTEMALARMS_ALARM_PATHFOLLOWER,SYSTEMALARMS_ALARM_ERROR);
				}
				break;
			default:

				for (uint32_t i = 0; i < VTOL_PID_NUM; i++)
					pid_zero(&vtol_pids[i]);

				// Track throttle before engaging this mode.  Cheap system ident
				StabilizationDesiredData stabDesired;
				StabilizationDesiredGet(&stabDesired);
				throttleOffset = stabDesired.Throttle;

				break;
		}

		AlarmsClear(SYSTEMALARMS_ALARM_PATHFOLLOWER);

	}
}
Example #25
0
/**
 * Module thread, should not return.
 */
static void airspeedTask(void *parameters)
{
	AirspeedSettingsUpdatedCb(AirspeedSettingsHandle());
	
	BaroAirspeedData airspeedData;
	AirspeedActualData airspeedActualData;

	airspeedData.BaroConnected = BAROAIRSPEED_BAROCONNECTED_FALSE;
	
#ifdef BARO_AIRSPEED_PRESENT		
	portTickType lastGPSTime = xTaskGetTickCount(); //Time since last GPS-derived airspeed calculation
	portTickType lastLoopTime= xTaskGetTickCount(); //Time since last loop

	float airspeedErrInt=0;
#endif
	
	//GPS airspeed calculation variables
#ifdef GPS_AIRSPEED_PRESENT
	GPSVelocityConnectCallback(GPSVelocityUpdatedCb);		
	gps_airspeedInitialize();
#endif
	
	// Main task loop
	portTickType lastSysTime = xTaskGetTickCount();
	while (1)
	{
		// Update the airspeed object
		BaroAirspeedGet(&airspeedData);

#ifdef BARO_AIRSPEED_PRESENT
		float airspeed_tas_baro=0;
		
		if(airspeedSensorType != AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GPSONLY) {
			//Fetch calibrated airspeed from sensors
			baro_airspeedGet(&airspeedData, &lastSysTime, airspeedSensorType, airspeedADCPin);

			//Calculate true airspeed, not taking into account compressibility effects
			int16_t groundTemperature_10;
			float groundTemperature;
			float positionActual_Down;

			PositionActualDownGet(&positionActual_Down);
			HomeLocationGroundTemperatureGet(&groundTemperature_10); // Gets tenths of degrees C
			groundTemperature = groundTemperature_10/10; // Convert into degrees C
			groundTemperature -= BARO_TEMPERATURE_OFFSET; //Do this just because we suspect that the board heats up relative to its surroundings. THIS IS BAD(tm)

			struct AirParameters air_STP = initialize_air_structure();
			air_STP.air_temperature_at_surface = groundTemperature + CELSIUS2KELVIN;

 #ifdef GPS_AIRSPEED_PRESENT
			//GPS present, so use baro sensor to filter TAS
			airspeed_tas_baro = cas2tas(airspeedData.CalibratedAirspeed, -positionActual_Down, &air_STP) + airspeedErrInt * GPS_AIRSPEED_BIAS_KI;
 #else
			//No GPS, so TAS comes only from baro sensor
			airspeedData.TrueAirspeed = cas2tas(airspeedData.CalibratedAirspeed, -positionActual_Down, &air_STP) + airspeedErrInt * GPS_AIRSPEED_BIAS_KI;
 #endif			
		}
		else
#endif
		{ //Have to catch the fallthrough, or else this loop will monopolize the processor!
			airspeedData.BaroConnected=BAROAIRSPEED_BAROCONNECTED_FALSE;
			airspeedData.SensorValue=12345;
			
			//Likely, we have a GPS, so let's configure the fallthrough at close to GPS refresh rates
			vTaskDelayUntil(&lastSysTime, MS2TICKS(SAMPLING_DELAY_MS_FALLTHROUGH));
		}
		
#ifdef GPS_AIRSPEED_PRESENT
		float v_air_GPS=-1.0f;
		
		//Check if sufficient time has passed. This will depend on whether we have a pitot tube
		//sensor or not. In the case we do, shoot for about once per second. Otherwise, consume GPS
		//as quickly as possible.
 #ifdef BARO_AIRSPEED_PRESENT
		float delT = TICKS2MS(lastSysTime - lastLoopTime) / 1000.0f;
		lastLoopTime=lastSysTime;
		if ( (TICKS2MS(lastSysTime - lastGPSTime) > 1000 || airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_GPSONLY)
				&& gpsNew) {
			lastGPSTime=lastSysTime;
 #else
		if (gpsNew)	{				
 #endif
			gpsNew=false; //Do this first

			//Calculate airspeed as a function of GPS groundspeed and vehicle attitude. From "IMU Wind Estimation (Theory)", by William Premerlani
			gps_airspeedGet(&v_air_GPS);
		}
		
			
		//Use the GPS error to correct the airspeed estimate.
		if (v_air_GPS > 0) //We have valid GPS estimate...
		{
			airspeedData.GPSAirspeed=v_air_GPS;

 #ifdef BARO_AIRSPEED_PRESENT
			if(airspeedData.BaroConnected==BAROAIRSPEED_BAROCONNECTED_TRUE){ //Check if there is an airspeed sensors present...
				//Calculate error and error integral
				float airspeedErr=v_air_GPS - airspeed_tas_baro;
				airspeedErrInt+=airspeedErr * delT;
				
				//Saturate integral component at 5 m/s
				airspeedErrInt = airspeedErrInt >  (5.0f / GPS_AIRSPEED_BIAS_KI) ?  (5.0f / GPS_AIRSPEED_BIAS_KI) : airspeedErrInt;
				airspeedErrInt = airspeedErrInt < -(5.0f / GPS_AIRSPEED_BIAS_KI) ? -(5.0f / GPS_AIRSPEED_BIAS_KI) : airspeedErrInt;
							
				//There's already an airspeed sensor, so instead correct it for bias with P correction. The I correction happened earlier in the function.
				airspeedData.TrueAirspeed = airspeed_tas_baro + airspeedErr * GPS_AIRSPEED_BIAS_KP;
				
				
				/* Note: 
				      This would be a good place to change the airspeed calibration, so that it matches the GPS computed values. However,
				      this might be a bad idea, as their are two degrees of freedom here: temperature and sensor calibration. I don't 
				      know how to control for temperature bias.
				 */
			}
			else
 #endif
			{
				//...there's no airspeed sensor, so everything comes from GPS. In this
				//case, filter the airspeed for smoother output
				float alpha=gpsSamplePeriod_ms/(gpsSamplePeriod_ms + GPS_AIRSPEED_TIME_CONSTANT_MS); //Low pass filter.
				airspeedData.TrueAirspeed=v_air_GPS*(alpha) + airspeedData.TrueAirspeed*(1.0f-alpha);
				
				//Calculate calibrated airspeed from GPS, since we're not getting it from a discrete airspeed sensor
				int16_t groundTemperature_10;
				float groundTemperature;
				float positionActual_Down;

				PositionActualDownGet(&positionActual_Down);
				HomeLocationGroundTemperatureGet(&groundTemperature_10); // Gets tenths of degrees C
				groundTemperature = groundTemperature_10/10; // Convert into degrees C
				groundTemperature -= BARO_TEMPERATURE_OFFSET; //Do this just because we suspect that the board heats up relative to its surroundings. THIS IS BAD(tm)

				struct AirParameters air_STP = initialize_air_structure();
				air_STP.air_temperature_at_surface = groundTemperature + CELSIUS2KELVIN;

				airspeedData.CalibratedAirspeed = tas2cas(airspeedData.TrueAirspeed, -positionActual_Down, &air_STP);
			}
		}
 #ifdef BARO_AIRSPEED_PRESENT
		else if (airspeedData.BaroConnected==BAROAIRSPEED_BAROCONNECTED_TRUE){
			//No GPS velocity estimate this loop, so filter true airspeed data with baro airspeed
			float alpha=delT/(delT + BARO_TRUEAIRSPEED_TIME_CONSTANT_S); //Low pass filter.
			airspeedData.TrueAirspeed=airspeed_tas_baro*(alpha) + airspeedData.TrueAirspeed*(1.0f-alpha);
		}
 #endif
#endif
		//Set the UAVO
		airspeedActualData.TrueAirspeed = airspeedData.TrueAirspeed;
		airspeedActualData.CalibratedAirspeed = airspeedData.CalibratedAirspeed;
		BaroAirspeedSet(&airspeedData);
		AirspeedActualSet(&airspeedActualData);
			
	}
}

	
#ifdef GPS_AIRSPEED_PRESENT
static void GPSVelocityUpdatedCb(UAVObjEvent * ev)
{
	gpsNew=true;
}
#endif

#ifdef BARO_AIRSPEED_PRESENT
void baro_airspeedGet(BaroAirspeedData *baroAirspeedData, portTickType *lastSysTime, uint8_t airspeedSensorType, int8_t airspeedADCPin_dummy)
{
	//Find out which sensor we're using.
	switch (airspeedSensorType) {
		case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002:
		case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV5004:
			//MPXV5004 and MPXV7002 sensors
			baro_airspeedGetAnalog(baroAirspeedData, lastSysTime, airspeedSensorType, airspeedADCPin);
			break;
		case AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_EAGLETREEAIRSPEEDV3:
			//Eagletree Airspeed v3
			baro_airspeedGetETASV3(baroAirspeedData, lastSysTime, airspeedSensorType, airspeedADCPin);
			break;
		default:
			baroAirspeedData->BaroConnected = BAROAIRSPEED_BAROCONNECTED_FALSE;
			vTaskDelayUntil(lastSysTime, MS2TICKS(SAMPLING_DELAY_MS_FALLTHROUGH));
			break;
	}
}
#endif

static void AirspeedSettingsUpdatedCb(UAVObjEvent * ev)
{
	AirspeedSettingsData airspeedSettingsData;
	AirspeedSettingsGet(&airspeedSettingsData);
	
	airspeedSensorType=airspeedSettingsData.AirspeedSensorType;
	gpsSamplePeriod_ms=airspeedSettingsData.GPSSamplePeriod_ms;
	
#if defined(PIOS_INCLUDE_MPXV7002)
	if (airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV7002){
		PIOS_MPXV7002_UpdateCalibration(airspeedSettingsData.ZeroPoint); //This makes sense for the user if the initial calibration was not good and the user does not wish to reboot.
	}
#endif
#if defined(PIOS_INCLUDE_MPXV5004)
	if (airspeedSensorType==AIRSPEEDSETTINGS_AIRSPEEDSENSORTYPE_DIYDRONESMPXV5004){
		PIOS_MPXV5004_UpdateCalibration(airspeedSettingsData.ZeroPoint); //This makes sense for the user if the initial calibration was not good and the user does not wish to reboot.
	}
#endif
}