How to set time period of pulse in PWM

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
kumar123
Posts: 68
Joined: 17 Oct 2023 07:32

How to set time period of pulse in PWM

#1 Post by kumar123 » 14 Dec 2023 05:56

Hi,
I am using PIC16f1526 micro-controller and PCA9685 IC to control servo motor. This below code I am using-

Code: Select all

#define Write_address 0x80  // I2C address for PCA9865 with no solder bridges
#define Read_address Write_address+1
#define PCA9685_software_reset 0x06
#define Reset   0x01        // Reset the device
#define MODE1   0x00        // 0x00 location for Mode1 register address
#define MODE2   0x01        // 0x01 location for Mode2 reigster address
#define LED0    0x06        // location for start of LED0 registers
#define ALL_CH_ON_L_reg   0xFA
#define ALL_CH_ON_H_reg   0xFB
#define ALL_CH_OFF_L_reg  0xFC
#define ALL_CH_OFF_H_reg  0xFD
#define HEARTBEAT LATC0_bit // green led on ETT board
sbit SCL_i2c at RC3_bit;
sbit SDA_i2c at RC4_bit;
sbit SCL_direction at TRISC3_bit;
sbit SDA_direction at TRISC4_bit;
////////////////////////////////////////////////////////////////////////////////
// Prototype functions - functions at end
void PCA9685_init();
void PCA9685_send(unsigned int value, unsigned char led);
void PCA9685AllLedOff();
unsigned char PCA9685_read_byte(unsigned char chip_register);
void PCA9685_write_byte(unsigned char chip_register, unsigned char value);
void PCA9685_write_word(unsigned char chip_register, unsigned int word_value);
void PCA9685_soft_reset();
////////////////////////////////////////////////////////////////////////////////
void main(){
    // block variables
    unsigned char              n = 0;   // LED flash
    unsigned int            loop = 0;   // loop counter
    unsigned int             pwm = 0;
    unsigned int                 x=0;
    
     OSCCON = 0x7a;    //0x7A     //122
     SCL_i2c = 0;
     SDA_i2c = 0;
     SCL_direction = 0;
     SDA_direction = 0;
  
    ADCON0 = 1;
   
    I2C1_Init(100000);
    PCA9685_init();

    PCA9685_send((int)4096 * 0.5 ,0); //     (int)4096 * 0.5
         
////////////////////////////////////////////////////////////////////////////////
// Functions
// Init the chip with pwm frequency and MODE2 settings
void PCA9685_init(){
     I2C1_start();             // Start
     I2C1_Wr(Write_address);   // Slave Write_address
     I2C1_Wr(MODE1);           // Mode 1 ADDRESS
     I2C1_Wr(0b00110001);      // Sleep and change default PWM frequency     00110001
     I2C1_stop();              // Stop
     delay_ms(1);              // Required 50 us delay
     I2C1_start();             // Start
     I2C1_Wr(Write_address);   // Slave Write_address
     I2C1_Wr(0xFE);            // PWM frequency PRE_SCALE ADDRESS to set pwm at 100Hz   fe
     I2C1_Wr(6);            // Osc_clk/(4096*update_rate)=25000000/(4096*100)=60=0x3C    //06
     I2C1_stop();              // Stop
     delay_ms(1);              // delay at least 500 us
     I2C1_start();             // Start
     I2C1_Wr(Write_address);   // Slave Write_address
     I2C1_Wr(MODE1);           // Mode 1 register ADDRESS
     I2C1_Wr(0b10100001);      // Set MODE1          //10100001
     I2C1_stop();              // Stop
     delay_ms(1);              // delay at least 500 us
     I2C1_start();             // Start
     I2C1_Wr(Write_address);   // Slave Address
     I2C1_Wr(MODE2);           // Mode2 register ADDRESS
     I2C1_Wr(0b00000100);      // Set MODE2 //00000100
     I2C1_stop();              //
}
// Send pulse length[0-4095] to selected LED/SERVO[0-15]
void PCA9685_send(unsigned int value, unsigned char led){
     unsigned char pulse_length;// temp variable for PWM
     I2C1_start();              // Start
     I2C1_Wr(Write_address);    // address of selected pca9685
     I2C1_Wr(LED0 + 4 * led);   // select slected LED ADDRESS
     I2C1_Wr(0x00);             // LED_ON_L    //00
     I2C1_Wr(0x00);             // LED_ON_H    // 00
     pulse_length = value;      // PWM value lo byte
     I2C1_Wr(pulse_length);     // LED_OFF_L
     pulse_length = value>>8;   // pwm 16 bit long, now shift upper 8 to lower 8
     I2C1_Wr(pulse_length);     // LED_OFF_H
     I2C1_stop();               // stop
}
void PCA9685AllLedOff(){
     I2C1_start();              // atart
     I2C1_Wr(Write_address);    // select pca9685
     I2C1_Wr(ALL_CH_OFF_L_reg); // All LEDs Off regiter
     I2C1_Wr(0b00000000);       // low byte
     I2C1_Wr(0b00010000);       // high byte, bit4 set so full_off see page 21
     I2C1_stop();               // Stop
}
// Read a byte and return it's value
unsigned char PCA9685_read_byte(unsigned char chip_register){
    unsigned char temp = 0x00;
    I2C1_Start();
    I2C1_Wr(Write_address);
    I2C1_Wr(chip_register);
    I2C1_Start();
    I2C1_Wr(Read_address);
    temp = I2C1_Rd(0);
    I2C1_Stop();
    return temp;
}
void PCA9685_write_byte(unsigned char chip_register, unsigned char value){
     I2C1_Start();
     I2C1_Wr(Write_address);
     I2C1_Wr(chip_register);
     I2C1_Wr(value);
     I2C1_Stop();
}
// Write 16bits to chip_register, increments automatically from lo to hi byte
void PCA9685_write_word(unsigned char chip_register, unsigned int word_value){
     unsigned char hb = 0x00;
     unsigned char lb = 0x00;
     lb = (word_value & 0x00FF);
     hb = ((word_value & 0xFF00) >> 0x08);
     PCA9685_write_byte(chip_register,lb);
     PCA9685_write_byte((chip_register+1),hb);
}
// Soft re-set
void PCA9685_soft_reset(){
    I2C1_Start();
    I2C1_Wr(0x00);
    I2C1_Wr(PCA9685_software_reset);
    I2C1_Stop();
}
This code is giving controlled duty cycle like 50%, 25%, etc. But I am not able to set the time period of Pulse 1ms. How to do this?
t1.png
t1.png (6.06 KiB) Viewed 160 times
Currently It's giving first one pulse, And now I am expecting second one pulse

Regards,
Kumar

Post Reply

Return to “mikroC PRO for PIC General”