高级编程与ASEK dll谐波线性化
高级编程与ASEK dll谐波线性化
作者:K.罗伯特·贝特
亚博棋牌游戏快板微系统公司有限责任公司
介绍
从工业自动化和机器亚博尊贵会员人到电子动力转向和电机位置传感的众多工业应用都需要在轴上或轴外布置中监控转轴的角度。
当在设计中使用磁铁时,磁输入很可能在整个旋转范围内不是均匀的——它将有固有误差。这些磁输入误差导致了系统的测量误差。线性化可以减少这些输入误差。
线性化的一种形式A1332和A1335,谐波线性化以多达15个校正谐波的形式应用线性化,其相位和幅度通过在从角度传感器IC周围的磁体的一个旋转中的数据上执行的数据而确定的FFT(快速傅里叶变换)确定。可以使用Allegro提供的软件容易地实现该技术以计算芯片内eEPROM的系数和程序。此应用笔记描述了如果Allegro提供的软件不够灵活,或者将使用自定义软件,则介绍客户可以使用的功能和过程流程。
编程要求
所有的软件都是在Microsoft Visual Studio 2010上使用。net 4.0开发的。下载您将要使用的设备的命令库(c# /. net),并向项目中添加对它包含的三个dll的引用。
收集数据
首先,关闭所有后线性化算法处理;这包括零偏移、后线性化旋转(RO)、短行程反转(IV)和旋转模位(RD)。预线性化调整可以保持开启状态,如ORATE设置、IIR滤波器(FI)和预线性化旋转(LR)。
在增加角度位置的方向移动编码器。如果角度传感器集成电路输出也不增加,然后设置LR钻头扭转角的方向传感器集成电路输出或旋转编码器为校准相反的方向,在这种情况下,Post-Linearization旋转钻头(RO)可能需要设置。更多细节请参阅A1332/ A1335编程参考。
最优的收集方法是以等间隔的步骤旋转目标,使合成数据点的数目为2的幂。通常,32或64个均匀间隔的数据点就足够了。如果不能做到这一点,那么就收集点,并且必须按照下一节讨论的那样对数据进行预处理。
收集所需数据点的另一种技术是多次旋转目标,以预定义的时间间隔收集数据。一旦收集到足够的点来覆盖目标的整个旋转,就必须按照下一节的讨论对它们进行预处理。
预处理数据
如果收集的数据点的数量不是2的幂次,或者收集的数据不是等间距的,那么必须调整数组的大小和/或使其等间距。要对数据执行此操作,请调用例程ResizePointArray。
x参数是编码器值的数组,y参数是在该编码器值处收集的设备读数。参数newSize是调整大小的数组所需的大小。如果x参数设置为空,则假设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样本程序员中使用的当前算法是选择振幅大于0.3的谐波。目前硬件中的一个限制是,只有在所选择的谐波之间只能跳过4个谐波。如果跳跃大于4,则需要选择最后一个谐波之间的许多谐波,并且还需要选择所需的谐波。
编程设备
一旦选择了谐波,就可以通过调用例程生成的rucateharmoniclizationdeviceValues来生成要写入设备的值。
HarmonicDeviceValues[] GenerateHarmonicLinearizationDeviceValues (HarmonicCoefficients[] coefficients)
谐波系数被传递到这个程序中,它返回一个为设备编程所需的值数组。这个例程唯一的例外是在选择的系数之间跳过4个以上的谐波系数。
要对设备进行谐波线性化编程,必须设置HL标志,必须将HAR_MAX字段设置为要使用的系数的数量,并且必须编写HARMONIC_PHASE_n、ADV_n和harmonic_amplude_n字段。
示例代码
使用系统;
使用Allegro.asek;
名称空间HarmonicLinearizationExample
{
公开课HarmonicLinearizationExample
{
公共HarmonicLinearizationExample ()
{
}
public void ProgramHarmonicLinearization(string filePath, ASEK asekProgrammer)
{
尝试
{
HasbonicCoeffients [] HC;
bool pointerror = false;
Double [] points = null;
字符串FieldBuffer = file.ReadAllText(FILEPATH);
字符串行;
列表
list
// 1.1收集数据
//从文本文件中的角度读取。以#开头的空线或线路被忽略。
if(!string.isnulloremaly(fieldbuffer))
{
使用StringReader sr = new StringReader(fieldBuffer)
{
while ((line = sr.ReadLine()) != null)
{
行= line.Trim ();
if(string.isnulloremaly(line)|| line.startswith(“#”))
{
继续;
}
//每行可以是2个形式中的1个。
//第一个包含编码器角,然后由逗号分隔的设备的角度(22.125,23.543)
//或者只是与设备的角度。(23.543)
//如果角度不是等距的,则需要两个值。
String []值= line.split(',');
如果值。长度> 1)
{
double encoder = Convert.ToDouble(值[0]);
而(编码器> = 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 ()))
{
//如果点数相差1,则删除最后一个点数,
if (powerOfTwo(deviceReadings.Count() - 1))
{
deviceReadings.RemoveAt (deviceReadings.Count () - 1);
点= devicereadings.toArray();
}
其他的
{
//否则计算所需样本的数量。
//如果样本的数量小于64,那么圆形
//取最接近2的幂,否则取整。
int desiredSamples = 8;
while (desiredSamples < deviceReadings.Count())
{
潜水* = 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);
//一个点错误就是当一个或多个角度更大的角度发生时会发生什么,而例程认为应该是什么。
//例如,如果要使用8个值的阵列[0,45,90,135,180,204,270,315]计算将向第6个标记警告
//数组项,因为它应该比实际更接近225。
如果(pointError)
{
对话框。Show(“其中一个角度与所需要的角度相差超过20度”);
}
// 1.4谐波的选择
//一旦计算出谐波系数数组,就需要选择这些系数。系数的个数
//计算例程返回的系数通常会超过设备支持的系数的数量,因此需要一些方法来限制这个数量
//需要的系数。可以选择前8个,也可以使用其他方法。
int numberOfHarmonicComponents = hc.Length;
int numberofselectedharmoniccomponents = 0;
int lastharmoniccomponentselected = 0;
int maxharmoniccomponents选择= 8;//在影响设备上的其他功能之前可以使用的最大谐波数
//对于这个例子,振幅超过0.3的前8个谐波被选中。
For (int index = 0;指数< numberOfHarmonicComponents;+ +指数)
{
如果(hc(指数)。振幅> 0.3)&& (numberOfSelectedHarmonicComponents < maxHarmonicComponentsSelected))
{
//如果谐波之间的数量是要被选择的
//最后选择的和声大于4,然后一些
//两者之间的谐波需要被选择。
int skip = index - lasttharmoniccomponentselected;
If (skip > 4)
{
//确定需要选择的谐波的数量
//不超过所需的数量。
INT NummumNeeded = 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 [i] .select = true;
+ + numberOfSelectedHarmonicComponents;
}
}
// 1.5设备编程
//生成需要写入eeprom的值。
[] 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);//输出
//设置要使用的谐波数
((IRegisterAccess) asekProgrammer) .WritePartialRegister (MemoryAccessType。0 x309 eepromValues扩展。19岁的长度16);// HAR_MAX =谐波数
//对于谐波
for(uint index = 0; index
UINT RegisterValue =(UINT)(((EEPROMVALUES [index] .phase << 12)&0x0fff000)+
((eepromValues(指数)。advance << 10) & 0x0C00) +
(eepromValues(指数)。振幅& 0 x03ff));
((iRegisterAccess)ASekprogrammer).writeRegister(MemedumentAccessType.extended,0x30c + index,procestervalue);// almonic_phase,adv和harmonic_amplitude
}
//关闭电源,然后重新打开,以确保设备正在使用新的线性化值。
asekProgrammer.SetVccOff ();
asekProgrammer.SetVcc (5.0);
}
}
捕获(例外EX)
{
MessageBox.Show (ex.Message);
}
}
private bool powerOfTwo(int值)
{
Int log2npoints = 0;
int j =值;
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.
135,258
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