多通道采集器采样接口设计

1.技术问题

这是一个非常小的设计,完全不值得把它展示出来。但是因为这个接口设计关系到一些细微的配置和技术限制,仍然有一些细节需要处理,并且很容易出错,我们先把技术问题罗列一下:

  1. 多个传感器对应的多个逻辑通道需要同步采样。
  2. 逻辑通道数量超出了物理采集器的极限,需要多台采集器同时工作。
  3. 各个逻辑通道的采样率,采样点数可能都不相同。
  4. 有些通道不需要采集太多数据,而有些通道需要连续采集大量数据。
  5. 多通道、高采样率采样时在同一个采集器上,可能会遭遇物理采集器的极限。
  6. 采样时因为电源因素,可能会涉及到预采样部分数据点。
  7. 在采集到一组数据后要尽快上传,因为后续对数据分析也是高耗时过程。
  8. 数据分析过程包含各个通道的分析,和关联通道分析。

2.接口设计

有兴趣的同志可以自行搭建自己的接口设计,不需要填充代码,只需要把接口和功能描述给出即可。我稍后上传我的设计文档。

2.1 采集层的接口设计

2.1.1 对外接口

#define MAX_CH_PER_HUB 128
typedef struct _sensor_shake_sample_params
{
	int magicNumber;
    bool isInited;
	const char *ipaddr; //采集器地址
	int chCnts;  //本采集器相关的本次采集通道数量:total channel to sample
	uint16_t* nBinArray;
	//uint16_t* innerBuff;
	int lenOfBufInBytes;
	float saps;
	int ptps;
	void *hDevice;
	int volStandard; //采集器电平标准
	int chIdxBase1Total_asHubChFirst; //当前采集器第一个通道对应的全体传感器阵列逻辑通道编号
	uint8_t maskOfChannelToSample[MAX_CH_PER_HUB/8]; //最高支持MAX_CH_PER_HUB路的单个采集器采样掩码位(小端模式)
}Sensor_shake_sample_params, *LPSensor_shake_sample_params;

//启动一次采样,异步
int sensor_shake_start_sample(Sensor_shake_sample_params *pparams);
//得到最近一个采样的结果
int sensor_shake_getSampleResult(Sensor_shake_sample_params *pparams);
//关闭采集设备
int sensor_shake_close(Sensor_shake_sample_params *params);
//采集结果转储
void sensor_sampleBuf2chBuff(uint16_t *tgtBuf, Sensor_shake_sample_params *pparams, int idx0OfSampleResult);

2.1.2 内部辅助函数

因为涉及到必须的预采样和物理采集通道编号、物理采集结果编号、和逻辑传感器阵列编号的转换,必须额外提供两个辅助函数(事实上它不够,参见A1部分):

int sensor_get_idxbase1Total(int chIdxbase1OfSampleResult, Sensor_shake_sample_params *pparams);
int getMoreSapsCntOfDataSampleBegin(float saps);


int getMoreSapsCntOfDataSampleBegin(float saps)
{
    int moreSamplesIn100ms = ceil(100e-3*saps);  #magic number 100e-3 = 100ms
    return moreSamplesIn100ms;
}

int sensor_get_idxbase1Total(int chIdxbase1OfSampleResult, Sensor_shake_sample_params *pparams)
{
	int ret = 0;
	int chAbsOfIdx1OfHubFirstCh = pparams->chIdxBase1Total_asHubChFirst;
    //仅打开需要开通的通道:
    int nChannel = 0;	
	int idxBase0OfHub = 0;
    for(int iCh = 0; iCh<sizeof(pparams->maskOfChannelToSample);++iCh)
	{
		for(int jCh=0; jCh<8;++jCh)
		{
			if(pparams->maskOfChannelToSample[iCh]&(1<<jCh))
			{
				idxBase0OfHub = iCh*8+jCh;
			}
			nChannel++;
			if(nChannel == chIdxbase1OfSampleResult) return (chAbsOfIdx1OfHubFirstCh + idxBase0OfHub);
		}
	}
	return -1;
}

2.1.3 配置变更 

配置文件事实上无需更新:因为采集速率不足的计算和拆分是自动进行的。

不过如果之前因为

2.2 技术问题

2.2.1 传感器阵列配置到采集任务拆分的辅助转换接口

这部分工作是进行与采样相关的多采集器并行加速以及在采集器物理极限达到时,必须进行的采集任务顺次拆分。

注意分布采集时,因为必然会涉及到通道配置的修改,这个时候可能需要对采集器的接口封装进行修改。比如之前因为采集过程不涉及到采集的通道变动,所以,start_sample()可以把open_sample_dev封在内部,此时,可能更合适的做法是将其暴露处理。类似这样。起码在内部逻辑设计时要注意。另外,因为涉及到额外的接口配置切换,所以后续,针对性的重试,部分数据的处理也需要跟进。

2.2.2 采集器传输故障

实际测试时,发现传感器采集器与主机之间的网络通道可能因为网络或者CPU占有率之类的因素导致出现软硬件error,出现这种情况时,因为没有额外的检验标准,该批次数据必须全部放弃,所以,现在的处理是等待所有采集器采集完毕后才发起计算任务。

2.2.3 计算的同步

之前为了能够让计算过程尽快的完成,每个计算进程是独立控制的。事实上似乎不需要这样做。因为各个逻辑通道的计算进程结束后,总会有等待并发起对设备的总体状况进行侦测和报告的过程。所以,现在把对计算线程的等待按常规方法做了——等待所有进程结束,然后在进行下一步:

                    dumb050904();
                    for (ti = 0; ti < gSensorDesc.hubs[i].idOfExecThreadCnt; ++ti) {
                        waitpid(gSensorDesc.hubs[i].idOfExecThread[ti], &status, 0); // Wait for acc calc to exit
                    }
                    dumb050904_1();

dumb函数是为了gdb调试用途做的空函数。

2.2.4 预采样

 这个问题已经另行专门讨论,参见:加速度传感器采集时无效数据的产生及消除-CSDN博客

附录A 易错项登记,处理建议

A.1 易错项 - 通道索引转换

1.各类索引号的转换,是最容易出错的部分,调试时大部分问题都源自这里。要仔细核对各个idx的互转函数的命名。建议所有的接口互转能够自动进行。

2.为了防止转换失败,建议在程序中对重要的数据结构引入debug阶段的校验机制。

后记:设计失误

采集到计算环节,我没有使用类似mqtt,redis之类的中间件,是我的最大设计失误。上面的设计仍然在延续这个错误。看过我的系列帖子的同志应该看到过,我始终倾向于使用自制的协议和算法。

前面我设计了使用memory-map来构建在c/python之间传递数据的方案,事实上,这个部分做起来显得稍稍复杂,并且一旦涉及变动io相关的数据结构,相关修改会比较麻烦。很容易出错。它的一些转换代码会出现类似“2048fIII4s”之类的符文。。。并且因为涉及跨线程,所有的改动,你需要做两次。

然后,一旦引入标准的中间件,调试的难度会降低不止一个数量级,它们可以通过第三方工具随时查看,甚至是远端。然后序号的问题会变得不存在。

最近的周末,我大概工作了24个小时,大部分时间都浪费在idx转换,同步,数据结构彼此的转换和同步上。回想起来真是愚蠢。

memorymap最早用的时候,它还有一个副作用。windows 和linux 平台的代码不兼容。浪费这些时间真是不值。。。。

在无法找到方便的商业方案的情况下,再考虑用二极管搭建电路,这应该是个设计的基本准则。希望自己能记得这个教训。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值