PCA9685는 I2C통신을 이용해서 PWM 신호 파형을 출력해주는 역할을 합니다
데이터시트를 읽어보시면 더욱 도움이 됩니다.
PCA9685 pdf, PCA9685 부품 상세설명, PCA9685 데이터시트, PCA9685 view ::: ALLDATASHEET :::
PCA9685 pdf, PCA9685 부품 상세설명, PCA9685 데이터시트, PCA9685 view ::: ALLDATASHEET :::
부품명 PCA9685 부품 상세설명 16-channel 12-bit PWM Fm I2C-bus LED controller 파일 크기 404.92 Kbytes Html View 1 2 3 4 5 6 7 8 9 More 제조업체 PHILIPS [NXP Semiconductors] 홈페이지 htt
pdf1.alldatasheet.co.kr
사용한 모듈은 아래와 같이 생겼습니다.
생각보다 저렴해서 추후 필요할 때 사용하면 유용하게 사용이 가능할 것 같네요 ^^;;
회로도도 같이 제공하니 참고하시면 좋을 듯 합니다.
저는 해당 IC를 사용하여 PCB를 제작하는 경우도 있으니 매우 유용한 자료네요 ^^;
MCU 보드는 AVR128DA48 Curiosity Nano 보드를 사용하였고
연결은 전원과 TWI0 (PA2, PA3)과 SDA, SCL을 연결하였습니다.
기본 Adafruit에서 제공하는 아두이노 라이브러리를 필요한 부분을 수정하여 사용하였습니다.
#include "pca9685.h"
#include "i2c.h"
void pca9685_begin(void)
{
pca9685_reset();
}
//
// /*!
// * @brief Sends a reset command to the PCA9685 chip over I2C
// */
void pca9685_reset()
{
uint8_t command1[2] = {PCA9685_MODE1, MODE1_RESTART}; // Normal mode
uint8_t command2[2] = {PCA9685_MODE2, MODE2_OUTDRV}; // Totem pole
i2cSendData((PCA9685_I2C_ADDRESS << 1), command1, 2);
i2cEndSession();
i2cSendData((PCA9685_I2C_ADDRESS << 1), command2, 2);
i2cEndSession();
_delay_ms(10);
}
/*!
* @brief Puts board into sleep mode
*/
void pca9685_sleep()
{
uint8_t awake = PCA9685_MODE1;
i2cGetData((PCA9685_I2C_ADDRESS << 1), &awake, 1);
i2cEndSession();
uint8_t sleep = awake | MODE1_SLEEP;
uint8_t command[] = {PCA9685_MODE1, sleep};
i2cSendData((PCA9685_I2C_ADDRESS << 1), command, 2);
_delay_ms(5); // wait until cycle ends for sleep to be active
}
/*!
* @brief Wakes board from sleep
*/
void pca9685_wakeup()
{
uint8_t sleep = PCA9685_MODE1;
i2cGetData((PCA9685_I2C_ADDRESS << 1), &sleep, 1);
i2cEndSession();
uint8_t wakeup = sleep & ~MODE1_SLEEP;
uint8_t command[] = {PCA9685_MODE1, wakeup};
i2cSendData((PCA9685_I2C_ADDRESS << 1), command, 2);
_delay_ms(5); // wait until cycle ends for sleep to be active
}
/*!
* @brief Sets the PWM frequency for the entire chip, up to ~1.6 KHz
* @param freq Floating point frequency that we will attempt to match
*/
void pca9685_setPWMFreq(uint16_t freq)
{
pca9685_sleep();
uint8_t prescaleval = ((FREQUENCY_OSCILLATOR / (freq * 4096.0)) + 0.5) - 1;
uint8_t command[2] = {PCA9685_PRESCALE, prescaleval}; // PWM Freq
i2cSendData((PCA9685_I2C_ADDRESS << 1), command, 2);
i2cEndSession();
pca9685_reset();
}
/*!
* @brief Gets the PWM output of one of the PCA9685 pins
* @param num One of the PWM output pins, from 0 to 15
* @return requested PWM output value
*/
uint8_t pca9685_getPWM(uint8_t num)
{
uint8_t ret;
uint8_t command = PCA9685_LED0_ON_L + 4 * num;
ret = i2cGetData((PCA9685_I2C_ADDRESS << 1), &command, 4);
i2cEndSession();
return ret;
}
/*!
* @brief Sets the PWM output of one of the PCA9685 pins
* @param num One of the PWM output pins, from 0 to 15
* @param on At what point in the 4096-part cycle to turn the PWM output ON
* @param off At what point in the 4096-part cycle to turn the PWM output OFF
*/
void pca9685_setPWM(uint8_t num, uint16_t on, uint16_t off)
{
uint8_t command1[2] = {PCA9685_LED0_ON_L + 4 * num, on & 0xFF};
uint8_t command2[2] = {PCA9685_LED0_ON_H + 4 * num, on >> 8};
uint8_t command3[2] = {PCA9685_LED0_OFF_L + 4 * num, off & 0xFF};
uint8_t command4[2] = {PCA9685_LED0_OFF_H + 4 * num, off >> 8};
i2cSendData(PCA9685_I2C_ADDRESS << 1, command1, 2);
i2cEndSession();
i2cSendData(PCA9685_I2C_ADDRESS << 1, command2, 2);
i2cEndSession();
i2cSendData(PCA9685_I2C_ADDRESS << 1, command3, 2);
i2cEndSession();
i2cSendData(PCA9685_I2C_ADDRESS << 1, command4, 2);
i2cEndSession();
}
항상 통신을 할때마다 약간의 애를 먹는데 이번에는 조금 빠르게 마무리가 됐습니다.
이번에 새로들인 로직 아날라이저가 많은 도움이 됐네요... ^^;;
사용 중인 오실로스코프로는 데이터 보기가 넘 힘들어서...ㅜㅜ
'b. 임베디드 > AVR' 카테고리의 다른 글
[ATtiny1616] TCB를 이용한 millis()함수 만들기 (0) | 2022.04.30 |
---|---|
[ATtiny1616] GPIO 예제 (0) | 2022.04.28 |
[ATtiny1616] 메인 Clock 설정 (0) | 2022.04.27 |
[AVR128DA48] 타이머 TCB0 예제 (0) | 2022.04.06 |
[AVR128DA] Bootloader (0) | 2021.12.01 |
AVR128DA48 CURIOSITY Nano 시작... (0) | 2021.11.12 |
[ATtiny1616] 40W BLDC Motor 제어 (2) | 2021.06.23 |
[경험담] ATmega 포트 Tri-state (Hi-Z상태) (0) | 2019.08.08 |