2
\$\begingroup\$

I'm trying to generate PWM signals for a stepper motor with a PCA9685 development board and an MCU (STM32F4). I'm able to write and read all commands to the chip via I2C — and verify that everything I send is transferred correctly. I'm using the internal oscillator of the chip.

Currently, the chip is configured to 50 Hz (Register 0xFE set to value 0x90). A logic analyzer shows a repetition frequency of 49.18 Hz. When I write values from 205 to 450 to the OFF register (address 0x08 and 0x09), I’m only getting a pulse width from 1.02 ms down to 0.7658 ms (yes the direction seems to decrease with increasing value). No matter how I adjust the OFF register value, I can't seem to achieve any pulse widths greater than ~1 ms (not 1.5 ms and not 2 ms).

Has anyone worked with the PCA9685 chip before? Do you have any recommendations on how to fix this or what to check?

Datasheet for reference

Code Snipped of STM32F4:

int main(void)
{
   //initialization
   SystemClock_Config();
   GPIO_Config();
   //Reset PCA9685
   I2C_config();
   I2C_start();
   I2C_addr(0x00);
   I2C_write(0x06);
   I2C_stop();
   //Set Frequency
   I2C_start();
   I2C_addr(0x80);
   I2C_write(0xFE);
   I2C_write(0x90);
   I2C_stop();
   //Read current status
   I2C_start();
   I2C_addr(0x80);
   I2C_write(0xFE);
   I2C_start();
   I2C_addr(0x80|1);
   register_return_value = I2C_read(0);
   I2C_stop();
   //Read current status
   I2C_start();
   I2C_addr(0x80);
   I2C_write(0x00);
   I2C_start();
   I2C_addr(0x80|1);
   register_return_value = I2C_read(0);
   I2C_stop();
   //Write Value
   I2C_start();
   I2C_addr(0x80);
   I2C_write(0x00);
   I2C_write((register_return_value & ~(0x10)));
   I2C_stop();
   //Read current status
   I2C_start();
   I2C_addr(0x80);
   I2C_write(0x00);
   I2C_start();
   I2C_addr(0x80|1);
   register_return_value = I2C_read(0);
   I2C_stop();
   uint16_t pwm_value = 205;
 //
 I2C_start();
 I2C_addr(0x80);
 I2C_write(0x06);
 I2C_write(0x00);
 I2C_stop();
   //
 I2C_start();
 I2C_addr(0x80);
 I2C_write(0x07);
 I2C_write(0x00);
 I2C_stop();
 //
 I2C_start();
 I2C_addr(0x80);
 I2C_write(0x08);
 I2C_write(0xFF & pwm_value);
 I2C_stop();
 //
 I2C_start();
 I2C_addr(0x80);
 I2C_write(0x09);
 I2C_write(0x0F & (pwm_value << 8));
 I2C_stop();
}
brhans
15.1k3 gold badges36 silver badges51 bronze badges
asked Jul 9 at 19:59
\$\endgroup\$
10
  • \$\begingroup\$ Please add your full code! I know the PCA very well and will try to help but seeing everything you're doing would be very helpful. Also some O-Scope captures would be great. When you write a value higher than 405, does it just max out at ~1ms no matter how high you go or is there other behavior? \$\endgroup\$ Commented Jul 9 at 20:09
  • \$\begingroup\$ The pulse width decreasing suggests you're configuring the registers incorrectly. Seeing the register values for registers 0x01, 0x02, and 0x06-0x09 would be what to check. \$\endgroup\$ Commented Jul 9 at 20:18
  • \$\begingroup\$ When I input increasing values, I get a pulse width that first increases and then decreases, but it never exceeds 1.2 ms. I will add the code below. \$\endgroup\$ Commented Jul 9 at 20:20
  • \$\begingroup\$ @InBedded16 Registers 0x06 to 0x09 have the values I have configure them. 0x06=0x00; 0x07=0x00; 0x08=0xCD (for 205dec) and 0x09=0x00; \$\endgroup\$ Commented Jul 9 at 20:27
  • \$\begingroup\$ @InBedded16 sure you mean 0x01 and 0x02 not 0x00 and 0x01? either way: 0x01=0x04 and 0x02=0xe2; 0x00=0x01 \$\endgroup\$ Commented Jul 9 at 20:29

2 Answers 2

5
\$\begingroup\$
I2C_write(0x0F & (pwm_value << 8));

This line is shifting pwm_value in the wrong direction, so it will always write 0 to the high byte of the register. It should be:

I2C_write(0x0F & (pwm_value >> 8));
answered Jul 10 at 4:37
\$\endgroup\$
1
  • \$\begingroup\$ Thanks, just noticed that... should have noticed myself :) \$\endgroup\$ Commented Jul 10 at 10:12
5
\$\begingroup\$

The code writes PWM value incorrectly.

The register 8 is written correctly for the low byte, but register 9 gets always written as 0.

Basically after 255 the PWM value wraps back to 0 which would explain what you are experiencing.

answered Jul 9 at 21:33
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.