38、观测量读取任务实现

\qquad 下面是HD-GR GNSS导航软件的观测量读取任务实现代码,入口函数meas_task(…)

// main_measure.c -- Grab measurements each TIC interrupt (~100ms).

/* 
 * Copyright (C) 2005 Andrew Greenberg
 * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
 * See the "COPYING" file distributed with this software for more information.
 */

/* Namuru GPS receiver project
 * Original : measure.c
 * Modes    : Some code has been modified for adaption to the Namuru HW by Peter Mumford
 * version  : V1.0
 * date     : 21st/Dec/2006
 */

/* 
 * HD-GR GNSS receiver project
 * Modes    : Inherited the code of measure.c in the Namuru GPS receiver project V1.0 
 *            and made necessary adjustments to adapt to the new HW, RTOS and functions.
 * version  : V1.0
 * date     : xx/xx/2015
 */

#include <io.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "includes.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "main_measure.h"
#include "gps_accum_task.h"
#include "b1i_accum_task.h"
#include "gps_message.h"
#include "b1i_message.h"
#include "main_pseudorange.h"
#include "main_position.h"


/******************************************************************************
 * Globals
 ******************************************************************************/

OS_EVENT *m_SemMeas;
measurement_t m_raw_meas;
OS_FLAGS channels_meas_ready;

void initialize_measurements( void)
{
	unsigned short ch;
	for (ch = 0; ch < TOT_MAX_CHANNELS; ch++) {
		m_raw_meas.chan_meas[ch].valid = 0;
	}
}

void grab_bit_times( void)
{
	unsigned short ch = 0, ch1 = 0;

	GNSS_ENTER_CRITICAL();
	for (; ch < GPS_MAX_CHANNELS; ch++) {
		m_raw_meas.chan_meas[ch].sync_bit_time = m_GPS_CH[ch].time_in_bits;
	}
	for (; ch < TOT_MAX_CHANNELS; ch++, ch1++) {
		m_raw_meas.chan_meas[ch].sync_bit_time = m_B1I_CH[ch1].time_in_bits;
	}
	GNSS_EXIT_CRITICAL();
}

