高级编程与ASEK dll谐波线性化

高级编程与ASEK dll谐波线性化

下载版本

作者:K.罗伯特·贝特
亚博棋牌游戏快板微系统公司有限责任公司

介绍

从工业自动化和机器亚博尊贵会员人到电子动力转向和电机位置传感的众多工业应用都需要在轴上或轴外布置中监控转轴的角度。

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

线性化的一种形式A1332A1335谐波线性化应用线性化的形式15校正谐波的相位和振幅决定通过一个FFT(快速傅里叶变换)上执行收集的数据从一个磁铁的旋转角度传感器IC。这种技术可以方便地使用Allegro-provided软件计算系数和实现片上eepm程序。本应用说明描述了当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的跳变,那么在最后选择的谐波和想要的谐波之间也需要选择尽可能多的谐波。

编程设备

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

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)

试一试

HarmonicCoefficients [] hc;
bool pointError = false;
Double [] points = null;
string fieldBuffer = File.ReadAllText(filePath);
字符串行;
List encoderreads = new List();
List deviceReadings = new List();

// 1.1收集数据
//从文本文件中读取角度。空白行或以#开头的行将被忽略。
如果(! string.IsNullOrEmpty (fieldBuffer))

使用StringReader sr = new StringReader(fieldBuffer)

while ((line = sr.ReadLine()) != null)

行= line.Trim ();
if (string.IsNullOrEmpty(line) || line. startswith ("#"))

继续;


//每一行可以是两种形式中的一种。
//首先包含一个编码器角度,然后是从设备到编码器的角度,用逗号隔开(22.125,23.543)
//或者只是与设备的角度。(23.543)
//如果角度不是等距的,则需要两个值。
string[] values = line.Split(', ');

如果值。长度> 1)

double encoder = Convert.ToDouble(值[0]);
While(编码器>= 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())

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],计算程序将为第6个值标记一个警告
//数组项,因为它应该比实际更接近225。
如果(pointError)

对话框。Show(“其中一个角度与所需要的角度相差超过20度”);


// 1.4谐波的选择
//一旦计算出谐波系数数组,就需要选择这些系数。系数的个数
//计算例程返回的系数通常会超过设备支持的系数的数量,因此需要一些方法来限制这个数量
//需要的系数。可以选择前8个,也可以使用其他方法。
int numberOfHarmonicComponents = hc.Length;
int numberOfSelectedHarmonicComponents = 0;
int lasttharmoniccomponentselected = 0;
int maxHarmonicComponentsSelected = 8; / /输出//在影响设备上的其他功能之前,可以使用的最大谐波数

//对于这个例子,振幅超过0.3的前8个谐波被选中。
For (int index = 0;指数< numberOfHarmonicComponents;+ +指数)

如果(hc(指数)。振幅> 0.3)&& (numberOfSelectedHarmonicComponents < maxHarmonicComponentsSelected))

//如果谐波之间的数量是要被选择的
//最后选择的和声大于4,然后一些
//两者之间的谐波需要被选择。
int skip = index - lasttharmoniccomponentselected;
If (skip > 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的值。
[] 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;指数< eepromValues.Length;+ +指数)

uint registerValue = (uint)(((eepromValues[index]. value]))相位<< 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