×

使用LInterp的精确线性磁性位置传感器

消耗积分:0 | 格式:zip | 大小:0.04 MB | 2023-02-03

张燕

分享资料个

描述

本教程向您展示如何“虚拟化”非线性磁性位置传感器,以通过单个函数调用生成精确的线性位置测量值。它使用ProjectHub 教程“ LInterp - 线性插值 PROGMEM 数组生成器”中描述的 LInterp 数组生成器为程序空间内存中的传感器生成线性平移数组 ( )。生成的传感器测量功能不使用 RAM 存储。该方案适用于任何 Arduino 开发板。PROGMEM

一个简单的磁性位置传感器

霍尔效应磁通量传感器(例如本教程中使用的Allegro Microsystems UGN3503 )与放置在被监测运动部件上的小型稀土磁体一起使用时,可成为出色的非接触式短程位置传感器。在必须以非侵入方式(除静磁场之外)将位置传感器安装到现有设备或机械传感器会提供太多运动阻力的情况下,它是理想的选择。它还提供高度的位置分辨率,仅受所选平移阵列大小和 Arduino 板 ADC 的模拟分辨率的限制。

磁通量传感器包括一个小型(约 0.5 平方毫米)霍尔效应晶体管,耦合到一个放大器,采用单个三端低成本塑料晶体管封装。霍尔效应晶体管产生与其两端的磁通密度成正比的电流,放大器将其缩放为零与其电源电压之间的输出电压(UGN3503 旨在使用 5V 电源工作,但可用于较低的分辨率3.3V)。它可以在许多几何结构中用作近静态位置传感器或高频(高达 20KHz)旋转编码器。Allegro 提供详细的设计参考对于设备。作为位置编码器,该传感器需要强而小的磁通量源,例如钕圆盘磁铁,以提供更大的物理范围(毫米)的测量。然而,固定磁铁周围的磁通量密度随距其表面的距离呈非线性变化,因此传感器的输出电压不会随距磁铁的距离呈线性变化。事实上,要计算传感器对于给定磁铁的读数及其相互分离是非常困难的,在实践中,传感器 - 磁铁响应函数被映射在其预期的使用范围内。这必须通过安装在被测设备组件内的传感器和磁铁来完成,以便周围铁质部件产生的环境磁场构成校准的一部分。因此,磁性传感器最适合用于(连续或参考)位置监测的永久安装。

在没有任何外加磁场的情况下(注意:地球的磁场微弱到可以忽略不计),UGN3503 将输出其电源电压的一半,或 2.5V(对于 5V 标称电源)。施加到设备正面(徽标侧)的北 (N) 极性磁场会将输出驱动至零伏,而施加的南 (S) 极性磁场会将输出驱动至电源电压。我们可以通过在传感器上移动磁铁 S 极(见下文)以产生峰值输出电压/位置关系来进行最简单的位置测量。请注意,在没有任何由局部磁场环境强加的不对称性的情况下,磁铁从左侧或右侧朝向传感器的运动会产生相同的传感器输出。

geom1_2KU7s59fnU.jpg?auto=compress%2Cformat&w=740&h=555&fit=max

上述几何结构仅使用传感器输出范围的一半。我们可以通过在所需运动范围的两端使用两个极性相反的磁铁来实现更多的位置分辨率和/或范围,如下所示。

geom2_y47DBbqOH9.jpg?auto=compress%2Cformat&w=740&h=555&fit=max

如图所示,磁铁相对于传感器的运动不必是线性的。磁铁可以旋转或摆动经过传感器。在所有情况下,传感器对磁铁整个运动范围的响应必须以位置增量映射。如果现有组件布局规定磁铁不能靠近传感器 3 毫米以内,则可以将一个小的圆柱形铁质物体(例如 m4 螺钉)作为磁通耦合器端接放置在传感器后面,以增加传感器截获的磁通量密度。

映射传感器输出

为测量函数实现给定精度和准确度所需的映射点数量由所选的线性变换阵列大小和 ADC 分辨率决定。后者形成了硬件可能固定的最终分辨率的上限,但在大多数情况下,专用于阵列的内存是测量精度的主要限制因素。LInterp数组生成器通过自动将数组放置在程序空间 (PROGMEM) 内存,比微控制器 RAM 大得多。这是在编译 Arduino 草图时执行的,因此不需要运行时代码。它还在提供的映射点之间线性插入数组值,因此可以定义大数组以从较少数量的映射点实现高翻译精度。最重要的是,传感器输出以均匀增加(或减少)的位置增量映射,插值器将自动在传感器输出的快速变化(响应梯度或转换率)区域分配更多阵列元素。

要选择阵列大小和映射点密度,首先以所需的输出单位指定线性传感器虚拟化功能的目标功能输出分辨率,并计算所需的模拟设备输出分辨率(以毫伏为单位)以实现所需的功能分辨率产生最小传感器响应梯度的磁铁位置 - 距离传感器最远的磁铁,或直接位于传感器下方的磁铁。假设默认的 Arduino 板 ADC 分辨率为 10 位或 1024 级,模拟参考电压 ( AREF ) 为 5.000V(并记住 ADC 最多只能读取AREF - 1 LSB),我们获得的固有 ADC 分辨率为(大约) 5mV 适用于连接到模拟输入的任何设备。

