ST MEMS创意大赛第4贴 -- 机械臂控制
[复制链接]
本帖最后由 传媒学子 于 2020-5-10 21:30 编辑
由于项目最后要驱动机械臂实现手势或者语音跟踪,机械臂驱动的话最好是用驱动板来进行驱动,因此上网上买了一个驱动模块,PCA9685, 可驱动16路PWM。
由于MEMS的MCU没有预留的GPIO口,因此,这里采用STM32F429作为驱动I2C PWM驱动器的主控MCU。
STM32F429主要实现以下功能:
1.采用串口接收PC机中的命令,这些命令根据ST MEMS 获取的传感器数值,结合LSM6DSOX机器学习内核,最终送出的数据。
2.解析串口中的数据,驱动I2C PWM驱动器,控制机械臂实现跟踪功能。
这里,首先分享2. 这里采用硬件I2C驱动pac9685, 采用HAL库进行操作,具体程序工程见附件。驱动PCA9685的库是从github上找的,移植到STM32F4上的,大家有兴趣的可以参考。
这里PCA9685有个坑,给大家指出:网上买的这个模块,见下图:
这个PAC9685输出端配置如下:
这个芯片原本是用于驱动LED的,被机器人爱好者用于驱动电机了,当然也是可以的;但是网上有一些卖这个模块的,不知道是从哪里搞来的。原理图也没有,资料也是网上的。
我重新看了手册,发现输出是需要添加上拉电阻的,而我买的模块却没有,浪费了我1天的时间,如果不加上拉电阻,波形幅度非常小,大概几十mv. 如果我手里没有那个逻辑分析仪,说实话,估计我就用STM23F429生成多路PWM了;最后看了手册将驱动板后边的输出部分加了一个上拉电阻拉至5V,其实拉到3.3V就行。然后,就可以驱动我的机械臂了。
主程序如下:
程序就不多贴了,硬件I2C,PCA9685driver驱动,STM32F4 MCU: 用STM32CubeMX 生成HAL库。
printf(" %d ",pca9685_init(&handle));
//pca9685_write_u8(&handle, 1, 0x10);
// Set PWM frequency.
// The frequency must be between 24Hz and 1526Hz.
printf("%d+1 ",pca9685_set_pwm_frequency(&handle, 50.0f));
// Set the channel on and off times.
// The channel must be >= 0 and < 16.
// The on and off times must be >= 0 and < 4096.
// In this example, the duty cycle is (off time - on time) / 4096 = (2048 - 0) / 4096 = 50%
printf("%d+2 ",pca9685_set_channel_pwm_times(&handle, 0, 0, 4096*0.5/20));
printf("%d+2 ",pca9685_set_channel_pwm_times(&handle, 1, 0, 4096*1/20));
printf("%d+2 ",pca9685_set_channel_pwm_times(&handle, 2, 0, 4096*1.5/20));
printf("%d+2 ",pca9685_set_channel_pwm_times(&handle, 3, 0, 4096*2.0/20));
// If you do not want to set the times by hand you can directly set the duty cycle. The last parameter
// lets you use a logarithmic scale for LED dimming applications.
//printf("%d+3 ",pca9685_set_channel_duty_cycle(&handle, 1, 0.5f, false));
/* USER CODE END 2 */
uint8_t prescaler = (uint8_t)roundf(25000000.0f/ (4096 * 50)) - 1;
printf(" %d ",prescaler);
#include "main.h"
#include <stdbool.h>
#ifndef PCA9685_I2C_TIMEOUT
#define PCA9685_I2C_TIMEOUT 0x1000
#endif
#define PCA9865_I2C_DEFAULT_DEVICE_ADDRESS 0x80
/**
* Structure defining a handle describing a PCA9685 device.
*/
typedef struct {
/**
* The handle to the I2C bus for the device.
*/
I2C_HandleTypeDef *i2c_handle;
/**
* The I2C device address.
* @see{PCA9865_I2C_DEFAULT_DEVICE_ADDRESS}
*/
uint16_t device_address;
/**
* Set to true to drive inverted.
*/
bool inverted;
} pca9685_handle_t;
/**
* Initialises a PCA9685 device by resetting registers to known values, setting a PWM frequency of 1000Hz, turning
* all channels off and waking it up.
* @param handle Handle to a PCA9685 device.
* @return True on success, false otherwise.
*/
bool pca9685_init(pca9685_handle_t *handle);
/**
* Tests if a PCA9685 is sleeping.
* @param handle Handle to a PCA9685 device.
* @param sleeping Set to the sleeping state of the device.
* @return True on success, false otherwise.
*/
bool pca9685_is_sleeping(pca9685_handle_t *handle, bool *sleeping);
/**
* Puts a PCA9685 device into sleep mode.
* @param handle Handle to a PCA9685 device.
* @return True on success, false otherwise.
*/
bool pca9685_sleep(pca9685_handle_t *handle);
/**
* Wakes a PCA9685 device up from sleep mode.
* @param handle Handle to a PCA9685 device.
* @return True on success, false otherwise.
*/
bool pca9685_wakeup(pca9685_handle_t *handle);
/**
* Sets the PWM frequency of a PCA9685 device for all channels.
* Asserts that the given frequency is between 24 and 1526 Hertz.
* @param handle Handle to a PCA9685 device.
* @param frequency PWM frequency to set in Hertz.
* @return True on success, false otherwise.
*/
bool pca9685_set_pwm_frequency(pca9685_handle_t *handle, float frequency);
/**
* Sets the PWM on and off times for a channel of a PCA9685 device.
* Asserts that the given channel is between 0 and 15.
* Asserts that the on and off times are between 0 and 4096.
* @param handle Handle to a PCA9685 device.
* @param channel Channel to set the times for.
* @param on_time PWM on time of the channel.
* @param off_time PWM off time of the channel.
* @return True on success, false otherwise.
*/
bool pca9685_set_channel_pwm_times(pca9685_handle_t *handle, unsigned channel, unsigned on_time, unsigned off_time);
/**
* Helper function to set the PWM duty cycle for a channel of a PCA9685 device. The duty cycle is either directly
* converted to a 12-bit value used for the PWM timings, if logarithmic is set to false, or an 8-bit value which is then
* transformed to a 12-bit value using a look up table for the PWM timings.
* Asserts that the duty cycle is between 0 and 1.
* @param handle Handle to a PCA9685 device.
* @param channel Channel to set the duty cycle of.
* @param duty_cycle Duty cycle to set.
* @param logarithmic Set to true to apply logarithmic function.
* @return True on success, false otherwise.
*/
bool pca9685_set_channel_duty_cycle(pca9685_handle_t *handle, unsigned channel, float duty_cycle, bool logarithmic);
bool pca9685_read_u8(pca9685_handle_t *handle, uint8_t address, uint8_t *dest);
bool pca9685_write_u8(pca9685_handle_t *handle, uint8_t address, uint8_t value);
具体代码,参考附件。
|