void fill_ch_pars( void)
{
	unsigned short ch, ch1;
    unsigned short ch_index;

	if (m_sys_posconst & POS_CONSTELL_GPS) {
		// If the channel is 1) locked and 2) the signal is good and 3) the
		// clock is set vaguely correctly and 4) we've set the epoch counter
		// for this channel, THEN grab the measurement data.
		ch_index = GPS_CH00_BASE;

		GNSS_ENTER_CRITICAL();
		for (ch = 0; ch < GPS_MAX_CHANNELS; ch++) {
			if ((m_GPS_CH[ch].state == CHANNEL_LOCK) &&
				(m_GPS_CH[ch].p_mag > LOCK_THRESHOLD) &&
				(m_gps_messages[ch].set_epoch_flag) &&
				(m_GPS_CH[ch].sync_20ms_epoch_count == 0)) {
				// Note: meas_bit_time set in grab_bit_times() above.
				m_raw_meas.chan_meas[ch].meas_bit_time = m_raw_meas.chan_meas[ch].sync_bit_time;
				m_raw_meas.chan_meas[ch].doppler = m_GPS_CH[ch].carrier_freq;
				m_raw_meas.chan_meas[ch].prn = m_GPS_CH[ch].prn;
				m_raw_meas.chan_meas[ch].power = m_GPS_CH[ch].p_mag;
				m_raw_meas.chan_meas[ch].valid = 1;
			// Can't use this measurement
			else {
				m_raw_meas.chan_meas[ch].valid = 0;
			}

			// increment channel index to top of next channel map
			ch_index += CH_BASE_STEP;
		}
		GNSS_EXIT_CRITICAL();
	}

	if (m_sys_posconst & POS_CONSTELL_BDS) {
		// If the channel is 1) locked and 2) the signal is good and 3) the
		// clock is set vaguely correctly and 4) we've set the epoch counter
		// for this channel, THEN grab the measurement data.
		ch_index = B1I_CH00_BASE;

		GNSS_ENTER_CRITICAL();
		for (ch1 = GPS_MAX_CHANNELS, ch = 0; ch1 < TOT_MAX_CHANNELS; ch1++, ch++) {
			if ((m_B1I_CH[ch].state == CHANNEL_LOCK) &&
				(m_B1I_CH[ch].p_mag > LOCK_THRESHOLD) &&
				(m_b1i_messages[ch].set_epoch_flag) &&
				(m_B1I_CH[ch].sync_20ms_epoch_count == 0)) {
				// Note: meas_bit_time set in grab_bit_times() above.
				m_raw_meas.chan_meas[ch1].meas_bit_time = m_raw_meas.chan_meas[ch1].sync_bit_time;
				m_raw_meas.chan_meas[ch1].doppler = m_B1I_CH[ch].carrier_freq;
				m_raw_meas.chan_meas[ch1].prn = m_B1I_CH[ch].prn;
				m_raw_meas.chan_meas[ch1].power = m_B1I_CH[ch].p_mag;
				m_raw_meas.chan_meas[ch1].valid = 1;
			}
			else {
				m_raw_meas.chan_meas[ch1].valid = 0;	// Can't use this measurement
			}

			// increment channel index to top of next channel map
			ch_index += CH_BASE_STEP;
		}
		GNSS_EXIT_CRITICAL();
	}
}

void gps_meas_task()
{
	unsigned short ch;
    unsigned short ch_index;
	unsigned short raw_epoch;
	unsigned long  long_temp;
    unsigned short bit_count_remainder;
    unsigned long  bit_count_modded, bit_time, meas_bit_time;

	// Grab the measurement data.
	ch_index = GPS_CH00_BASE;
	for (ch = 0; ch < GPS_MAX_CHANNELS; ch++) {
		if (m_raw_meas.chan_meas[ch].valid) {
			// Grab the latched data from the correlators (in their
			// numerical order -- go optimized compiler, go!)

			long_temp = read_from_correlator( ch_index + CODE_MEASUREMENT );
			m_raw_meas.chan_meas[ch].code_phase = (unsigned short)((long_temp >> 10) & 0x7FF);	// bits [20:10]
			m_raw_meas.chan_meas[ch].code_dco_phase = (unsigned short)(long_temp & 0x3FF);		// bits [9:0]

#ifdef ENABLE_CARRIER_PHASE_MEASUREMENT
			long_temp = read_from_correlator( ch_index + CARRIER_MEASUREMENT );
			m_raw_meas.chan_meas[ch].carrier_cycles = long_temp >> 10;							// bits [31:10]
			m_raw_meas.chan_meas[ch].carrier_dco_phase = (unsigned short)(long_temp & 0x3FF);	// bits [9:0]
#endif // ENABLE_CARRIER_PHASE_MEASUREMENT

			raw_epoch = (unsigned short)(read_from_correlator( ch_index + EPOCH ));
			m_raw_meas.chan_meas[ch].epoch_bits  = (raw_epoch >> 5) & 0x3F;						// bits [10:5]
			m_raw_meas.chan_meas[ch].epoch_codes = raw_epoch & 0x1F;							// bits [4:0]

			// Fix up in case the epoch counter is on a different side of
		    // a 50 bit "word" from us.
			bit_time = m_raw_meas.chan_meas[ch].meas_bit_time;
		    bit_count_remainder = bit_time % 50;
			bit_count_modded = bit_time - bit_count_remainder;
		    if ((bit_count_remainder < 10) && (m_raw_meas.chan_meas[ch].epoch_bits > 40))
		        bit_count_modded -= 50;
		    if ((bit_count_remainder > 40) && (m_raw_meas.chan_meas[ch].epoch_bits < 10))
		        bit_count_modded += 50;

		    meas_bit_time = bit_count_modded + m_raw_meas.chan_meas[ch].epoch_bits;
		    m_raw_meas.chan_meas[ch].meas_bit_time = meas_bit_time;
			// check meas_bit_time
			if (labs(bit_time-meas_bit_time) >= 10) {
				m_gps_messages[ch].set_epoch_flag = 0;
			}

			// Tell the pseudorange thread which measurements it can use.
			// Note that we don't want to just call the pr thread from here
			// because we're in a DSR and should get out ASAP
			channels_meas_ready |= (1 << ch);
		}

		// increment channel index to top of next channel map
		ch_index += CH_BASE_STEP;
	}
}

void b1i_meas_task()
{
	unsigned short ch, ch1;
    unsigned short ch_index;
	unsigned short raw_epoch;
	unsigned long  long_temp;
    unsigned short bit_count_remainder;
    unsigned long  bit_count_modded, bit_time, meas_bit_time;

	// Grab the measurement data.
	ch_index = B1I_CH00_BASE;
	for (ch1 = GPS_MAX_CHANNELS, ch = 0; ch1 < TOT_MAX_CHANNELS; ch1++, ch++) {
		if (m_raw_meas.chan_meas[ch1].valid) {
			// Grab the latched data from the correlators (in their
			// numerical order -- go optimized compiler, go!)

			long_temp = read_from_correlator( ch_index + CODE_MEASUREMENT );
			m_raw_meas.chan_meas[ch1].code_phase = (short)(long_temp >> 11);			// bits [22:11]
			m_raw_meas.chan_meas[ch1].code_dco_phase = (short)(long_temp & 0x7FF);		// bits [10:0]

#ifdef ENABLE_CARRIER_PHASE_MEASUREMENT
			long_temp = read_from_correlator( ch_index + CARRIER_MEASUREMENT );
			m_raw_meas.chan_meas[ch1].carrier_cycles = long_temp >> 10;					// bits [31:10]
			m_raw_meas.chan_meas[ch1].carrier_dco_phase = (short)(long_temp & 0x3FF);	// bits [9:0]
#endif // ENABLE_CARRIER_PHASE_MEASUREMENT

			raw_epoch = (short)(read_from_correlator( ch_index + EPOCH ));
			m_raw_meas.chan_meas[ch1].epoch_bits  = raw_epoch >> 5;
			m_raw_meas.chan_meas[ch1].epoch_codes = raw_epoch & 0x1f;

			// Fix up in case the epoch counter is on a different side of
		    // a 50 bit "word" from us.
			bit_time = m_raw_meas.chan_meas[ch1].meas_bit_time;
		    bit_count_remainder = bit_time % 50;
			bit_count_modded = bit_time - bit_count_remainder;
		    if ((bit_count_remainder < 10) && (m_raw_meas.chan_meas[ch1].epoch_bits > 40))
		        bit_count_modded -= 50;
		    if ((bit_count_remainder > 40) && (m_raw_meas.chan_meas[ch1].epoch_bits < 10))
		        bit_count_modded += 50;

		    meas_bit_time = bit_count_modded + m_raw_meas.chan_meas[ch1].epoch_bits;
		    m_raw_meas.chan_meas[ch1].meas_bit_time = meas_bit_time;
			// check meas_bit_time
			if (labs(bit_time-meas_bit_time) >= 10) {
				m_b1i_messages[ch].set_epoch_flag = 0;
			}

			// Tell the pseudorange thread which measurements it can use.
			// Note that we don't want to just call the pr thread from here
			// because we're in a DSR and should get out ASAP
			channels_meas_ready |= (1 << ch);
		}

		// increment channel index to top of next channel map
		ch_index += CH_BASE_STEP;
	}
}


void set_pps_org( double seconds, pvt_share_t* ppvt_share)
{
	double ms;
	long tic, delay;
	clock_state_t clk_state = get_clock_state();
	pps_state_t pps_state = get_pps_state();
	static long pvt_id = 0;
	static long pps_org_ofs = 0;				// unit: ns
	static int pps_tic_slew = 0;				// unit: clock
	static long pps_tic_add1 = VALUE_TIC_ADD1;	// unit: clock
	static double tm_ofs_start = 0;				// unit: GPS second

	switch (pps_state) {
	// 用本地时钟校准TIC
	case PPS_INIT_ED:
		if (clk_state >= SF1_CLOCK) {
			seconds -= (long)seconds;
			tic = m_raw_meas.meas_tic - (long)(seconds*10.0 + 0.5);
			if (tic < 0) tic += 10;
			load_tic_count(tic);
			set_pps_state(PPS_TIC_ED);
		}
		break;

	// 用定位解算时间将TIC校准到1个ACCUM_INT准确性, 缺省约0.78ms
	case PPS_TIC_ED:
		if ((ppvt_share->valid) &&			// 定位解算有效
			(ppvt_share->id > 1) && 			// 非第1次有效解算
			(fabs(ppvt_share->bs) < 1.0E-5)) {// 时钟偏差小于10微秒
			ms = seconds - (long)seconds;			// 取小数秒
			ms = seconds*10.;						// 以0.1秒为单位
			tic = (long)ms;							// 得TIC计数值
			ms -= tic;								// 得1个TIC中的小数
			ms *= TIC_2_ACCUM_DIV;					// 以ACCUM_INT间隔为单位
			delay = (long)ms;						// 总ACCUM_INT计数
			if (delay == 0) {
				load_tic_count(tic % 10);			// load tic count
			}
			else {
				ms -= delay;						// 得ACCUM_INT余数
				delay *= (VALUE_ACCUM_INT+1);		// 当前TIC时钟位置
				delay = (VALUE_TIC_DIV+1) - delay;	// 要延迟的时钟数
				load_tic_count((++tic) % 10);		// 将TIC计数加1
				set_tic_delay(delay, 0, 0);			// 延迟到TIC起点
			}
			// 保存剩余延迟值,单位: 纳秒
			pps_org_ofs = (long)(ms*((1.0E+8)/TIC_2_ACCUM_DIV));
			// 保存当前时间
			tm_ofs_start = seconds;
			set_pps_state(PPS_ORG_ING);
		}
		break;

	// 精细校准TIC原点
	case PPS_ORG_ING:
		// 异常情况处理: 假设时钟漂移小于1微秒/s(1PPM)且允许在50s内完成
		// 精细校准, 因此精细校准期间累积的时钟漂移值不应大于50微秒.
		if (!ppvt_share->valid) {
			seconds -= tm_ofs_start;
			if (seconds < 0) seconds += SECONDS_IN_WEEK;
			if (seconds > 50) set_pps_state(PPS_TIC_ED);
			break;
		}

		// 延迟100微秒
		if (pps_org_ofs >= 100000) {
			// 100毫秒 = 1000*100微秒
			delay = VALUE_TIC_ADD1/1000;
			set_tic_delay(-delay, 0, 1);
			pps_org_ofs -= 100000;
		}
		// 延迟剩余微秒
		else if (pps_org_ofs >= 1000) {
			// 取微秒数
			tic = pps_org_ofs/1000;
			delay = (tic*VALUE_TIC_ADD1)/100000;
			set_tic_delay(-delay, 0, 1);
			pps_org_ofs -= tic*1000;
		}
		// 延迟微秒小数
		else if (pps_org_ofs > 0) {
			// 以0.1秒为单位计算延迟值
			ms = (double)pps_org_ofs*(1.0E-8);
			delay = (long)(ms*(double)VALUE_TIC_ADD1);
			set_tic_delay(-delay, 0, 1);
			pps_org_ofs = 0;
		}

		// TIC原点校准结束
		if (pps_org_ofs < 10) {
			pvt_id = ppvt_share->id;
			pps_org_ofs = 0;
			pps_tic_slew = 0;
			pps_tic_add1 = VALUE_TIC_ADD1;
			set_pps_state(PPS_OFS_ING);
		}
		break;

	// 校准TIC漂移
	case PPS_OFS_ING:
		// 异常情况处理: 假设时钟漂移小于1微秒/s(1PPM)且允许在最长50s内
		// 完成漂移校准, 因此漂移校准期间积累的漂移值不应大于50微秒, 加上
		// "精细校准TIC原点"可能传递过来的50微秒最大漂移,从而总漂移值不
		// 应大于100微秒.
		if (!ppvt_share->valid) {
			seconds -= tm_ofs_start;
			if (seconds < 0) seconds += SECONDS_IN_WEEK;
			if (seconds > 50) set_pps_state(PPS_TIC_ED);
			break;
		}

		// 自TIC原点校准结束后,至少完成了1次有效解算, 且时钟偏差小于10微秒
		if ((ppvt_share->id < (pvt_id+1)) ||
			(fabs(ppvt_share->bs) > 1.0E-5)) {
			break;
		}

		// 计算时间差
		ms = seconds - tm_ofs_start;
		if (ms < 0) ms += SECONDS_IN_WEEK;
		// 以约2秒为间隔调整延迟
		if (ms >= 2) {
			long slew, mod;
			tic = (long)(ms*10.0 + 0.5);		// 实际TIC次数
			ms = (seconds-(long)seconds);		// 取整秒尾数
			ms *= (1.0E+4);						// 以100微秒为单位
			ms -= (long)(ms+0.5);				// 取100微秒尾数
			ms *= (double)pps_tic_add1/1000.;	// 转换为时钟数
			slew = (long)(ms*10.0/tic+0.5);		// 计算1秒钟上的延迟量
			mod = labs(slew) % 10;				// 计算平均延迟后的余量
			slew /= 10;							// 计算平均延迟量
			if (labs(slew) >= 128) {			// 每个TIC上的延迟量太大
				set_pps_state(PPS_TIC_ED);		// 回到PPS_TIC_ED状态
			}									// 正常时这不应出现
			delay = (long)(ms+0.5);				// 截止上个TIC时间点的总延迟量
			delay += 2*slew;					// 附加在2个TIC时间区间中的延迟量
			pps_tic_slew -= slew;
			pps_tic_add1 = VALUE_TIC_ADD1 + pps_tic_slew;
			set_tic_slew(-delay, pps_tic_slew, mod);

			pvt_id = ppvt_share->id;
			tm_ofs_start = seconds;
		}
		break;

	case PPS_OFS_ED:
	default:
		break;
	}
}

/******************************************************************************
 * Grab the latched measurement data from the accumulators after a TIC.
 ******************************************************************************/
void meas_task(void* pdata)
{
	INT8U err;

	m_SemMeas = OSSemCreate(0);

	while (1) {
		OSSemPend(m_SemMeas, 0, &err);

		// wake up when the ACCUM DSR detects a new TIC
		if (get_clock_state() >= SF1_CLOCK) {
			// Get the current GPS time to mark the time of measurement
			m_raw_meas.meas_time = get_time();
			m_raw_meas.meas_tic = (unsigned short)read_from_correlator(TIC_COUNT);

			channels_meas_ready = 0;
			if ((m_raw_meas.meas_tic % 2) == 0) {
				b1i_meas_task();
				channels_meas_ready <<= GPS_MAX_CHANNELS;
				gps_meas_task();
			}

			// And finally, flag all the valid measurements to the pseudorange
			// thread and if there are none, but there were last TIC, then
			// explicitely clear the pseudoranges.
			if (channels_meas_ready) {
				calculate_pseudorange(channels_meas_ready);
			}

			// Finally, make sure we didn't miss any other posts to the measure
			// semaphore- if we did, complain about it.
			err = OSSemAccept(m_SemMeas);
			if (err > 0) {
#ifdef ENABLE_TRACKING_LOG
				printf("MEASURE THREAD: MISSED SEMAPHORE.\r\n");
#endif // ENABLE_TRACKING_LOG
				do {
					err = OSSemAccept(m_SemMeas);
				} while(err > 0);
			}
			else {
				pvt_share_t pvt_share;

				// Transfer solution status and local clock bias to measure thread.
#ifdef GNSS_ENABLE_MUTEX
				OSMutexPend(m_PrCbsMutex, 0, &err);
#endif
				pvt_share = m_pvt_share;
#ifdef GNSS_ENABLE_MUTEX
				OSMutexPost(m_PrCbsMutex);
#endif
				set_pps_org(m_raw_meas.meas_time.seconds, &pvt_share);
			}
		}
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BLDC(无刷直流电机)滑膜观测器是一种用于监测无刷电机滑动摩擦状况的传感器。在C语言中,您可以按照以下步骤来实现BLDC滑膜观测器: 1. 引入必要的头文件:根据使用的硬件和传感器,引入相应的文件,例如ADC(模数转换器)和GPIO(通用输入输出)等。 2. 初始化硬件:根据您的硬件配置,进行初始化设置,包括ADC和GPIO的初始化。 3. 读取传感器数值:使用ADC模块读取与滑膜观测器连接的传感器的模拟数值。这些传感器可以是用于监测电机电流、速度或其他相关参数的传感器。 4. 转换数值:根据ADC的配置和参考电压等参数,将模拟数值转换为实际物理,例如电压、电流或速度等。 5. 处理数据:根据实际需求,对转换后的数据进行处理。例如,可以使用滑动平均或滤波等算法对数据进行平滑处理。 6. 判断滑膜情况:根据处理后的数据,通过一定的算法或阈值判断滑膜的磨损情况或摩擦状态。这可以涉及比较当前数值与之前的数值,或者与预设的阈值进行比较。 7. 输出结果:根据判断结果,可以使用GPIO控制LED灯或其他设备来输出滑膜的状态或发出警报。 需要注意的是,具体的实现细节和代码将取决于您使用的硬件平台、传感器类型以及BLDC电机控制算法。您可能需要参考硬件和传感器的文档以及相关的C语言库函数来完成这个任务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值