对于此示例,我们将采用单磁体几何结构,其中磁体位于直径 50mm 的金属圆盘的边缘,旋转金属圆盘以使磁体的 S 极朝向传感器,最小间隔为 3mm。我们选择以度为单位的圆盘方向的输出刻度,我们可以使用三角学通过将指针连接到圆盘并测量其尖端移动的距离来精确测量。我们为(比如说)0.1 度的传感器输出函数指定一个目标角分辨率。通过使用电压表监测传感器的输出,我们发现在距传感器 12 度的磁铁位置处,指针的连续度数增量之间的差异降至 20mV。由于 20mV 大约等于 4 个 ADC 电平,我们在这里获得的“设备”角分辨率仅为 0.25 度,因此 1 度范围内的插值最多会超出 0.13 度(忽略 ADC 误差)。如果我们将这个位置同时作为我们的分辨率规格、范围限制和零位置,那么我们可以计算出与可能的最高分辨率对应的线性平移阵列的最大尺寸:

0度传感器电压:2.62V

12度时传感器电压:4.21V

要求的模拟设备分辨率:5mV

分辨率限制下的最大插值大小:4 个 ADC 级别

最大数组大小= ( 4.21 - 2.62 ) / ( 4 * 0.005 ) = 80 个元素(加上数组插值上限的一个元素)

接下来,我们决定要测量多少个映射点,这取决于我们可以测量圆盘周围指针分度的精度,以及通过在平移数组值的映射点之间使用线性插值来估计我们损失了多少分辨率。后一种约束在检测器响应的最陡峭区域影响最大,在这种情况下,电压表上可以看到磁体位置距传感器 5-6 度,传感器梯度约为每度 500mV。该图对应于我们最大插值大小的 25 个数组元素,但该区域中满足我们选择的角分辨率规范的元素要少得多。这里数组元素的过度分配是我们(整个数组)插值大小规范被设置为传感器响应极限的设备分辨率限制的不可避免结果。如果我们通过取地图中点 6 和 7 的平均值来手动插入电压预测,我们将获得 3.33V 的预测值;测量我们圆盘上这个位置(6.5 度)的实际电压,我们得到 3.29V 或 40mV 的最坏情况插值误差。因此,通过以 1 度的间隔映射传感器并在它们之间进行线性插值,我们可以在任何地方满足我们的角分辨率标准。[进阶说明:如果我们只想在地图的一个区域增加测绘点,使得点间距不规则,那么就必须对整张地图进行正则化。见 测量我们圆盘上这个位置(6.5 度)的实际电压,我们得到 3.29V 或 40mV 的最坏情况插值误差。因此,通过以 1 度的间隔映射传感器并在它们之间进行线性插值,我们可以在任何地方满足我们的角分辨率标准。[进阶说明:如果我们只想在地图的一个区域增加测绘点,使得点间距不规则,那么就必须对整张地图进行正则化。见 测量我们圆盘上这个位置(6.5 度)的实际电压,我们得到 3.29V 或 40mV 的最坏情况插值误差。因此,通过以 1 度的间隔映射传感器并在它们之间进行线性插值,我们可以在任何地方满足我们的角分辨率标准。[进阶说明:如果我们只想在地图的一个区域增加测绘点,使得点间距不规则,那么就必须对整张地图进行正则化。见 那么整个地图必须正则化。见 那么整个地图必须正则化。见LInterp参考教程部分“ Irregularly-spacedordinate mapping sets ”了解详情。]

配置数组生成器

LInDev.h从LInterp参考教程中复制设备虚拟器大纲头文件并将其重命名LInMagSens.h为与草图或其其他头文件中的任何一个。我们在磁盘上以 1 度间隔测量的传感器映射点电压值现在LI_P0以LI_P12毫伏为单位作为定义输入,其余未使用的条目已删除。所有定义在使用后都被数组生成器脚本删除,因此我们需要在和标签处保留数组开始和结束位置(以毫伏为单位)的副本(注意 long-int 类型 'LI_PnLI_MAG_SENS_IN_MINMAG_SENS_IN_MAXL' 后缀以防止任何用户提供的代码中的整数算术溢出)。接下来,我们在MAG_SENS_OUT_标签处定义数组输出缩放,并在 处定义插值大小MAG_SENS_INTERP。这样就完成了数组定义。

模拟电压相对于我们的传感器映射的正确转换至关重要的是实际模拟参考电压,在Arduino板AREF引脚上测量或施加。ADC 使用它来将输入电压缩放到电平,并且必须提供给标签上的阵列发生器,以毫伏为单位。不要假定显示的默认 5000mV 值,因为小型板载 5V 稳压器如果被滥用可能会超出数百 mV。另一种常见的参考电压错误是由于假定AREF的 USB 端口为 5V 电源而引起的。符合标准的 Arduino 板在此电源中包含一个势垒二极管,可降低板的工作电压(和AREFANALOG_RNG)到约4.65V 。由不正确的比例引起的错误ANALOG_RNG表现为变换数组末尾或以上的设备输出级别的变换函数的输出值丢失或无意义,其大小也根据ANALOG_RNG. 还要记住,在AREF引脚上使用的外部参考电压需要代码analogReference( EXTERNAL ); 中的函数调用setup()或MAG_SENS_Setup()器件函数原型。

标LIndev.h头还包括用于设备初始化、数组插值和设备访问的原型函数。这些自动引用上面定义的自定义值标签并且无需修改即可工作。根据需要添加或更改这些函数,以隔离一个头文件中的所有特定于设备的代码,并为来自底层设备的测量生成单个函数调用。未使用的功能不会上传到 Arduino 开发板。在我们的示例中,该函数MAG_SENS_ReadAvg()被包装在一个名为的宏中,该宏Position()将圆盘的当前角度作为一个float值返回。存根程序LInMagSens.ino只是打开与 Arduino IDE 串行监视器的串行通信,并返回对Position()函数的连续调用序列。

完成的设备虚拟器没有使用 RAM 和约 700 字节的代码空间内存,包括约 350 字节的数组。使用的pgmspace.h库和analogRead()函数一起占用大约 1.3K 的代码空间内存,这不会添加到进一步的设备定义中。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'使用LInterp的精确线性磁性位置传感器',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);