mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.0 PCA9634
This commit is contained in:
parent
ff21e55088
commit
2e0ef7f994
@ -2,7 +2,7 @@
|
||||
// FILE: PCA9634.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 03-01-2022
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.2.0
|
||||
// PURPOSE: Arduino library for PCA9634 I2C LED driver
|
||||
// URL: https://github.com/RobTillaart/PCA9634
|
||||
//
|
||||
@ -10,6 +10,14 @@
|
||||
// 0.1.0 2022-01-03 initial version -- based upon 0.3.2 PCA9635
|
||||
// 0.1.1 2022-01-04 minor fixes
|
||||
// 0.1.2 2022-04-13 issue #7 add constants and functions for mode registers.
|
||||
//
|
||||
// 0.2.0 2022-05-29 breaking changes
|
||||
// rename reset() to configure()
|
||||
// add mode1 and mode2 parameter to configure.
|
||||
// add SUB CALL and ALL CALL functions.
|
||||
// update documentation.
|
||||
// renamed PCA9634_MODE2_STOP to PCA9634_MODE2_ACK
|
||||
|
||||
|
||||
|
||||
#include "PCA9634.h"
|
||||
@ -38,7 +46,7 @@ bool PCA9634::begin(uint8_t sda, uint8_t scl)
|
||||
_wire->begin();
|
||||
}
|
||||
if (! isConnected()) return false;
|
||||
reset();
|
||||
configure();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -48,7 +56,7 @@ bool PCA9634::begin()
|
||||
{
|
||||
_wire->begin();
|
||||
if (! isConnected()) return false;
|
||||
reset();
|
||||
configure();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -61,13 +69,13 @@ bool PCA9634::isConnected()
|
||||
}
|
||||
|
||||
|
||||
void PCA9634::reset()
|
||||
void PCA9634::configure(uint8_t mode1_mask, uint8_t mode2_mask)
|
||||
{
|
||||
_data = 0;
|
||||
_error = 0;
|
||||
|
||||
uint8_t mode1_mask = PCA9634_MODE1_AUTOINCR2 | PCA9634_MODE1_ALLCALL;
|
||||
writeReg(PCA9634_MODE1, mode1_mask); // AUTOINCR | NOSLEEP | ALLADRR 0x81
|
||||
setMode1(mode1_mask);
|
||||
setMode2(mode2_mask);
|
||||
}
|
||||
|
||||
|
||||
@ -179,15 +187,116 @@ uint8_t PCA9634::getLedDriverMode(uint8_t channel)
|
||||
}
|
||||
|
||||
|
||||
// note error flag is reset after read!
|
||||
// note error flag is set to PCA9634_OK after read!
|
||||
int PCA9634::lastError()
|
||||
{
|
||||
int e = _error;
|
||||
_error = 0;
|
||||
_error = PCA9634_OK;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// SUB CALL - ALL CALL
|
||||
//
|
||||
bool PCA9634::enableSubCall(uint8_t nr)
|
||||
{
|
||||
if ((nr == 0) || (nr > 3)) return false;
|
||||
uint8_t prev = getMode1();
|
||||
uint8_t reg = prev;
|
||||
if (nr == 1) reg |= PCA9634_MODE1_SUB1;
|
||||
else if (nr == 2) reg |= PCA9634_MODE1_SUB2;
|
||||
else reg |= PCA9634_MODE1_SUB3;
|
||||
// only update if changed.
|
||||
if (reg != prev) setMode1(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::disableSubCall(uint8_t nr)
|
||||
{
|
||||
if ((nr == 0) || (nr > 3)) return false;
|
||||
uint8_t prev = getMode1();
|
||||
uint8_t reg = prev;
|
||||
if (nr == 1) reg &= ~PCA9634_MODE1_SUB1;
|
||||
else if (nr == 2) reg &= ~PCA9634_MODE1_SUB2;
|
||||
else reg &= ~PCA9634_MODE1_SUB3;
|
||||
// only update if changed.
|
||||
if (reg != prev) setMode1(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::isEnabledSubCall(uint8_t nr)
|
||||
{
|
||||
if ((nr == 0) || (nr > 3)) return false;
|
||||
uint8_t reg = getMode1();
|
||||
if (nr == 1) return (reg & PCA9634_MODE1_SUB1) > 0;
|
||||
if (nr == 2) return (reg & PCA9634_MODE1_SUB2) > 0;
|
||||
return (reg & PCA9634_MODE1_SUB3) > 0;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::setSubCallAddress(uint8_t nr, uint8_t address)
|
||||
{
|
||||
if ((nr == 0) || (nr > 3)) return false;
|
||||
writeReg(PCA9634_SUBADR(nr), address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t PCA9634::getSubCallAddress(uint8_t nr)
|
||||
{
|
||||
if ((nr == 0) || (nr > 3)) return 0;
|
||||
uint8_t address = readReg(PCA9634_SUBADR(nr));
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::enableAllCall()
|
||||
{
|
||||
uint8_t prev = getMode1();
|
||||
uint8_t reg = prev | PCA9634_MODE1_ALLCALL;
|
||||
// only update if changed.
|
||||
if (reg != prev) setMode1(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::disableAllCall()
|
||||
{
|
||||
uint8_t prev = getMode1();
|
||||
uint8_t reg = prev & ~PCA9634_MODE1_ALLCALL;
|
||||
// only update if changed.
|
||||
if (reg != prev) setMode1(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::isEnabledAllCall()
|
||||
{
|
||||
uint8_t reg = getMode1();
|
||||
return reg & PCA9634_MODE1_ALLCALL;
|
||||
}
|
||||
|
||||
|
||||
bool PCA9634::setAllCallAddress(uint8_t address)
|
||||
{
|
||||
writeReg(PCA9634_ALLCALLADR, address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t PCA9634::getAllCallAddress()
|
||||
{
|
||||
uint8_t address = readReg(PCA9634_ALLCALLADR);
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
|
@ -3,7 +3,7 @@
|
||||
// FILE: PCA9634.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 03-01-2022
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.2.0
|
||||
// PURPOSE: Arduino library for PCA9634 I2C LED driver, 8 channel
|
||||
// URL: https://github.com/RobTillaart/PCA9634
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define PCA9634_LIB_VERSION (F("0.1.2"))
|
||||
#define PCA9634_LIB_VERSION (F("0.2.0"))
|
||||
|
||||
#define PCA9634_MODE1 0x00
|
||||
#define PCA9634_MODE2 0x01
|
||||
@ -42,24 +42,25 @@
|
||||
|
||||
|
||||
// Configuration bits MODE1 register
|
||||
#define PCA9634_MODE1_AUTOINCR2 0x80 // RO, 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_AUTOINCR1 0x40 // RO, bit1
|
||||
#define PCA9634_MODE1_AUTOINCR0 0x20 // RO bit0
|
||||
#define PCA9634_MODE1_AUTOINCR2 0x80 // ReadOnly, 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_AUTOINCR1 0x40 // ReadOnly, bit1
|
||||
#define PCA9634_MODE1_AUTOINCR0 0x20 // ReadOnly, bit0
|
||||
#define PCA9634_MODE1_SLEEP 0x10 // 0 = normal 1 = sleep
|
||||
#define PCA9634_MODE1_SUB1 0x08 // 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_SUB2 0x04 // 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_SUB3 0x02 // 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_ALLCALL 0x01 // 0 = disable 1 = enable
|
||||
#define PCA9634_MODE1_NONE 0x00
|
||||
|
||||
// Configuration bits MODE2 register
|
||||
#define PCA9634_MODE2_BLINK 0x20 // 0 = dim 1 = blink
|
||||
#define PCA9634_MODE2_INVERT 0x10 // 0 = normal 1 = inverted
|
||||
#define PCA9634_MODE2_STOP 0x08 // 0 = on STOP 1 = on ACK
|
||||
#define PCA9634_MODE2_ACK 0x08 // 0 = on STOP 1 = on ACK
|
||||
#define PCA9634_MODE2_TOTEMPOLE 0x04 // 0 = open drain 1 = totem-pole
|
||||
#define PCA9634_MODE2_NONE 0x00
|
||||
|
||||
|
||||
// NOT IMPLEMENTED YET
|
||||
#define PCA9634_SUBADR(x) (0x0E +(x)) // x = 1..3
|
||||
// (since 0.2.0)
|
||||
#define PCA9634_SUBADR(x) (0x0D +(x)) // x = 1..3
|
||||
#define PCA9634_ALLCALLADR 0x11
|
||||
|
||||
|
||||
@ -72,7 +73,8 @@ public:
|
||||
bool begin(uint8_t sda, uint8_t scl);
|
||||
#endif
|
||||
bool begin();
|
||||
void reset();
|
||||
void configure(uint8_t mode1_mask = PCA9634_MODE1_ALLCALL,
|
||||
uint8_t mode2_mask = PCA9634_MODE2_NONE);
|
||||
bool isConnected();
|
||||
|
||||
uint8_t channelCount() { return _channelCount; };
|
||||
@ -100,15 +102,33 @@ public:
|
||||
|
||||
|
||||
// TODO PWM also in %% ?
|
||||
void setGroupPWM(uint8_t value) { writeReg(PCA9634_GRPPWM, value); }
|
||||
uint8_t getGroupPWM() { return readReg(PCA9634_GRPPWM); }
|
||||
void setGroupPWM(uint8_t value) { writeReg(PCA9634_GRPPWM, value); };
|
||||
uint8_t getGroupPWM() { return readReg(PCA9634_GRPPWM); };
|
||||
|
||||
// TODO set time in milliseconds and round to nearest value?
|
||||
void setGroupFREQ(uint8_t value) { writeReg(PCA9634_GRPFREQ, value); }
|
||||
uint8_t getGroupFREQ() { return readReg(PCA9634_GRPFREQ); }
|
||||
void setGroupFREQ(uint8_t value) { writeReg(PCA9634_GRPFREQ, value); };
|
||||
uint8_t getGroupFREQ() { return readReg(PCA9634_GRPFREQ); };
|
||||
|
||||
int lastError();
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// SUB CALL - ALL CALL (since 0.2.0)
|
||||
//
|
||||
// nr = { 1, 2, 3 }
|
||||
bool enableSubCall(uint8_t nr);
|
||||
bool disableSubCall(uint8_t nr);
|
||||
bool isEnabledSubCall(uint8_t nr);
|
||||
bool setSubCallAddress(uint8_t nr, uint8_t address);
|
||||
uint8_t getSubCallAddress(uint8_t nr);
|
||||
|
||||
bool enableAllCall();
|
||||
bool disableAllCall();
|
||||
bool isEnabledAllCall();
|
||||
bool setAllCallAddress(uint8_t address);
|
||||
uint8_t getAllCallAddress();
|
||||
|
||||
|
||||
private:
|
||||
// DIRECT CONTROL
|
||||
uint8_t writeReg(uint8_t reg, uint8_t value); // returns error status.
|
||||
|
@ -30,15 +30,19 @@ library is a 8 channel derived variation of the PCA9635 class.
|
||||
- **PCA9634(uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor with I2C device address,
|
||||
and optional the Wire interface as parameter.
|
||||
- **bool begin()** initializes the library after startup. Mandatory.
|
||||
- **bool begin(uint8_t sda, uint8_t scl)** idem, ESP32 ESP8266 only. Library does not support
|
||||
multiple Wire instances (yet).
|
||||
- **void reset()** resets the library to start up conditions.
|
||||
- **bool begin(uint8_t sda, uint8_t scl)** idem, ESP32 ESP8266 only.
|
||||
- **void configure(uint8_t mode1_mask = PCA9634_MODE1_ALLCALL, uint8_t mode2_mask = PCA9634_MODE2_NONE)**
|
||||
configures the library, optionally setting the MODE1 and MODE2 configuration registers.
|
||||
See PCA9634.h and datasheet for settings possible.
|
||||
**configure()** is typically used at startup.
|
||||
- **bool isConnected()** checks if address is available on I2C bus.
|
||||
- **uint8_t channelCount()** returns the number of channels = 8.
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
@ -55,18 +59,25 @@ This is ideal to trigger e.g. multiple LEDs (servo's) at same time.
|
||||
|
||||
### Read and write
|
||||
|
||||
Read and write individual values to LED channels.
|
||||
Requires LEDs' DriverMode of the specific channels to be in PWM mode.
|
||||
|
||||
- **uint8_t write1(uint8_t channel, uint8_t value)** writes a single 8 bit PWM value.
|
||||
- **uint8_t write3(uint8_t channel, uint8_t R, uint8_t G, uint8_t B)** writes three consecutive PWM registers.
|
||||
- **uint8_t write3(uint8_t channel, uint8_t R, uint8_t G, uint8_t B)**
|
||||
writes three consecutive PWM registers.
|
||||
typical use is to write R, G, B values for a full colour LED.
|
||||
- **uint8_t writeN(uint8_t channel, uint8_t \* array, uint8_t count)** write count consecutive PWM registers.
|
||||
- **uint8_t writeN(uint8_t channel, uint8_t \* array, uint8_t count)**
|
||||
write count consecutive PWM registers.
|
||||
May return **PCA9634_ERR_WRITE** if array has too many elements
|
||||
(including channel as offset).
|
||||
|
||||
|
||||
### Mode registers
|
||||
|
||||
Used to configure the PCA963x general behaviour.
|
||||
|
||||
- **uint8_t writeMode(uint8_t reg, uint8_t value)** configuration of one of the two configuration registers.
|
||||
check datasheet for details.
|
||||
Check datasheet for details.
|
||||
- **uint8_t readMode(uint8_t reg)** reads back the configured mode,
|
||||
useful to add or remove a single flag (bit masking).
|
||||
- **uint8_t setMode1(uint8_t value)** convenience wrapper.
|
||||
@ -80,10 +91,10 @@ useful to add or remove a single flag (bit masking).
|
||||
(added 0.1.2)
|
||||
|
||||
| Name | Value | Description |
|
||||
|:------------------------|:-----:|:--------------------------------|
|
||||
| PCA9634_MODE1_AUTOINCR2 | 0x80 | RO, 0 = disable 1 = enable |
|
||||
| PCA9634_MODE1_AUTOINCR1 | 0x40 | RO, bit1 |
|
||||
| PCA9634_MODE1_AUTOINCR0 | 0x20 | RO bit0 |
|
||||
|:------------------------|:-----:|:-----------------------------------|
|
||||
| PCA9634_MODE1_AUTOINCR2 | 0x80 | Read Only, 0 = disable 1 = enable |
|
||||
| PCA9634_MODE1_AUTOINCR1 | 0x40 | Read Only, bit1 |
|
||||
| PCA9634_MODE1_AUTOINCR0 | 0x20 | Read Only, bit0 |
|
||||
| PCA9634_MODE1_SLEEP | 0x10 | 0 = normal 1 = sleep |
|
||||
| PCA9634_MODE1_SUB1 | 0x08 | 0 = disable 1 = enable |
|
||||
| PCA9634_MODE1_SUB2 | 0x04 | 0 = disable 1 = enable |
|
||||
@ -97,7 +108,7 @@ useful to add or remove a single flag (bit masking).
|
||||
|
||||
|
||||
These constants makes it easier to set modes without using a non descriptive
|
||||
bitmask. The constants can be merged by OR-ing them together, see snippet:
|
||||
bit mask. The constants can be merged by OR-ing them together, see snippet:
|
||||
|
||||
```cpp
|
||||
ledArray.writeMode(PCA9634_MODE2, 0b00110100);
|
||||
@ -116,10 +127,14 @@ ledArray.setMode2(PCA9634_MODE2_BLINK | PCA9634_MODE2_INVERT | PCA9634_MODE2_TOT
|
||||
|
||||
### Group PWM and frequency
|
||||
|
||||
Check datasheet for the details.
|
||||
|
||||
- **void setGroupPWM(uint8_t value)** sets all channels that are part of the PWM group to value.
|
||||
- **uint8_t getGroupPWM()** get the current PWM setting of the group.
|
||||
- **void setGroupFREQ(value)** see datasheet for details.
|
||||
- **uint8_t getGroupFREQ()** returns the freq of the PWM group.
|
||||
- **void setGroupFREQ(uint8_t value)** is used for blinking the group of configured LED.
|
||||
Value goes from 0 to 255 with each step representing an increase of approx. 41 ms.
|
||||
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
|
||||
@ -137,6 +152,44 @@ ledArray.setMode2(PCA9634_MODE2_BLINK | PCA9634_MODE2_INVERT | PCA9634_MODE2_TOT
|
||||
| PCA9634_ERR_I2C | 0xFA | I2C communication error
|
||||
|
||||
|
||||
### SUB CALL and ALL CALL
|
||||
|
||||
Please read the datasheet to understand the working of **SUB CALL** and **ALL CALL**.
|
||||
|
||||
Since version 0.2.0 there is (experimental) support for the **SUB CALL** and **ALL CALL** functions.
|
||||
It needs more testing and if there are issues, please report.
|
||||
|
||||
AllCall is automatically activated for each device on startup.
|
||||
|
||||
#### Description
|
||||
|
||||
**SUB CALL** allows one to make groups of PCA9634 devices and control them on group level.
|
||||
The number of groups one can make depends on free I2C addresses on one I2C bus.
|
||||
Using multiple I2C buses or multiplexers will even increase the possible number.
|
||||
Every PCA9634 device can be member of up to three of these groups.
|
||||
To become member one needs to set the **setSubCallAddress(nr, address)** and enable
|
||||
it with **enableSubCall(nr)**.
|
||||
|
||||
In the same way one can become member of an **ALL CALL** group.
|
||||
Typically there is only one such group but one can configure more of them by applying different addresses.
|
||||
|
||||
#### Interface
|
||||
|
||||
The functions to enable all/sub-addresses are straightforward:
|
||||
|
||||
- **bool enableSubCall(uint8_t nr)** nr = 1,2,3
|
||||
- **bool disableSubCall(uint8_t nr)** nr = 1,2,3
|
||||
- **bool isEnabledSubCall(uint8_t nr)** nr = 1,2,3
|
||||
- **bool setSubCallAddress(uint8_t nr, uint8_t address)**
|
||||
- **uint8_t getSubCallAddress(uint8_t nr)**
|
||||
|
||||
- **bool enableAllCall()**
|
||||
- **bool disableAllCall()**
|
||||
- **bool isEnabledAllCall()**
|
||||
- **bool setAllCallAddress(uint8_t address)**
|
||||
- **uint8_t getAllCallAddress()**
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
@ -146,7 +199,9 @@ See examples
|
||||
|
||||
- improve documentation
|
||||
- unit tests
|
||||
- SUB CALL if possible?
|
||||
- ALL CALL if possible?
|
||||
- add examples
|
||||
- follow PCA9635 developments
|
||||
- sync with PCA9635 developments
|
||||
- merge with PCA9635 and a PCA963X base class if possible
|
||||
|
||||
|
@ -7,7 +7,7 @@ PCA9634 KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
begin KEYWORD2
|
||||
reset KEYWORD2
|
||||
configure KEYWORD2
|
||||
|
||||
isConnected KEYWORD2
|
||||
setLedDriverMode KEYWORD2
|
||||
@ -31,6 +31,13 @@ getGroupFREQ KEYWORD2
|
||||
|
||||
lastError KEYWORD2
|
||||
|
||||
enableSubCall KEYWORD2
|
||||
disableSubCall KEYWORD2
|
||||
isEnabledSubCall KEYWORD2
|
||||
enableAllCall KEYWORD2
|
||||
disableAllCall KEYWORD2
|
||||
isEnabledAllCall KEYWORD2
|
||||
|
||||
|
||||
# Constants ( LITERAL1)
|
||||
PCA9634_LIB_VERSION LITERAL1
|
||||
@ -50,8 +57,11 @@ PCA9634_MODE1_SUB1 LITERAL1
|
||||
PCA9634_MODE1_SUB2 LITERAL1
|
||||
PCA9634_MODE1_SUB3 LITERAL1
|
||||
PCA9634_MODE1_ALLCALL LITERAL1
|
||||
PCA9634_MODE1_NONE LITERAL1
|
||||
|
||||
PCA9634_MODE2_BLINK LITERAL1
|
||||
PCA9634_MODE2_INVERT LITERAL1
|
||||
PCA9634_MODE2_STOP LITERAL1
|
||||
PCA9634_MODE2_TOTEMPOLE LITERAL1
|
||||
PCA9634_MODE2_NONE LITERAL1
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/PCA9634.git"
|
||||
},
|
||||
"version": "0.1.2",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=PCA9634
|
||||
version=0.1.2
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for PCA9634 I2C LED driver 8 channel
|
||||
|
Loading…
Reference in New Issue
Block a user