CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DC Motor Library for Adafruit Motor Driver V2 board

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
dyeatman



Joined: 06 Sep 2003
Posts: 1933
Location: Norman, OK

View user's profile Send private message

DC Motor Library for Adafruit Motor Driver V2 board
PostPosted: Sun Oct 26, 2014 8:15 pm     Reply with quote

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!!!!
ciuffoly



Joined: 25 Aug 2023
Posts: 1

View user's profile Send private message Send e-mail

PostPosted: Fri Aug 25, 2023 12:38 am     Reply with quote

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



Joined: 06 Sep 2003
Posts: 1933
Location: Norman, OK

View user's profile Send private message

PostPosted: Sat Sep 09, 2023 4:33 pm     Reply with quote

What processor, motor and power supply are you trying to use?
_________________
Google and Forum Search are some of your best tools!!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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