2462 views|1 replies

530

Posts

4

Resources
The OP
 

ST MEMS Creative Competition Post 4 - Robotic Arm Control [Copy link]

 This post was last edited by a media student on 2020-5-10 21:30

Since the project will eventually drive the robotic arm to achieve gesture or voice tracking, it is best to use a driver board to drive the robotic arm. Therefore, I bought a driver module online, PCA9685, which can drive 16-channel PWM.

Since the MEMS MCU does not have a reserved GPIO port, the STM32F429 is used as the main control MCU to drive the I2C PWM driver.

STM32F429 mainly implements the following functions:

1. Use the serial port to receive commands from the PC. These commands are based on the sensor values obtained by ST MEMS and combined with the LSM6DSOX machine learning core to finally send out data.

2. Parse the data in the serial port, drive the I2C PWM driver, and control the robotic arm to achieve tracking function.

Here, first share 2. Here, the hardware I2C driver pac9685 is used, and the HAL library is used for operation. The specific program engineering is attached. The library that drives PCA9685 is found on github and ported to STM32F4. You can refer to it if you are interested.

There is a pitfall in PCA9685 here, let me point it out to you: this module bought online, see the picture below:

The PAC9685 output terminal configuration is as follows:

This chip was originally used to drive LEDs, and has been used by robot enthusiasts to drive motors, which is of course possible; but there are some people selling this module online, and I don’t know where they got it from. There is no schematic diagram, and the information is also online.

I re-read the manual and found that the output needs to add a pull-up resistor, but the module I bought did not have one, which wasted a day of my time. If I did not add the pull-up resistor, the waveform amplitude was very small, about tens of mV. If I did not have the logic analyzer, to be honest, I would probably use STM23F429 to generate multi-channel PWM; Finally, I read the manual and added a pull-up resistor to the output part behind the driver board to pull it to 5V, but in fact it only needs to be pulled to 3.3V. Then, I can drive my robotic arm.

The main program is as follows:

I won’t post much about the program, hardware I2C, PCA9685driver driver, STM32F4 MCU: use STM32CubeMX to generate HAL library.

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);
	

For specific codes, please refer to the attachment.

pca9685.h

3.28 KB, downloads: 0

pca9685.c

8.05 KB, downloads: 0

Latest reply

Great! This looks good.   Details Published on 2020-5-11 11:39
 
 

1w

Posts

204

Resources
2
 

Great! This looks good.

Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
Personal signature

玩板看这里:

http://en.eeworld.com/bbs/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!

 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews

Room 1530, Zhongguancun MOOC Times Building, Block B, 18 Zhongguancun Street, Haidian District, Beijing 100190, China Tel:(010)82350740 Postcode:100190

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list