Red/Green/Blue/Amber (RGBA) color backlighting applications. Each LED output has its
own 12-bit resolution (4096 steps) fixed frequency individual PWM controller that operates
at a programmable frequency from a typical of 40 Hz to 1000 Hz with a duty cycle that is
adjustable from 0 % to 100 % to allow the LED to be set to a specific brightness value.
All outputs are set to the same PWM frequency.
begin()
init()
setLEDDimmed()
sample code 如下:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define PCA9685_MODE1 0x00 // location for Mode1 register address | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define PCA9685_MODE2 0x01 // location for Mode2 reigster address | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define PCA9685_LED0 0x06 // location for start of LED0 registers | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define PCA9685_I2C_BASE_ADDRESS B1000000 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class PCA9685 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //NB the i2c address here is the value of the A0, A1, A2, A3, A4 and A5 pins ONLY | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //as the class takes care of its internal base address. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //so i2cAddress should be between 0 and 63 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PCA9685(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void begin(int i2cAddress); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bool init(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void setLEDOn(int ledNumber); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void setLEDOff(int ledNumber); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void setLEDDimmed(int ledNumber, byte amount); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void writeLED(int ledNumber, word outputStart, word outputEnd); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void writeRegister(int regaddress, byte val); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| word readRegister(int regAddress); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Our actual i2c address: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| byte _i2cAddress; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; |
| #include "PCA9685.h" | |
| PCA9685::PCA9685() {} | |
| void PCA9685::begin(int i2cAddress) { | |
| _i2cAddress = PCA9685_I2C_BASE_ADDRESS | (i2cAddress & B00111111); | |
| } | |
| bool PCA9685::init() { | |
| delay(1); | |
| writeRegister(PCA9685_MODE1, (byte)0x01); // reset the device | |
| delay(1); | |
| bool isOnline; | |
| if (readRegister(PCA9685_MODE1)==0x01) { | |
| isOnline = true; | |
| } else { | |
| isOnline = false; | |
| } | |
| writeRegister(PCA9685_MODE1, (byte)B10100000); // set up for auto increment | |
| writeRegister(PCA9685_MODE2, (byte)0x10); // set to output | |
| return isOnline; | |
| } | |
| void PCA9685::setLEDOn(int ledNumber) { | |
| writeLED(ledNumber, 0x1000, 0); | |
| } | |
| void PCA9685::setLEDOff(int ledNumber) { | |
| writeLED(ledNumber, 0, 0x1000); | |
| } | |
| void PCA9685::setLEDDimmed(int ledNumber, byte amount) { // Amount from 0-100 (off-on) | |
| if (amount==0) { | |
| setLEDOff(ledNumber); | |
| } else if (amount>=100) { | |
| setLEDOn(ledNumber); | |
| } else { | |
| int randNumber = (int)random(4096); // Randomize the phaseshift to distribute load. Good idea? Hope so. | |
| writeLED(ledNumber, randNumber, (int)(amount*41+randNumber) & 0xFFF); | |
| } | |
| } | |
| void PCA9685::writeLED(int ledNumber, word LED_ON, word LED_OFF) { // LED_ON and LED_OFF are 12bit values (0-4095); ledNumber is 0-15 | |
| if (ledNumber >=0 && ledNumber <= 15) { | |
| Wire.beginTransmission(_i2cAddress); | |
| Wire.write(PCA9685_LED0 + 4*ledNumber); | |
| Wire.write(lowByte(LED_ON)); | |
| Wire.write(highByte(LED_ON)); | |
| Wire.write(lowByte(LED_OFF)); | |
| Wire.write(highByte(LED_OFF)); | |
| Wire.endTransmission(); | |
| } | |
| } | |
| //PRIVATE | |
| void PCA9685::writeRegister(int regAddress, byte data) { | |
| Wire.beginTransmission(_i2cAddress); | |
| Wire.write(regAddress); | |
| Wire.write(data); | |
| Wire.endTransmission(); | |
| } | |
| word PCA9685::readRegister(int regAddress) { | |
| word returnword = 0x00; | |
| Wire.beginTransmission(_i2cAddress); | |
| Wire.write(regAddress); | |
| Wire.endTransmission(); | |
| Wire.requestFrom((int)_i2cAddress, 1); | |
| // int c=0; | |
| //Wait for our 2 bytes to become available | |
| while (Wire.available()) { | |
| //high byte | |
| // if (c==0) { returnword = Wire.read() << 8; } | |
| //low byte | |
| // if (c==1) { | |
| returnword |= Wire.read(); | |
| //} | |
| //c++; | |
| } | |
| return returnword; | |
| } |
沒有留言:
張貼留言