本文介绍在Android环境下添加步进电机的驱动和电机应用的思路。
摄像头需要2个步进电机,控制左右旋转和上下旋转,底盘需要2个步进电机,控制车体移动,步进电机5线4相,总共需要16路pwm。
限于板子IO口数量不够,本次调试pwm模块pca9685拓展,支持16路pwm,我直接从x宝买了块模块,商家没技术支持。
本章包括硬件搭建、驱动编写和测试程序编写。
硬件准备
连接设备至nanopi2
驱动编写
查看设备i2c地址
A6固定是1,A5~A1用电压表测量是0(可以根据实际要求修改高低),读写位。所以默认0b1000000 = 0x40
nanopi2引脚参考
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_2/zh
资源文件放在plat-xxx底下,芯片是s5p4418,板子资源文件放在arch/arm/plat-s5p4418/nanopi2,修改device.c添加i2c资源文件。
static struct i2c_board_info __initdata pca9685_i2c_bdi = {
I2C_BOARD_INFO("pca9685", 0X40),
.irq = -1,
};
......
i2c_register_board_info(0, &pca9685_i2c_bdi, 1);
这就注册了一个i2c资源地址0x40,匹配方式是另一个i2c_driver 也叫"pca9685".
Kconfig
config PWM_PCA9685
bool "pca9685 driver"
help
pwm driver for motor
Makefile
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
config
CONFIG_PWM_PCA9685=y
以上添加模块方式是按照正常流程的做法。如果要省事的做法直接在Makefile,obj-y+=pwm-pca9685,o
参考linux官方代码。
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/pwm/pwm-pca9685.c?id=refs/tags/v4.6-rc6
nanopi2不支持pwm接口,我选择用misc driver方式注册。
框架搭好了,开始处理驱动细节,参考手册编写。
使能芯片
When the oscillator is off (Sleep mode) the LEDn outputs cannot be turned on, off or dimmed/blinked.
意思是睡眠模式下,关闭振荡器,输出也关闭。
/*wake me up*/
static int pca9685_pwm_request(void)
{
return regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, 0x0);
}
/*let me down*/
static int pca9685_pwm_free(void)
{
return regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, MODE1_SLEEP);
}
设定占空比
参考手册的例子Fig7 LED Output,example1
LEDn_ON:延长时间后开始拉高
LEDn_OFF:经过多少时间后开始拉低
static int pca9685_pwm_config(int channel, int on, int off)
{
int on_h = (on & 0xf00) >> 8;
int on_l = on &0xff;
int off_h = (off & 0xf00)>>8;
int off_l = off & 0xff;
regmap_write(pca->regmap, LED_N_ON_H(channel), on_h);
regmap_write(pca->regmap, LED_N_ON_L(channel), on_l);
regmap_write(pca->regmap, LED_N_OFF_H(channel), off_h);
regmap_write(pca->regmap, LED_N_OFF_L(channel), off_l);
pr_info("%s config channel:%d, on:%d, off:%d\n", __func__, channel, on, off);
return 0;
}
分频器配置
The maximum PWM frequency is 1526 Hz if the PRE_SCALE register is set "0x03h".
The minimum PWM frequency is 24 Hz if the PRE_SCALE register is set "0xFFh".
The PRE_SCALE register can only be set when the SLEEP bit of MODE1 register is set to logic 1.
这说的是频率范围24Hz~1526Hz,只有寄存器Mode1设置为睡眠模式,设置分频才有效。
static int pca9685_pwm_set_prescale(int hz)
{
int save_mode=regmap_read(pca->regmap, PCA9685_MODE1);
int val = 25*1000000/(4096 * hz) - 1;
regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, 1);
regmap_write(pca->regmap, PCA9685_PRESCALE, val);
regmap_write(pca->regmap, PCA9685_MODE1, save_mode);
}
测试程序
参照前几章我写的Android Jni编写,编写测试程序。
Jni接口:
打开设备:
public native int open();
关闭设备:
public native int close();
申请pwm:
public native int request();
释放pwm:
public native int free();
配置pwm:
public native int config(int channel, int on, int off);
关闭pwm:
public native int unconfig(int channel);
配置分频器:
public native int hz(int hz);
Java测试代码
Pwm mPwm = new Pwm();
mPwm.open();
mPwm.request();
mPwm.config(0, 0, STEP - 1);
mPwm.config(1, STEP, 2 * STEP - 1);
mPwm.config(2, 2 * STEP, 3 * STEP - 1);
mPwm.config(3, 3 * STEP, 4 * STEP - 1);
运行程序要注意以下两点,增加设备权限。
1、给你创建的设备增加读写权限,不同板子厂商,init.rc位置也不一样。
在system/core/rootdir/init.rc
chmod 666 /dev/pca9685
2、关闭SELInux
setenforce 0
也可以永久关闭SELInux,参考nanopi2 wiki
./fw_setenv /dev/sdc bootargs XXX androidboot.selinux=permissive
验证PWM波形
验证波形可以用示波器,条件限制,没有购买示波器,到网上买了个逻辑分析仪,几十块。支持24M,对于pca9685,,绰绰有余。
实际测得波形:
设置4路pwm,软件设置占空比为1/4,波形测得占空比也为1/4.
步进电机原理
PWM波形输出符合预期,接下来要实现我们的电机转动。
步进电机的基本原理,定子按照时序通电,让动子转动。
如下图。
四相四拍工作方式
正转通电顺序:A->B->C->D->A
反转通电顺序:D->C->B->A->D
四相八拍工作方式
正转通电顺序:A->AB->B->BC->C->CD->D->DA
反转通电顺序:D->DC->C->CB->B->BA->A->AD
时间与角度
我使用24byj电机,步距角5.625/64,有减速齿轮。
步距角我理解是,每一步走的角度,并不是每一个脉冲走的角度,八拍方式一个脉冲不止走了一步。
现在已知条件:工作方式、步距角,我们要求时间才能精确旋转角度,我设置脉冲频率100HZ
脉冲周期T = 1/100 = 10ms
角度(度) 时间(ms) 说明
每一步 5.625°/64 10/8 八拍方式,每一步占一拍
一个周期 8 * 5.625°/64 10
一圈 360° x
x = 360 * 10 / ( 8 * 5.625°/64) = 5120ms。5.12s转360°
遇到一些问题:
1、ULN2003驱动板是反向输出,也就是输入正输出为负,使用PCA9685寄存器MODE1置INVERT为高
2、ULN2003输入电压必须大于等于5V,3.3V情况下,驱动不了电机。
3、测试开始电机未能转动,电机本身有振动,PWM频率调太高了,我把PWM频率降下来。
装上外壳后,效果图