![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
DC Motor Library for Adafruit Motor Driver V2 board |
Posted: Sun Oct 26, 2014 8:15 pm |
|
|
This is a basic library for DC motor control using the Adafruit
Motor/Servo Driver V2 board. This library does NOT support
Servo/Stepper control.
Be sure to use PCM Programmers' Bus Scanner in the Code library
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
to confirm I2C communications then set the PCA9685 Address
(typically 0xC0 or 0x80) in the first line of the library
below BEFORE trying to use this library!
Code: | /*****************************************
* File: pca9685_DC_Motor_Library.h *
* CCS C Compatible driver library for *
* driving DC Motors using Adafruit *
* Motor Shield Version 2 *
*****************************************/
/* General registers */
#define PCA_addr 0xC0 // address of the PCA9685 PWM Chip
#define MODE1 0x00 // Mode1 Register Address
#define CHAN0 0x06 // Chan 0 register Address
#define PCA9685AI 0x20 // Mode1 Autoincrement bit
#define PreScale 0xFE // Prescale Register
#define Sleep 0x10 // Mode1 Sleep Bit
//
int PWMChan,IN1,IN2;
//
void pca9685_init(int address)
{
/********************************************
* Init PCA9685 *
* Input:[address of the pc9685 to init] *
* Output:[void] *
/********************************************/
i2c_start(); // Send Start
i2c_write(address+write); // Send PCA address + write
i2c_write(MODE1); // write control register address
i2c_write(PCA9685AI); // Set MODE1 = INT_CLK, AutoIncrement, Normal
// no need to set Mode2 - defaults are good
i2c_stop(); // Send Stop
delay_us(500); // required for PCA oscillator startup
}
//
void pca9685_Set_rate(int address, rate)
{ // set rate in PreScale register
i2c_start(); // Send Start
i2c_write(address+write); // Send PCA address + write
i2c_write(MODE1); // write control register address
i2c_write(sleep); // Set MODE1 register = Sleep Mode
i2c_start(); // Send restart
i2c_write(address+write); // Send PCA address + write
i2c_write(prescale); // write prescale control register address
i2c_write(rate); // Set prescale register to desired rate/frequency.
i2c_start(); // Send restart
i2c_write(address+write); // Send PCA address + write
i2c_write(MODE1); // write control register address
i2c_write(PCA9685AI); // Set MODE1 back to INT_CLK, AutoIncrement, Normal
i2c_stop(); // Send Stop
delay_us(500); // required for PCA oscillator startup
}
//
void pca9685_set_chan_registers(int8 PCA_address, int8 channel, int16 ONvalue, int16 OFFValue)
{
/***************************************************
* pca9685_set_chan_registers(int8 PCA_address, int8 Channel, int16 ONvalue, int16 OFFValue)
* Send 12 bit PWM data to the registers *
* Input[ address, Channel_0to15, pwmON, pwmOFF] *
* Output[void] *
***************************************************/
i2c_start(); // Send Start
i2c_write(pca_address); // Address of selected pca9685
i2c_write(Chan0+(4 * channel)); // output desired PCA9685 channel
i2c_write(ONValue & 0xff); // Chan_ON_L low byte
i2c_write(ONValue >>8); // Chan_ON_L High Byte
i2c_write(OFFValue & 0xFf); // Chan_OFF_L low byte
i2c_write(OFFValue >> 8); // Chan_OFF_L High Byte
i2c_stop(); // Send Stop
}
//
void pca9685_set_chan_off(int8 PCA_address, int8 Chan)
{
pca9685_set_chan_registers(PCA_address,Chan, 0x0000, 0x0000);
}
//
void pca9685_set_chan_on(int8 PCA_address, int8 Chan)
{
pca9685_set_chan_registers(PCA_address,Chan, 0xFF00, 0x0F00);
}
void Set_PCA_Channels(mtr_num)
{
switch(mtr_num) { // use motor number to select PCA channels
// required on the Adafruit Motor Driver V2 board
case 1:
{ // Motor 1 selected
PWMChan=8;
IN1=10;
IN2=9;
break;
}
case 2:
{ // Motor 2 selected
PWMChan=13;
IN1=11;
IN2=12;
break;
}
case 3:
{ // Motor 3 selected
PWMChan=2;
IN1=4;
IN2=3;
break;
}
case 4:
{ // Motor 4 selected
PWMChan=7;
IN1=5;
IN2=6;
break;
}
}
}
//
void run_motor_CW(int8 PCA_Address, int8 mtr_num, int16 DutyCycle) // DutyCycle=0-100
{ // IN1=Low, IN2=High
int16 offvalue;
//
Set_PCA_Channels(mtr_num); // translate motor number to PCA channels
// Clockwise requires IN1=High, IN2=Low
pca9685_set_chan_on ( PCA_address, IN1); // IN1
pca9685_set_chan_off( PCA_address, IN2); // IN2
// calculate numbers from speed value provided
offValue = DutyCycle * 41; // 0 - 4100
if (offValue > Speedmax)
{
pca9685_set_chan_on(PCA_address, pwmchan);
}
//
else if (offValue < Speedmin)
{
pca9685_set_chan_off(PCA_address, pwmchan);
}
else
{
// otherwise fall through and set the duty cycle
/* pca9685_set_chan_registers(int8 PCA_address, int8 PWMChan, int16 ONvalue, int16 OFFValue) */
pca9685_set_chan_registers(PCA_address, pwmchan, 0x0, offvalue);
}
}
//
void run_motor_CCW(int8 PCA_Address, int8 mtr_num, int16 DutyCycle) // DutyCycle 0-100
{ // CCW requires IN1=Low, IN2=High
int16 offvalue;
//
Set_PCA_Channels(mtr_num); // translate motor number to PCA channels on Adafruit Board
//
pca9685_set_chan_off( PCA_address, IN1); // IN1
pca9685_set_chan_on ( PCA_address, IN2); // IN2
// calculate PWM numbers from DutyCycle 0-100 value provided
offValue = DutyCycle * 41; // 0 - 4100
if (offValue > Speedmax)
{
pca9685_set_chan_on(PCA_address, pwmchan);
}
//
else if (offValue < Speedmin)
{
pca9685_set_chan_off(PCA_address, pwmchan);
}
else
{
// otherwise fall through and set the duty cycle
/* pca9685_set_chan_registers(int8 PCA_address, int8 PWMChan, int16 ONvalue, int16 OFFValue) */
pca9685_set_chan_registers(PCA_address, pwmchan, 0x0, offvalue);
}
}
//
void Motor_STOP(int8 PCA_Address, int8 mtr_num)
{ // Stop Motor on a selected channel
Set_PCA_Channels(mtr_num); // translate motor number to proper PCA channels
//
pca9685_set_chan_off( PCA_address, IN1); // IN1
pca9685_set_chan_off ( PCA_address, IN2); // IN2
pca9685_set_chan_off( PCA_address, pwmchan); // PWM output off
}
//
void All_Motors_Stop(int8 PCA_Address)
{ // Stop All motors on all channels
int8 mnum;
//
for (mnum=1;mnum<=4; mnum++)
{
Set_PCA_Channels(mnum); // translate motor number to proper PCA channels
pca9685_set_chan_off(PCA_address,IN1); // IN1
pca9685_set_chan_off(PCA_address,IN2); // IN2
pca9685_set_chan_off(PCA_address, pwmchan); // PWM output off
}
}
/*************** End of library *******************/
|
Example calls from Main program
Code: |
pca9685_Set_rate(PCA_Addr, 20); // set pulse frequency by varying prescale register
pca9685_init (PCA_Addr); // set normal mode
//
run_motor_CW(PCA_Addr, 1, 50 ); // Run Motor 1 Clockwise w/duty cycle=50%
delay_ms(1500); // run for 1.5 seconds
Motor_stop(pca_addr, 1); //stop motor 1
delay_ms(500); //wait 500ms for motor to stop
run_motor_CCW(PCA_Addr, 1, 50); // Run Motor 1 CCW w/duty cycle=50%
delay_ms(1500); // run for 1.5 seconds
Motor_stop(pca_addr, 1); // stop Motor 1
|
_________________ Google and Forum Search are some of your best tools!!!! |
|
![](templates/subSilver/images/spacer.gif) |
ciuffoly
Joined: 25 Aug 2023 Posts: 1
|
|
Posted: Fri Aug 25, 2023 12:38 am |
|
|
Hello, I am trying to drive a DC motor with PCA9685, it runs but never at full speed.
Code: |
i2c_start(); //Start signal
i2c_write(0x80) ; //Specifying slave address in write mode
i2c_write(0x00); //Control register set to address 00h
i2c_write(0x20);
//i2c_write(0x21); // Mode 1 configured to with AI=1 and ALLCALL=1
// 00100001
// |||||||+-- PCA9685 responds to LED All Call I2C-bus address
// ||||||+--- PCA9685 does not respond to I2C-bus subaddress 3
// |||||+---- PCA9685 does not respond to I2C-bus subaddress 2
// ||||+----- PCA9685 does not respond to I2C-bus subaddress 1
// |||+------ Normal mode[2]
// |+------- Register Auto-Increment enabled.
// +-------- Use internal clock.Use internal clock.
i2c_stop(); //Stop signal
unsigned int on_count = 0xFFF; // ex 99
unsigned int off_count = 0x00; // ex 66
ledn = 1;
i2c_start();
i2c_write(0x80);
i2c_write((ledn*4)+6);
i2c_write(on_count&0xFF);
i2c_write((on_count&0xF00)>>8);
i2c_write(off_count&0xFF);
i2c_write((off_count&0xF00)>>8);
i2c_stop(); |
|
|
![](templates/subSilver/images/spacer.gif) |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
|
Posted: Sat Sep 09, 2023 4:33 pm |
|
|
What processor, motor and power supply are you trying to use? _________________ Google and Forum Search are some of your best tools!!!! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|