在工业控制中,许多场合都可以看到电机的身影。特别是步进电机,以其精度高,运行可靠等优势,广泛地应用于数字控制系统中。像这一类步进电机的控制,通常都是使用的脉冲信号来实现的。当步进电机接收到一个脉冲信号,会转动一个固定的角度,所以可以通过控制脉冲的个数来控制转动的角度,从而实现精确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度,从而实现控制速度的目的。
英创嵌入式工控板提供了两种控制步进电机的方法给用户,第一种方法是使用GPIO发出脉冲来实现控制电机的目的,根据需要转动的角度和速度,通过调用GPIO的API函数来发出相应个数和频率的脉冲就能够达到这一目的。但是如果控制电机的实时性要求比较高,需要达到10ms以内的精度,那么第一种方法可能就不能满足要求了,因为控制GPIO是通过了操作系统来执行的,这样程序就涉及到了系统调度等因素,在实时性方面肯定就不能满足太高的需求。于是英创公司推出了另外一种实时性较高的方法,即使用PWM脉冲来控制电机。
英创工控主板EM928x系列上共有4路PWM输出,其最高输出频率可达12MHz,但如果希望保证一定精 度的占空比(1%的精度),则输出最高频率只能到240KHz。而EM335x系列上也有4路PWM输出,其最高输出频率可达50MHz,但如果希望保证一定精度的占空比(1% 的精度),则输出最高频率只能到1MHz。从频率和占空比上看,应该是完全满足控制速度的要求,但是如果要实现精确定位的功能,还需要控制脉冲的个数,所以英创公司修改了PWM脉冲驱动,在原来的基础上增加了对PWM波个数控制和计数的功能,使应用程序能控制发出的脉冲个数,从而精确步进电机的动作。
本文以下部分将介绍这一新增加的功能以及在应用程序中的调用方法。
实现这一功能是通过利用CPU内部的计数器来记录PWM脉冲的个数,当达到预定的值,就产生中断将PWM脉冲停止,这样就能够对PWM脉冲的计数并且产生指定个数的脉冲,这一部分的功能英创公司已经在驱动中完成,用户只需要在应用程序中通过接口调用,就可以启用、停止计数功能,并且实时查询脉冲数。支持这一功能的PWM波有两路:PWM1和PWM2,能产生的最小波形数为2。对PWM的操作可归为2种基本操,在原有的普通使能和停止功能基础上加入了计数功能的操作,所对应的命令参数,定义如下:
#define EM9280_COUNT_START 12 // 启动带计数功能的PWM脉冲输出
#define EM9280_COUNT_STOP 13 // 强制停止带计数功能的PWM脉冲输出
接下来来看头文件中定义的PWM 的数据结构,包括频率、占空比以及极性等参数:
struct pwm_config_info
{
unsigned int cmd; // = 0, 1, 2, ....
unsigned int freq; /* in Hz */
unsigned int duty; /* in % */
unsigned int polarity;
unsigned int count;
};
cmd表示指令:就是上面说的两种操作。
freq表示输出的脉冲频率,单位为 Hz。Freq 的取值范围 和板卡的最高支持频率有关。
duty表示输出脉冲的占空比,单位为%。
Duty的取值范围:1 – 99。
Polarity表示输出脉冲的极性,选择 0 或者 1。
count是新加入的参数,表示需要生成的PWM波的个数。
进行PWM操作时,首先打开相应的设备节点文件,然后再调用 write( )函数进行 pwm 的设置、启动计数等操作,以下为启动计数功能的相关应用代码:
int PWM_COUNT_Start(int fd, int freq, int duty, unsigned int count)
{
int rc;
struct pwm_config_info conf;
conf.cmd = EM9280_COUNT_START;
conf.freq = freq;
conf.duty = duty;
conf.polarity = POLARITY;
conf.count = count;
rc = write(fd, &conf, sizeof(struct pwm_config_info));
return rc;
}
这样就只需要调用PWM_COUNT_Start()这个函数,并将参数带入即可,我们就以产生5个占空比为1KHZ的波形为例:
int npwm = 1;
int fd;
char device[32];
unsigned int freq = 1000;
unsigned int duty = 50;
unsigned int count = 5;
sprintf( device, '/dev/em9280_pwm%d', npwm );
fd = open(device, O_RDWR);
if ( fd < 0)
{
printf('can not open /dev/em9280_pwm%d device file!\n', npwm);
return -1;
}
printf( 'Open %s\n', device );
PWM_COUNT_Start( fd, freq, duty, count );
在脉冲输出的过程中,可以调用read函数读取已经输出的脉冲数,如果到达某一个值的时候需要停止输出,就调用write( )函数进行pwm的停止,详细的代码如下:
int PWM_COUNT_Stop(int fd )
{
int rc;
struct pwm_config_info conf;
memset( &conf, 0, sizeof(struct pwm_config_info));
conf.cmd = EM9280_COUNT_STOP;
rc = write(fd, &conf, sizeof(struct pwm_config_info));
return rc;
}
// 读取已发送脉冲数
read(fd, &buf, sizeof(buf));
if( buf>=5 ) // 当输出脉冲数到达某个值则停止
PWM_COUNT_Stop( fd );
生成5个占空比为1KHz的波形的程序运行的结果如下图:
通过对PWM脉冲计数功能的实现,就可以对电机进行精确的控制了,详细的代码请参考光盘中的例程。
全部0条评论
快来发表一下你的评论吧 !