dyeatman
Joined: 06 Sep 2003 Posts: 1854 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!!!! |
|