Android步进电机

本文介绍在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频率降下来。

装上外壳后,效果图

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值