具有ASEK DLL谐波线性化的高级编程

具有ASEK DLL谐波线性化的高级编程

Download PDF Version

By K. Robert Bate,
Allegro MicroSystems, LLC

介绍

Numerous applications in industries spanning from industrial automation and robotics, to electronic power steering and motor position sensing require monitoring the angle of a rotating shaft either in an on-axis or off-axis arrangement.

在设计中使用磁铁时,磁性输入很可能在整个旋转范围内均匀 - 它将具有固有的误差。这些磁输入误差会导致系统中的测量误差。线性化可以减少这些输入错误。

可提供一种形式的线性化A1332A1335谐波线性化以多达15个校正谐波的形式应用线性化,其相位和幅度通过在从角度传感器IC周围的磁体的一个旋转中的数据上执行的数据而确定的FFT(快速傅里叶变换)确定。可以使用Allegro提供的软件容易地实现该技术以计算芯片内eEPROM的系数和程序。此应用笔记描述了如果Allegro提供的软件不够灵活,或者将使用自定义软件,则介绍客户可以使用的功能和过程流程。

编程要求

All of the software was developed on Microsoft Visual Studio 2010 using .NET 4.0. Download the Command Library (C#/.NET) for the device that you are going to use and add to the project references to the three DLLs that it contains.

收集数据

First, turn off all post-linearization algorithmic processing; this includes ZeroOffset, Post-Linearization Rotation (RO), Short Stroke Inversion (IV), and the Rotate Die bit (RD). Prelinearization adjustments may be left on, such as ORATE settings, IIR filter (FI), and Prelinearization Rotation (LR).

Move the encoder in the direction of increasing angle position. If the angle sensor IC output does not also increase, then either set the LR bit to reverse the direction of the angle sensor IC output or rotate the encoder in the opposite direction for calibration, in which case the Post-Linearization Rotate bit (RO) will likely need to be set. See the A1332/ A1335 programming reference for more details.

最佳收集方法是以等间隔的步骤旋转目标,使得所得到的数据点的数量是2.通常,32或64个均匀间隔的数据点足够。如果无法完成此操作,则收集点,并且如下一部分中所讨论的,必须预处理数据。

Another technique to gather the required data points is to rotate the target many times, collecting the data at a predefined interval. Once enough points have been gathered to cover the entire rotation of the target, then they must be preprocessed as discussed in the next section.

预处理数据

如果收集的数据点的数量不是两个的功率,或者收集的数据不等等地间隔,则必须调整点阵列和/或使得恰好间隔。要对数据执行此操作,请调用例程resizepointarray。

x参数是编码器值阵列,y参数是在该编码器值收集的设备读数。参数Newsize是调整大小阵列的所需大小。如果x参数设置为null,则假定y值以0开始于0开始,并在360处结束。如果x参数未为空,则在执行调整大小之前将排序输入阵列。

Double [] ResizePointarray(Double [] x,Double [] Y,Int Newsize)

This routine will perform a cubic-spline interpolation on the input arrays to generate an equal-spaced array with the desired number of points.

初始处理

Once the data has been collected and made into an array of a length which is a power of 2, then the harmonic coefficients are ready to be calculated. To calculate the coefficients, call the routine CalculateHarmonicLinearCoefficients.

HarmonicCoeffient [] CalculateHarmonicLoceAlcofience(Double []点,Bool PigetError)

其输入是已收集的角度阵列。例程执行FFT,并将返回系数数组和警告标志。当一个或多个输入角度大于20度不同的输入角度与例程计算它应该是相差时,设置点错误警告标志。

For example, for an 8 entry array, the routine calculates that the angles should be [0, 45, 90, 135, 180, 225, 270, 315]. If the input array is [0, 45, 90, 135, 180, 204, 270, 315], then the routine will set the pointError because the 6th array entry has an error greater than 20 degrees.

选择谐波

一旦计算了所有谐波系数,必须选择所需的谐波。通常,计算例程生成的谐波数将超过设备可以支持的谐波数量,因此必须选择一些选择相关谐波的算法。

使用的谐波数也取决于哪个设备以及使用该功能。对于A1332,最大谐波数为15,但如果使用最大值,则许多可编程功能将使用默认值,例如短语配置和特定的I2C和SPI设置。不使用这些可编程功能的默认值的最大谐波数为9.对于A1335,最大谐波数为11,但要获取此号码,则许多可编程功能将使用默认值,例如短程设置。不使用这些可编程功能的默认值的最大谐波数为8。

使用最简单的算法是选择第一个谐波到所需的谐波数量。虽然很容易,它将选择不会显着影响输出的谐波。

Allegro A1335样本程序员中使用的当前算法是选择振幅大于0.3的谐波。目前硬件中的一个限制是,只有在所选择的谐波之间只能跳过4个谐波。如果跳跃大于4,则需要选择最后一个谐波之间的许多谐波,并且还需要选择所需的谐波。

编程设备

一旦选择了谐波,就可以通过调用例程生成的rucateharmoniclizationdeviceValues来生成要写入设备的值。

HarmonicDeviceValues []生成哈卡卡猴弹性DeviceValues(HasbonicCoefients []系数)

谐波系数被传递到该例程中,并且它返回编程设备所需的值的数组。此例程将抛出的唯一例外情况是在所选系数之间跳过超过4个谐波系数的情况。

要为谐波线性化进行编程,必须设置HL标志,必须将HAR_MAX字段设置为要使用的系数数,并且必须写入谐波_PUSE_N,ADV_N和HARMONIC_AMPLUTION_N字段。

示例代码

使用系统;
使用Allegro.asek;

namespace HarmonicLinearizationExample
{
public class HarmonicLinearizationExample
{
public HarmonicLinearizationExample()
{
}

公共void程序armonearization(String Filepath,Asek Asekprogrammer)
{
尝试
{
HasbonicCoeffients [] HC;
bool pointerror = false;
double[] points = null;
字符串FieldBuffer = file.ReadAllText(FILEPATH);
string line;
列表 encoderreadings = new list ();
list devicereadings = new list ();

// 1.1 Collecting the data
//从文本文件中的角度读取。以#开头的空线或线路被忽略。
if(!string.isnulloremaly(fieldbuffer))
{
使用(stringReader SR = New StringReader(FieldBuffer))
{
而((line = sr.readline())!= null)
{
line = line.trim();
if(string.isnulloremaly(line)|| line.startswith(“#”))
{
继续;
}

//每行可以是2个形式中的1个。
//第一个包含编码器角,然后由逗号分隔的设备的角度(22.125,23.543)
//或只是从设备的角度。(23.543)
//如果角度不等于间隔,则需要两个值。
String []值= line.split(',');

if(值.Length> 1)
{
double encoder = Convert.ToDouble(values[0]);
而(编码器> = 360.0)
{
编码器 - = 360.0;
}
而(编码器<0.0)
{
encoder += 360.0;
}
Encoderreadings.add(编码器);
devicereadings.add(convert.todouble(值[1]));
}
else
{
devicereadings.add(convert.todouble(值[0]));
}
}
}

// 1.2预处理数据
if(!Poweroftwo(devicereadings.count()))
{
//如果点数为OFF,则只需删除最后一个,
if(poweroftwo(devicereadings.count.count() - 1))
{
deviceReadings.RemoveAt(deviceReadings.Count() - 1);
点= devicereadings.toArray();
}
else
{
//否则计算所需样本的数量。
//如果样本的数量小于64,那么圆形
//最多两个,否则圆润。
int iscandsamples = 8;
while (desiredSamples < deviceReadings.Count())
{
潜水* = 2;
}

if(devicereadings.count()> 64)
{
jailenceSamples / = 2;
}

//如果没有编码器读数,假设设备读数同样间隔。
if(encoderreadings.count()!= devicereadings.count())
{
//将角度列表转换为数组,然后调整大小。
点=((iHarmoniclineArization)ASekprogrammer).resizepointarray(null,devicereadings.toArray(),希望的arample);
}
else
{
//将角度列表转换为数组,然后调整大小。
点= ((IHarmonicLinearization) asekProgrammer)。ResizePointArray(encoderReadings.ToArray(), deviceReadings.ToArray(), desiredSamples);
}
}
}
else
{
// Convert the list of angles to an array
点= devicereadings.toArray();
}

// 1.3初始处理
// Calculate the coefficients from the array of points.
hc = ((IHarmonicLinearization)asekProgrammer).CalculateHarmonicLinearCoefficients(points, out pointError);

//一个点错误就是当一个或多个角度更大的角度发生时会发生什么,而例程认为应该是什么。
//例如,如果要使用8个值的阵列[0,45,90,135,180,204,270,315]计算将向第6个标记警告
// entry in the array because it should be closer to 225 than it is.
if (pointError)
{
MessageBox.show(“其中一个角度从所需的内容越多20度。”);
}

// 1.4谐波的选择
//一旦计算了谐波系数阵列,需要选择系数。系数的数量
//计算例程返回通常超过设备可以支持的系数数量,这使得一些限制数量的方法
// of coefficents is needed. The first 8 could be picked or another method could be used.
int numberOfHarmonicComponents = hc.Length;
int numberofselectedharmoniccomponents = 0;
int lastharmoniccomponentselected = 0;
int maxharmoniccomponents选择= 8;//在影响设备上的其他功能之前可以使用的最大谐波数

// For this example, the first 8 harmonics where the amplitude exceed 0.3 are selected.
for(int index = 0; index {
if((hc [index] .amplitude> 0.3)&&(numberofselectedharmoniccomponents {
//如果要选择的谐波之间的谐波数量
//选择的最后一个谐波更大,然后4然后一些
//需要选择谐波。
int skip = index - lastharmoniccomponentselect;
如果(跳过> 4)
{
//确保需要选择的谐波数量
// does not exceed the number that is desired.
INT NummumNeeded = Skip / 4;
if((numberneededed + numberofselectedharmoniccomponents)<= maxharmoniccomponentsselect)
{
for(int jndex = 1; jndex <= number4eded; ++ jndex)
{
hc [jndex] .select = true;
++numberOfSelectedHarmonicComponents;
}
hc [index] .select = true;
++numberOfSelectedHarmonicComponents;
}
else
{
//代码无法在不超过的情况下选择所需的谐波
//选择的最大系数数,因此它将停止选择。
break;
}
}
else
{
hc [index] .select = true;
++numberOfSelectedHarmonicComponents;
}
LastharmonicComponentselect =指数;
}
}

//如果没有选择谐波,则选择前8个。
if (numberOfSelectedHarmonicComponents == 0)
{
for (int i = 0; (i < numberOfHarmonicComponents) && (numberOfSelectedHarmonicComponents < 8); ++i)
{
HC [i] .select = true;
++numberOfSelectedHarmonicComponents;
}
}

// 1.5编程设备
//生成要写入EEPROM所需的值。
HarmonicDeviceValues [] EEPROMVALUES =((IHARMONICLINARIZEARIZE)ASEKPROGGRAMMAMER).generateHarmonicLIZAZEVICEVALUES(HC);

//确保设备上的电源
asekProgrammer.SetVcc(5.0);

// Enable writing to the device’s eeprom, this requires making the SRAM writable and to stop the processor
((isramwriteacessmode)asekprogrammer).setsramwriteaccessmode();
((iProcessorMode)ASekprogrammer).setprocessoridle();

//在EEPROM中打开谐波线性化
((iRegisterAccess)ASekprogrammer).writepartialRegister(MeminityAccessType.extended,0x306,15,15);// hl = 1

// Set the number of harmonics to be used
((IRegisterAccess)asekProgrammer).WritePartialRegister(MemoryAccessType.extended, 0x309, eepromValues.Length, 19, 16); // HAR_MAX = number of harmonics

// For the harmonics
for(uint index = 0; index {
UINT RegisterValue =(UINT)(((EEPROMVALUES [index] .phase << 12)&0x0fff000)+
((EEPROMVALUES [INDEX] .Advance << 10)&0x0C00)+
(EEPROMVALUES [索引] .AMPLUTY&0x03FF));
((iRegisterAccess)ASekprogrammer).writeRegister(MemedumentAccessType.extended,0x30c + index,procestervalue);// almonic_phase,adv和harmonic_amplitude
}

// Turn the power off then back on to make sure the device is using the new linearization values.
asekprogrammer.setvccoff();
asekProgrammer.SetVcc(5.0);
}
}
捕获(例外EX)
{
MessageBox.Show(ex.Message);
}
}

私人BOOL Poweroftwo(INT值)
{
int log2npoints = 0;
int j =值;

while ((j > 0) && ((j & 1) == 0)) // Compute log base 2 of input value
{
log2npoints ++;
j >> = 1;
}

if ((value < 2) || (value != (1 << log2npoints)))
{
返回false;
}

return 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

With two columns:

0,123
22.5,145.5.
45,168
67.5,190.5
90,213
112.5,235.5.
135,258
157.5,280.5
180,303
202.5,325.5.
225,348
247.5,10.5
270,33
292.5,55.5.
315,78
337.5,100.5