用ASEK dll进行高级编程
用ASEK dll进行高级编程
作者:k·罗伯特·贝特
雷竞技竞猜下载快板微系统公司有限责任公司
简介
从工业自动化和机器雷竞技最新网址人,到电子动力转向和电机位置传感,许多行业的应用都需要监测转轴在轴上或轴外的角度。
当在设计中使用磁铁时,在整个旋转范围内,磁输入极有可能不是均匀的——它会有固有误差。这些磁输入误差导致了系统的测量误差。线性化可以减少这些输入误差。
线性化的一种形式是A1332而且A1335,谐波线性化采用线性化的形式,最多15个校正谐波,其相位和振幅由FFT(快速傅立叶变换)对围绕角度传感器IC旋转的磁铁收集的数据进行确定。该技术可以很容易地使用allegro提供的软件计算系数和芯片上的EEPROM程序来实现。当allegro提供的软件不够灵活或者需要使用定制软件时,此应用说明描述了客户可以使用的功能和流程。
编程需求
所有的软件都是在Microsoft Visual Studio 2010上使用。net 4.0开发的。下载您将要使用的设备的命令库(c# /. net),并向项目中添加对其中包含的三个dll的引用。
收集数据
首先,关闭所有后线性化算法处理;这包括零偏移,后线性化旋转(RO),短行程反转(IV)和旋转模位(RD)。预线性化调整可以保留,如oror设置,IIR滤镜(FI)和预线性化旋转(LR)。
向增加角度位置的方向移动编码器。如果角度传感器IC输出也没有增加,那么要么设置LR位以反转角度传感器IC输出的方向,要么将编码器向相反的方向旋转进行校准,在这种情况下,可能需要设置后线性化旋转位(RO)。有关更多细节,请参阅A1332/ A1335编程参考。
最佳的收集方法是以等间隔的步骤旋转目标,这样得到的数据点的数量是2的幂。通常,32或64个均匀间隔的数据点就足够了。如果不能做到这一点,那么就收集这些点,并且必须对数据进行预处理,这将在下一节中讨论。
收集所需数据点的另一种技术是多次旋转目标,以预定义的间隔收集数据。一旦收集了足够多的点以覆盖目标的整个旋转,那么必须对它们进行预处理,如下一节所讨论的那样。
预处理的数据
如果收集的数据点的数量不是2的幂,或者收集的数据不是等间隔的,那么必须调整点数组的大小和/或使其为等间隔的。要对数据执行此操作,请调用例程ResizePointArray。
x参数是编码器值的数组,y参数是在编码器值处收集的设备读数。参数newSize是调整后的数组所需的大小。如果x参数被设置为null,那么y值被假定以从0开始到以360结束的相等间距收集。如果x参数不为空,则在执行调整大小之前对输入数组进行排序。
double[] ResizePointArray(double[] x, double[] y, int newSize)
这个例程将对输入数组执行三次样条插值,以生成具有所需点数的等间距数组。
初步处理
一旦收集到数据并将其制成长度为2的幂的数组,就可以计算谐波系数了。要计算系数,调用例程CalculateHarmonicLinearCoefficients。
HarmonicCoefficients[] CalculateHarmonicLinearCoefficients (double[] points, out bool pointError)
它的输入是已收集的角度数组。该例程执行FFT并将返回系数数组和一个警告标志。当一个或多个输入角与例程的计算值相差超过20度时,点错误警告标志被设置。
例如,对于8项数组,该例程计算角度应为[0,45,90,135,180,225,270,315]。如果输入数组是[0,45,90,135,180,204,270,315],那么例程将设置pointError,因为第6个数组条目的误差大于20度。
选择谐波
一旦计算出所有的谐波系数,就必须选择所需的谐波。通常情况下,计算例程产生的谐波数量会超过设备所能支持的谐波数量,因此必须选择一些算法来选择相关的谐波。
所使用的谐波的数量也取决于所使用的设备和特性。对于A1332,最大的谐波数是15,但如果使用最大的谐波数,许多可编程功能将使用默认值,如短冲程配置和特定的I2C和SPI设置。对于那些可编程特性,不使用默认值的最大谐波数是9。对于A1335,最大谐波数是11,但为了得到这个数字,许多可编程功能将使用默认值,如短冲程设置。对于那些可编程特性,不使用默认值的最大谐波数是8。
最简单的算法是选择第一个谐波到所需的谐波数量。虽然很容易,但它将选择不会显著影响输出的谐波。
目前在Allegro A1335 Samples Programmer中使用的算法是选择振幅大于0.3的谐波。当前硬件中需要注意的一个限制是,只能在选定的谐波之间跳过4个谐波。如果有大于4的跳变,那么在最后选择的谐波和期望的谐波之间也需要选择任意多的谐波。
编程设备
一旦选择了谐波,那么可以通过调用GenerateHarmonicLinearizationDeviceValues例程来生成要写入设备的值。
HarmonicDeviceValues[]生成harmoniclinearizationdevicevalues (HarmonicCoefficients[] coefficients)
谐系数被传递到这个例程中,它返回一个数组的值需要对设备进行编程。这个例程唯一会抛出的例外情况是,在所选系数之间跳过了4个以上的谐波系数。
要为谐波线性化设备编程,必须设置HL标志,必须将HAR_MAX字段设置为要使用的系数的数量,必须写入HARMONIC_PHASE_n, ADV_n和HARMONIC_AMPLITUDE_n字段。
示例代码
使用系统;
使用Allegro.ASEK;
名称空间HarmonicLinearizationExample
{
公开课HarmonicLinearizationExample
{
公共HarmonicLinearizationExample ()
{
}
ProgramHarmonicLinearization(字符串filePath, ASEK asekProgrammer)
{
试一试
{
HarmonicCoefficients [] hc;
bool pointError = false;
双[]点= null;
string fieldBuffer = File.ReadAllText(filePath);
字符串行;
List
List
// 1.1收集数据
//从文本文件中读取角度。空行或以#开头的行将被忽略。
如果(! string.IsNullOrEmpty (fieldBuffer))
{
使用(StringReader sr = new StringReader(fieldBuffer))
{
while ((line = sr.ReadLine()) != null)
{
行= line.Trim ();
if (string.IsNullOrEmpty(line) || line. startwith ("#"))
{
继续;
}
//每一行可以有两种形式。
//第一个包含编码器角度,然后是与设备的角度,用逗号分隔(22.125,23.543)
//或者只是设备的角度。(23.543)
//如果两个角的间隔不相等,则需要这两个值。
string[] values = line.Split(', ');
如果值。长度> 1)
{
双编码器= Convert.ToDouble(值[0]);
While (encoder >= 360.0)
{
编码器- = 360.0;
}
While(编码器< 0.0)
{
编码器+ = 360.0;
}
encoderReadings.Add(编码器);
deviceReadings.Add (Convert.ToDouble(值[1]));
}
其他的
{
deviceReadings.Add (Convert.ToDouble(值[0]));
}
}
}
// 1.2数据预处理
如果(! powerOfTwo (deviceReadings.Count ()))
{
//如果点数少了一个,就去掉最后一个,
if (powerOfTwo(deviceReadings.Count() - 1))
{
deviceReadings.RemoveAt (deviceReadings.Count () - 1);
点= deviceReadings.ToArray ();
}
其他的
{
//否则计算所需样本的数量。
//如果样本数小于64则舍入
//取上至2的最近次幂,否则取下。
int desiredSamples = 8;
while (desiredSamples < deviceReadings.Count())
{
desiredSamples * = 2;
}
if (deviceReadings.Count() > 64)
{
desiredSamples / = 2;
}
//如果没有编码器读数,假定设备读数是等间隔的。
if (encoderreads . count () != deviceReadings.Count())
{
//将角度列表转换为数组,然后调整它的大小。
点= ((IHarmonicLinearization) asekProgrammer)。desiredSamples ResizePointArray (null, deviceReadings.ToArray ());
}
其他的
{
//将角度列表转换为数组,然后调整它的大小。
points = ((IHarmonicLinearization)asekProgrammer).ResizePointArray(encoderreads . toarray (), deviceReadings.ToArray(), desiredSamples);
}
}
}
其他的
{
//将角度列表转换为数组
点= deviceReadings.ToArray ();
}
// 1.3初始处理
//从点数组中计算系数。
hc = ((IHarmonicLinearization) asekProgrammer)。CalculateHarmonicLinearCoefficients(点,pointError);
//当一个或多个角度与程序认为的角度相差超过20度时,就会发生点错误。
//例如,如果使用8个值的数组[0,45,90,135,180,204,270,315],calculate将为第6个标记一个警告
因为它应该比实际值更接近225。
如果(pointError)
{
对话框。显示(“其中一个角度与期望的角度相差超过20度。”);
}
// 1.4谐波的选择
//一旦计算出谐波系数数组,就需要选择这些系数。系数的个数
//计算例程返回通常会超过设备可以支持的系数数量,所以有一些限制的方法
//需要的系数。可以选择前8个,也可以使用其他方法。
int numberOfHarmonicComponents = hc.Length;
int numberOfSelectedHarmonicComponents = 0;
int lastHarmonicComponentSelected = 0;
int maxHarmonicComponentsSelected = 8;//在影响到设备上的其他特性之前可以使用的最大谐波数
//在这个例子中,选择振幅超过0.3的前8个谐波。
For (int index = 0;指数< numberOfHarmonicComponents;+ +指数)
{
如果(hc(指数)。&& (numberOfSelectedHarmonicComponents < maxHarmonicComponentsSelected))
{
//如果要选择的谐波之间的谐波数
//和最后选择的谐波大于4然后一些
//之间的谐波需要选择。
int skip = index - lastHarmonicComponentSelected;
If(跳过> 4)
{
//确定需要选择的谐波的数量
//不超过所需的数量。
int numberNeeded = skip / 4;
if ((numberNeeded + numberOfSelectedHarmonicComponents) <= maxHarmonicComponentsSelected)
{
For (int jndex = 1;jndex < = numberNeeded;+ + jndex)
{
hc [jndex]。选择= true;
+ + numberOfSelectedHarmonicComponents;
}
hc(指数)。选择= true;
+ + numberOfSelectedHarmonicComponents;
}
其他的
{
//代码无法选择所需的谐波而不超过
//选择的最大系数数,因此它将停止选择。
打破;
}
}
其他的
{
hc(指数)。选择= true;
+ + numberOfSelectedHarmonicComponents;
}
lastHarmonicComponentSelected =指数;
}
}
//如果没有选择谐波,则选择前8。
if (numberOfSelectedHarmonicComponents == 0)
{
For (int I = 0;(i < numberOfHarmonicComponents) && (numberOfSelectedHarmonicComponents < 8);+ + i)
{
hc[我]。选择= true;
+ + numberOfSelectedHarmonicComponents;
}
}
// 1.5设备编程
//生成写入eeprom所需的值。
HarmonicDeviceValues[] eepromValues = ((IHarmonicLinearization)asekProgrammer).GenerateHarmonicLinearizationDeviceValues(hc);
//确认设备的电源是打开的
asekProgrammer.SetVcc (5.0);
//允许写入设备的eeprom,这需要使SRAM可写,并停止处理器
((ISRAMWriteAccessMode) asekProgrammer) .SetSRAMWriteAccessMode ();
((IProcessorMode) asekProgrammer) .SetProcessorIdle ();
//打开eeprom中的谐波线性化
((IRegisterAccess) asekProgrammer) .WritePartialRegister (MemoryAccessType。扩展,0x306, 1,15,15);// hl = 1
//设置要使用的谐波数
((IRegisterAccess) asekProgrammer) .WritePartialRegister (MemoryAccessType。0 x309 eepromValues扩展。19岁的长度16);// HAR_MAX =谐波数
//对于谐波
For (uint index = 0;指数< eepromValues.Length;+ +指数)
{
uint registerValue = (uint)((eepromValues[index].)阶段<< 12)& 0x0FFF000) +
((eepromValues(指数)。advance << 10) & 0x0C00) +
(eepromValues(指数)。振幅& 0 x03ff));
((IRegisterAccess) asekProgrammer) .WriteRegister (MemoryAccessType。扩展,0x30C +索引,registerValue);// HARMONIC_PHASE, ADV和HARMONIC_AMPLITUDE
}
//关闭电源,然后重新打开,以确保设备正在使用新的线性化值。
asekProgrammer.SetVccOff ();
asekProgrammer.SetVcc (5.0);
}
}
捕获(异常交货)
{
MessageBox.Show (ex.Message);
}
}
private bool powerOfTwo(int值)
{
Int log2npoints = 0;
Int j = value;
while ((j > 0) && ((j & 1) == 0)) //计算输入值以2为底的对数
{
log2npoints + +;
j > > = 1;
}
If ((value < 2) || (value != (1 << log2npoints)))
{
返回错误;
}
返回true;
}
}
}
角度输入文件格式
这个文件包含一个角度值列表。如果用逗号分隔两个值,则第一个值是编码器角度,第二个值是设备角度。行可以为空,或者如果以#开头,则认为它们是注释。
输入文件:
329.59
354.81
6.832
13.566
17.592
20.228
22.638
24.638
25.956
27.454
28.77
30.054
30.966
有两列:
0123年
22.5,145.5
45168年
67.5,190.5
90213年
112.5,235.5
135258年
157.5,280.5
180303年
202.5,325.5
225348年
247.5, 10.5
270年,33
292.5, 55.5
315年,78年
337.5,100.5