2016年4月13日 星期三

PCA9685

The PCA9685 is an I2C-bus controlled 16-channel LED controller optimized for LCD
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 如下:
PCA9685 ledDriver;
void setup()
{
Serial.begin(9600); // set up serial
Serial.println("Serial Started");
Wire.begin(); // Wire must be started!
ledDriver.begin(B111000); // Address pins A5-A0 set to B111000
ledDriver.init();
}
void loop()
{
// Notice: setLEDDimmed cannot be used in a loop to give you a pleasant
// "turning-up" of the LED. This is because each time you set a level for a LED
// it will calculate random timing intervals for the PWM function in the chip
// This is done in order to distribute current consumptions of the full time period.
for(int level=5;level>=0;level--) {
for(int i=0; i<16; i++) {
ledDriver.setLEDDimmed(i,level*20);
delay(100);
}
}
for(int level=0;level<=5;level++) {
for(int i=0; i<16; i++) {
ledDriver.setLEDDimmed(i,level*20);
delay(100);
}
}
}
//Register defines from data sheet
#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;
}
Reference https://github.com/kasperskaarhoj/PCA9685-Arduino-Library

沒有留言:

張貼留言