0.4.3 PCA9635

This commit is contained in:
rob tillaart 2023-03-07 16:18:49 +01:00
parent 972102e1ce
commit 6b5a5cc638
13 changed files with 363 additions and 130 deletions

View File

@ -6,7 +6,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update

View File

@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6

View File

@ -10,7 +10,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:

View File

@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.3] - 2023-01-23
- update GitHub actions
- update license 2023
- add OutputEnable control functions.
- add example **PCA9635_OE_control.ino**
- update unit test.
- **configure()** now returns error state
- update readme.md
- minor edits
## [0.4.2] - 2022-11-19
- add RP2040 in build-CI

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016-2022 Rob Tillaart
Copyright (c) 2016-2023 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -2,7 +2,7 @@
// FILE: PCA9635.cpp
// AUTHOR: Rob Tillaart
// DATE: 23-apr-2016
// VERSION: 0.4.2
// VERSION: 0.4.3
// PURPOSE: Arduino library for PCA9635 I2C LED driver
// URL: https://github.com/RobTillaart/PCA9635
@ -16,9 +16,12 @@
//
PCA9635::PCA9635(const uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_channelCount = 16;
_address = deviceAddress;
_wire = wire;
_channelCount = 16;
_data = 0;
_error = PCA9635_OK;
_OutputEnablePin = 255;
}
@ -48,6 +51,22 @@ bool PCA9635::begin(uint8_t mode1_mask, uint8_t mode2_mask)
}
uint8_t PCA9635::configure(uint8_t mode1_mask, uint8_t mode2_mask)
{
_data = 0;
_error = PCA9635_OK;
uint8_t r1 = setMode1(mode1_mask);
uint8_t r2 = setMode2(mode2_mask);
if ((r1 != PCA9635_OK) || (r2 != PCA9635_OK))
{
return PCA9635_ERROR;
}
return _error;
}
bool PCA9635::isConnected()
{
_wire->beginTransmission(_address);
@ -56,13 +75,9 @@ bool PCA9635::isConnected()
}
void PCA9635::configure(uint8_t mode1_mask, uint8_t mode2_mask)
uint8_t PCA9635::channelCount()
{
_data = 0;
_error = 0;
setMode1(mode1_mask);
setMode2(mode2_mask);
return _channelCount;
}
@ -88,7 +103,7 @@ uint8_t PCA9635::writeN(uint8_t channel, uint8_t* arr, uint8_t count)
{
if (channel + count > _channelCount)
{
_error = PCA9635_ERR_WRITE;
_error = PCA9635_ERR_CHAN;
return PCA9635_ERROR;
}
uint8_t base = PCA9635_PWM(channel);
@ -104,7 +119,8 @@ uint8_t PCA9635::writeN(uint8_t channel, uint8_t* arr, uint8_t count)
_error = PCA9635_ERR_I2C;
return PCA9635_ERROR;
}
return PCA9635_OK;
_error = PCA9635_OK;
return _error;
}
@ -116,7 +132,7 @@ uint8_t PCA9635::writeMode(uint8_t reg, uint8_t value)
return PCA9635_OK;
}
_error = PCA9635_ERR_REG;
return PCA9635_ERROR;
return _error;
}
@ -130,7 +146,7 @@ uint8_t PCA9635::readMode(uint8_t reg)
return value;
}
_error = PCA9635_ERR_REG;
return PCA9635_ERROR;
return _error;
}
@ -154,7 +170,8 @@ uint8_t PCA9635::setLedDriverMode(uint8_t channel, uint8_t mode)
uint8_t clrmask = ~(0x03 << shift);
uint8_t value = (readReg(reg) & clrmask) | setmask;
writeReg(reg, value);
return PCA9635_OK;
_error = PCA9635_OK;
return _error;
}
@ -168,13 +185,16 @@ uint8_t PCA9635::getLedDriverMode(uint8_t channel)
}
uint8_t reg = PCA9635_LEDOUT_BASE + (channel >> 2);
uint8_t shift = (channel & 0x03) * 2; // 0,2,4,6 places
uint8_t shift = (channel & 0x03) * 2; // 0, 2, 4, 6 places
uint8_t value = (readReg(reg) >> shift ) & 0x03;
return value;
}
// note error flag is reset after read!
/////////////////////////////////////////////////////
//
// ERROR
//
int PCA9635::lastError()
{
int e = _error;
@ -183,7 +203,6 @@ int PCA9635::lastError()
}
/////////////////////////////////////////////////////
//
// SUB CALL - ALL CALL
@ -192,12 +211,16 @@ bool PCA9635::enableSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t prev = getMode1();
uint8_t reg = prev;
if (nr == 1) reg |= PCA9635_MODE1_SUB1;
else if (nr == 2) reg |= PCA9635_MODE1_SUB2;
else reg |= PCA9635_MODE1_SUB3;
uint8_t mask = prev;
if (nr == 1) mask |= PCA9635_MODE1_SUB1;
else if (nr == 2) mask |= PCA9635_MODE1_SUB2;
else mask |= PCA9635_MODE1_SUB3;
// only update if changed.
if (reg != prev) setMode1(reg);
if (mask != prev)
{
setMode1(mask);
// TODO error handling ...
}
return true;
}
@ -206,12 +229,16 @@ bool PCA9635::disableSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t prev = getMode1();
uint8_t reg = prev;
if (nr == 1) reg &= ~PCA9635_MODE1_SUB1;
else if (nr == 2) reg &= ~PCA9635_MODE1_SUB2;
else reg &= ~PCA9635_MODE1_SUB3;
uint8_t mask = prev;
if (nr == 1) mask &= ~PCA9635_MODE1_SUB1;
else if (nr == 2) mask &= ~PCA9635_MODE1_SUB2;
else mask &= ~PCA9635_MODE1_SUB3;
// only update if changed.
if (reg != prev) setMode1(reg);
if (mask != prev)
{
setMode1(mask);
// TODO error handling ...
}
return true;
}
@ -219,16 +246,20 @@ bool PCA9635::disableSubCall(uint8_t nr)
bool PCA9635::isEnabledSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t reg = getMode1();
if (nr == 1) return (reg & PCA9635_MODE1_SUB1) > 0;
if (nr == 2) return (reg & PCA9635_MODE1_SUB2) > 0;
return (reg & PCA9635_MODE1_SUB3) > 0;
uint8_t mask = getMode1();
if (nr == 1) return (mask & PCA9635_MODE1_SUB1) > 0;
if (nr == 2) return (mask & PCA9635_MODE1_SUB2) > 0;
return (mask & PCA9635_MODE1_SUB3) > 0;
}
bool PCA9635::setSubCallAddress(uint8_t nr, uint8_t address)
{
if ((nr == 0) || (nr > 3)) return false;
if ((nr == 0) || (nr > 3))
{
// _error = ?? TODO
return false;
}
writeReg(PCA9635_SUBADR(nr), address);
return true;
}
@ -236,7 +267,11 @@ bool PCA9635::setSubCallAddress(uint8_t nr, uint8_t address)
uint8_t PCA9635::getSubCallAddress(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return 0;
if ((nr == 0) || (nr > 3))
{
// _error = ?? TODO
return 0;
}
uint8_t address = readReg(PCA9635_SUBADR(nr));
return address;
}
@ -245,9 +280,13 @@ uint8_t PCA9635::getSubCallAddress(uint8_t nr)
bool PCA9635::enableAllCall()
{
uint8_t prev = getMode1();
uint8_t reg = prev | PCA9635_MODE1_ALLCALL;
uint8_t mask = prev | PCA9635_MODE1_ALLCALL;
// only update if changed.
if (reg != prev) setMode1(reg);
if (mask != prev)
{
setMode1(mask);
// error handling TODO
}
return true;
}
@ -255,17 +294,21 @@ bool PCA9635::enableAllCall()
bool PCA9635::disableAllCall()
{
uint8_t prev = getMode1();
uint8_t reg = prev & ~PCA9635_MODE1_ALLCALL;
uint8_t mask = prev & ~PCA9635_MODE1_ALLCALL;
// only update if changed.
if (reg != prev) setMode1(reg);
if (mask != prev)
{
setMode1(mask);
// error handling TODO
}
return true;
}
bool PCA9635::isEnabledAllCall()
{
uint8_t reg = getMode1();
return reg & PCA9635_MODE1_ALLCALL;
uint8_t mask = getMode1();
return mask & PCA9635_MODE1_ALLCALL;
}
@ -283,6 +326,46 @@ uint8_t PCA9635::getAllCallAddress()
}
/////////////////////////////////////////////////////
//
// OE - Output Enable control
//
// active LOW see page 5 par 6.2 datasheet
//
bool PCA9635::setOutputEnablePin(uint8_t pin)
{
_OutputEnablePin = pin;
if (_OutputEnablePin != 255)
{
pinMode(_OutputEnablePin, OUTPUT);
digitalWrite(_OutputEnablePin, HIGH);
return true;
}
// must it be set to HIGH now?
return false;
}
bool PCA9635::setOutputEnable(bool on)
{
if (_OutputEnablePin != 255)
{
digitalWrite(_OutputEnablePin, on ? LOW : HIGH);
return true;
}
return false;
}
uint8_t PCA9635::getOutputEnable()
{
if (_OutputEnablePin != 255)
{
return digitalRead(_OutputEnablePin);
}
return HIGH;
}
/////////////////////////////////////////////////////
//
@ -294,6 +377,7 @@ uint8_t PCA9635::writeReg(uint8_t reg, uint8_t value)
_wire->write(reg);
_wire->write(value);
_error = _wire->endTransmission();
if (_error == 0) _error = PCA9635_OK;
else _error = PCA9635_ERR_I2C;
return _error;
@ -305,6 +389,7 @@ uint8_t PCA9635::readReg(uint8_t reg)
_wire->beginTransmission(_address);
_wire->write(reg);
_error = _wire->endTransmission();
if (_wire->requestFrom(_address, (uint8_t)1) != 1)
{
_error = PCA9635_ERROR;
@ -316,5 +401,5 @@ uint8_t PCA9635::readReg(uint8_t reg)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -3,7 +3,7 @@
// FILE: PCA9635.h
// AUTHOR: Rob Tillaart
// DATE: 23-apr-2016
// VERSION: 0.4.2
// VERSION: 0.4.3
// PURPOSE: Arduino library for PCA9635 I2C LED driver, 16 channel
// URL: https://github.com/RobTillaart/PCA9635
@ -12,7 +12,7 @@
#include "Wire.h"
#define PCA9635_LIB_VERSION (F("0.4.2"))
#define PCA9635_LIB_VERSION (F("0.4.3"))
#define PCA9635_MODE1 0x00
#define PCA9635_MODE2 0x01
@ -25,8 +25,8 @@
#define PCA9635_GRPFREQ 0x13
// check datasheet for details
#define PCA9635_LEDOUT_BASE 0x14 // 0x14..0x17
#define PCA9635_LEDOFF 0x00 // default @ startup
#define PCA9635_LEDOUT_BASE 0x14 // 0x14..0x17
#define PCA9635_LEDOFF 0x00 // default @ startup
#define PCA9635_LEDON 0x01
#define PCA9635_LEDPWM 0x02
#define PCA9635_LEDGRPPWM 0x03
@ -41,26 +41,26 @@
#define PCA9635_ERR_I2C 0xFA
// Configuration bits MODE1 register
#define PCA9635_MODE1_AUTOINCR2 0x80 // ReadOnly, 0 = disable 1 = enable
#define PCA9635_MODE1_AUTOINCR1 0x40 // ReadOnly, bit1
#define PCA9635_MODE1_AUTOINCR0 0x20 // ReadOnly, bit0
#define PCA9635_MODE1_SLEEP 0x10 // 0 = normal 1 = sleep
#define PCA9635_MODE1_SUB1 0x08 // 0 = disable 1 = enable
#define PCA9635_MODE1_SUB2 0x04 // 0 = disable 1 = enable
#define PCA9635_MODE1_SUB3 0x02 // 0 = disable 1 = enable
#define PCA9635_MODE1_ALLCALL 0x01 // 0 = disable 1 = enable
// Configuration bits MODE1 register
#define PCA9635_MODE1_AUTOINCR2 0x80 // ReadOnly, 0 = disable 1 = enable
#define PCA9635_MODE1_AUTOINCR1 0x40 // ReadOnly, bit1
#define PCA9635_MODE1_AUTOINCR0 0x20 // ReadOnly, bit0
#define PCA9635_MODE1_SLEEP 0x10 // 0 = normal 1 = sleep
#define PCA9635_MODE1_SUB1 0x08 // 0 = disable 1 = enable
#define PCA9635_MODE1_SUB2 0x04 // 0 = disable 1 = enable
#define PCA9635_MODE1_SUB3 0x02 // 0 = disable 1 = enable
#define PCA9635_MODE1_ALLCALL 0x01 // 0 = disable 1 = enable
#define PCA9635_MODE1_NONE 0x00
// Configuration bits MODE2 register
#define PCA9635_MODE2_BLINK 0x20 // 0 = dim 1 = blink
#define PCA9635_MODE2_INVERT 0x10 // 0 = normal 1 = inverted
#define PCA9635_MODE2_ACK 0x08 // 0 = on STOP 1 = on ACK
#define PCA9635_MODE2_TOTEMPOLE 0x04 // 0 = open drain 1 = totem-pole
// Configuration bits MODE2 register
#define PCA9635_MODE2_BLINK 0x20 // 0 = dim 1 = blink
#define PCA9635_MODE2_INVERT 0x10 // 0 = normal 1 = inverted
#define PCA9635_MODE2_ACK 0x08 // 0 = on STOP 1 = on ACK
#define PCA9635_MODE2_TOTEMPOLE 0x04 // 0 = open drain 1 = totem-pole
#define PCA9635_MODE2_NONE 0x00
// NOT IMPLEMENTED YET
#define PCA9635_SUBADR(x) (0x17+(x)) // x = 1..3
// NOT IMPLEMENTED YET
#define PCA9635_SUBADR(x) (0x17+(x)) // x = 1..3
#define PCA9635_ALLCALLADR 0x1B
@ -76,23 +76,19 @@ public:
#endif
bool begin(uint8_t mode1_mask = PCA9635_MODE1_ALLCALL,
uint8_t mode2_mask = PCA9635_MODE2_NONE);
void configure(uint8_t mode1_mask, uint8_t mode2_mask);
bool isConnected();
uint8_t channelCount() { return _channelCount; };
/////////////////////////////////////////////////////
//
// CONFIGURATION
//
uint8_t configure(uint8_t mode1_mask, uint8_t mode2_mask);
uint8_t channelCount();
uint8_t setLedDriverMode(uint8_t channel, uint8_t mode);
uint8_t getLedDriverMode(uint8_t channel);
// single PWM setting
uint8_t write1(uint8_t channel, uint8_t value);
// RGB setting, write three consecutive PWM registers
uint8_t write3(uint8_t channel, uint8_t R, uint8_t G, uint8_t B);
// generic worker, write N consecutive PWM registers
uint8_t writeN(uint8_t channel, uint8_t* arr, uint8_t count);
// reg = 1, 2 check datasheet for values
uint8_t writeMode(uint8_t reg, uint8_t value);
uint8_t readMode(uint8_t reg);
@ -102,7 +98,6 @@ public:
uint8_t getMode1() { return readMode(PCA9635_MODE1); };
uint8_t getMode2() { return readMode(PCA9635_MODE2); };
// TODO PWM also in %% ?
void setGroupPWM(uint8_t value) { writeReg(PCA9635_GRPPWM, value); };
uint8_t getGroupPWM() { return readReg(PCA9635_GRPPWM); };
@ -111,11 +106,32 @@ public:
void setGroupFREQ(uint8_t value) { writeReg(PCA9635_GRPFREQ, value); };
uint8_t getGroupFREQ() { return readReg(PCA9635_GRPFREQ); };
int lastError();
/////////////////////////////////////////////////////
//
// SUB CALL - ALL CALL (since 0.2.0)
// WRITE
//
// single PWM setting
uint8_t write1(uint8_t channel, uint8_t value);
// RGB setting, write three consecutive PWM registers
uint8_t write3(uint8_t channel, uint8_t R, uint8_t G, uint8_t B);
// generic worker, write N consecutive PWM registers
uint8_t writeN(uint8_t channel, uint8_t* arr, uint8_t count);
/////////////////////////////////////////////////////
//
// ERROR
//
// note error flag is reset after read!
int lastError();
/////////////////////////////////////////////////////
//
// SUB CALL - ALL CALL (since 0.2.0)
//
// nr = { 1, 2, 3 }
bool enableSubCall(uint8_t nr);
@ -131,20 +147,29 @@ public:
uint8_t getAllCallAddress();
/////////////////////////////////////////////////////
//
// OE - Output Enable control
//
bool setOutputEnablePin(uint8_t pin);
bool setOutputEnable(bool on);
uint8_t getOutputEnable();
private:
// DIRECT CONTROL
uint8_t writeReg(uint8_t reg, uint8_t value); // returns error status.
// DIRECT CONTROL
uint8_t writeReg(uint8_t reg, uint8_t value); // returns error status.
uint8_t readReg(uint8_t reg);
uint8_t _address;
uint8_t _register;
uint8_t _data;
int _error;
uint8_t _channelCount = 16;
uint8_t _OutputEnablePin;
TwoWire* _wire;
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -15,17 +15,20 @@ Arduino library for PCA9635 I2C 8 bit PWM LED driver, 16 channel.
This library is to control the I2C PCA9635 PWM extender.
The 16 channels are independently configurable in steps of 1/256.
this allows for better than 1% fine tuning of the duty-cycle
This allows for better than 1% fine tuning of the duty-cycle
of the PWM signal.
library is related to the 8 channel PCA9634 class.
library is related to the 8 channel https://github.com/RobTillaart/PCA9634 class.
(these might merge in the future)
## Interface
```cpp
#include "PCA9635.h"
```
### Constructor
#### Constructor
- **PCA9635(uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor with I2C device address,
and optional the Wire interface as parameter.
@ -41,25 +44,25 @@ See PCA9635.h and datasheet for settings possible.
- **uint8_t channelCount()** returns the number of channels = 16.
### LedDriverMode
#### LedDriverMode
Configure LED behaviour.
- **uint8_t setLedDriverMode(uint8_t channel, uint8_t mode)** mode is 0..3 See datasheet for full details.
- **uint8_t getLedDriverMode(uint8_t channel)** returns the current mode of the channel.
| LED mode | Value | Description |
|:-------------------|:-----:|:----------------------------------|
| PCA9635_LEDOFF | 0x00 | led is 100% off, default @startup |
| PCA9635_LEDON | 0x01 | led is 100% on. |
| PCA9635_LEDPWM | 0x02 | set LED in PWM mode, 0..255 |
| PCA9635_LEDGRPPWM | 0x03 | add LED to the GRPPWM* |
| LED mode | Value | Description |
|:--------------------|:-------:|:------------------------------------|
| PCA9635_LEDOFF | 0x00 | led is 100% off, default @startup |
| PCA9635_LEDON | 0x01 | led is 100% on. |
| PCA9635_LEDPWM | 0x02 | set LED in PWM mode, 0..255 |
| PCA9635_LEDGRPPWM | 0x03 | add LED to the GRPPWM* |
\* all LEDs in the group GRPPWM can be set to the same PWM value in one set.
This is ideal to trigger e.g. multiple LEDs (servo's) at same time.
### Read and write
#### Read and write
Read and write individual values to LED channels.
Requires LEDs' DriverMode of the specific channels to be in PWM mode.
@ -74,7 +77,7 @@ May return **PCA9635_ERR_WRITE** if array has too many elements
(including channel as offset).
### Mode registers
#### Mode registers
Used to configure the PCA963x general behaviour.
@ -92,21 +95,21 @@ useful to add or remove a single flag (bit masking).
(added 0.3.4)
| Name | Value | Description |
|:------------------------|:-----:|:-----------------------------------|
| PCA9635_MODE1_AUTOINCR2 | 0x80 | Read Only, 0 = disable 1 = enable |
| PCA9635_MODE1_AUTOINCR1 | 0x40 | Read Only, bit1 |
| PCA9635_MODE1_AUTOINCR0 | 0x20 | Read Only, bit0 |
| PCA9635_MODE1_SLEEP | 0x10 | 0 = normal 1 = sleep |
| PCA9635_MODE1_SUB1 | 0x08 | 0 = disable 1 = enable |
| PCA9635_MODE1_SUB2 | 0x04 | 0 = disable 1 = enable |
| PCA9635_MODE1_SUB3 | 0x02 | 0 = disable 1 = enable |
| PCA9635_MODE1_ALLCALL | 0x01 | 0 = disable 1 = enable |
| | | |
| PCA9635_MODE2_BLINK | 0x20 | 0 = dim 1 = blink |
| PCA9635_MODE2_INVERT | 0x10 | 0 = normal 1 = inverted |
| PCA9635_MODE2_STOP | 0x08 | 0 = on STOP 1 = on ACK |
| PCA9635_MODE2_TOTEMPOLE | 0x04 | 0 = open drain 1 = totem-pole |
| Name | Value | Description |
|:--------------------------|:-------:|:-------------------------------------|
| PCA9635_MODE1_AUTOINCR2 | 0x80 | Read Only, 0 = disable 1 = enable |
| PCA9635_MODE1_AUTOINCR1 | 0x40 | Read Only, bit1 |
| PCA9635_MODE1_AUTOINCR0 | 0x20 | Read Only, bit0 |
| PCA9635_MODE1_SLEEP | 0x10 | 0 = normal 1 = sleep |
| PCA9635_MODE1_SUB1 | 0x08 | 0 = disable 1 = enable |
| PCA9635_MODE1_SUB2 | 0x04 | 0 = disable 1 = enable |
| PCA9635_MODE1_SUB3 | 0x02 | 0 = disable 1 = enable |
| PCA9635_MODE1_ALLCALL | 0x01 | 0 = disable 1 = enable |
| ---- | | |
| PCA9635_MODE2_BLINK | 0x20 | 0 = dim 1 = blink |
| PCA9635_MODE2_INVERT | 0x10 | 0 = normal 1 = inverted |
| PCA9635_MODE2_STOP | 0x08 | 0 = on STOP 1 = on ACK |
| PCA9635_MODE2_TOTEMPOLE | 0x04 | 0 = open drain 1 = totem-pole |
These constants makes it easier to set modes without using a non descriptive
bit mask. The constants can be merged by OR-ing them together, see snippet:
@ -125,7 +128,7 @@ ledArray.setMode2(PCA9635_MODE2_BLINK | PCA9635_MODE2_INVERT | PCA9635_MODE2_TOT
```
### Group PWM and frequency
#### Group PWM and frequency
Check datasheet for the details.
@ -137,22 +140,22 @@ So 0x00 results in 41 ms blinking period (on AND off) and 0xFF in approx. 10.5 s
- **uint8_t getGroupFREQ()** returns the set frequency of the PWM group.
### Miscellaneous
#### Miscellaneous
- **int lastError()** returns **PCA9635_OK** if all is OK, and other error codes otherwise.
| Error code | Value | Description |
|:------------------|:-----:|:---------------------|
| PCA9635_OK | 0x00 | Everything went well
| PCA9635_ERROR | 0xFF | Generic error
| PCA9635_ERR_WRITE | 0xFE | Tries to write more elements than PWM channels
| PCA9635_ERR_CHAN | 0xFD | Channel out of range
| PCA9635_ERR_MODE | 0xFC | Invalid mode
| PCA9635_ERR_REG | 0xFB | Invalid register
| PCA9635_ERR_I2C | 0xFA | I2C communication error
| Error code | Value | Description |
|:--------------------|:-------:|:----------------------|
| PCA9635_OK | 0x00 | Everything went well
| PCA9635_ERROR | 0xFF | Generic error
| PCA9635_ERR_WRITE | 0xFE | Tries to write more elements than PWM channels
| PCA9635_ERR_CHAN | 0xFD | Channel out of range
| PCA9635_ERR_MODE | 0xFC | Invalid mode
| PCA9635_ERR_REG | 0xFB | Invalid register
| PCA9635_ERR_I2C | 0xFA | I2C communication error
### SUB CALL and ALL CALL
## SUB CALL and ALL CALL
Please read the datasheet to understand the working of **SUB CALL** and **ALL CALL**.
@ -192,24 +195,56 @@ The functions to enable all/sub-addresses are straightforward:
- **uint8_t getAllCallAddress()**
## Operation
#### OutputEnable
See examples
Since 0.4.3 (experimental) support to control the OE (Output Enable) pin of the PCA9635.
This OE pin can control all LEDs simultaneously. It also allows to
control multiple PCA9635.
Think of simultaneous switching ON/OFF of get dimming with a high frequency PWM.
See datasheet for the details
- **bool setOutputEnablePin(uint8_t pin = 255)** sets the IO pin to connect to the OE pin of the PCA9635.
A value of 255 indicates no pin set/selected.
Sets the OE pin to LOW.
Returns true on success.
- **bool setOutputEnable(uint8_t value)** Sets the OE pin HIGH or LOW.
All non zero values are HIGH.
Returns true on success.
- **uint8_t getOutputEnable()** get the current value of the OE pin.
If pin is not set/selected it will return LOW.
Note: the OE is LOW active. The user has to set the power on value
by means of a PULL UP / DOWN resistor.
## Future
#### must
#### Must
- improve documentation
#### should
#### Should
- move code from .h to .cpp
- unit tests
- SUB CALL if possible?
- ALL CALL if possible?
- add examples
- improve error handling (0.5.0)
- return values etc.
- documentation.
#### Could
#### could
- sync with PCA9634 developments
- merge with PCA9634 and a PCA963X base class if possible
- restructure function groups
- in .cpp to match .h
- readme.md
#### Wont

View File

@ -0,0 +1,45 @@
//
// FILE: PCA9635_OE_control.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test PCA9635 library
#include "Arduino.h"
#include "Wire.h"
#include "PCA9635.h"
PCA9635 ledArray(0x20);
void setup()
{
Serial.begin(115200);
Serial.print("PCA9635 LIB version: ");
Serial.println(PCA9635_LIB_VERSION);
Serial.println();
ledArray.begin();
// just one channel
ledArray.write1(1, 100);
ledArray.setOutputEnablePin(12);
ledArray.setOutputEnable(true);
delay(1000);
ledArray.setOutputEnable(false);
delay(1000);
ledArray.setOutputEnable(true);
// TODO elaborate
Serial.println("done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -38,9 +38,15 @@ enableAllCall KEYWORD2
disableAllCall KEYWORD2
isEnabledAllCall KEYWORD2
setOutputEnablePin KEYWORD2
setOutputEnable KEYWORD2
getOutputEnable KEYWORD2
#
# Constants ( LITERAL1)
#
PCA9635_LIB_VERSION LITERAL1
PCA9635_OK LITERAL1
PCA9635_ERROR LITERAL1
PCA9635_ERR_WRITE LITERAL1

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/PCA9635.git"
},
"version": "0.4.2",
"version": "0.4.3",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=PCA9635
version=0.4.2
version=0.4.3
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for PCA9635 I2C LED driver 16 channel

View File

@ -89,6 +89,33 @@ unittest(test_LedDriverMode)
}
unittest(test_OutputEnable)
{
PCA9635 ledArray(0x20);
assertTrue(ledArray.begin());
assertEqual(HIGH, ledArray.getOutputEnable());
assertTrue(ledArray.setOutputEnablePin(12));
assertEqual(HIGH, ledArray.getOutputEnable());
assertTrue(ledArray.setOutputEnable(true));
assertEqual(LOW, ledArray.getOutputEnable());
assertTrue(ledArray.setOutputEnable(false));
assertEqual(HIGH, ledArray.getOutputEnable());
assertTrue(ledArray.setOutputEnable(true));
assertEqual(LOW, ledArray.getOutputEnable());
assertFalse(ledArray.setOutputEnablePin(255));
assertEqual(HIGH, ledArray.getOutputEnable());
}
unittest_main()
// --------
// -- END OF FILE --