0.4.0 PCA9685_RT

This commit is contained in:
rob tillaart 2022-06-10 12:52:02 +02:00
parent dc45c57956
commit f26f864731
7 changed files with 401 additions and 112 deletions

View File

@ -2,66 +2,37 @@
// FILE: PCA9685.cpp
// AUTHOR: Rob Tillaart
// DATE: 24-apr-2016
// VERSION: 0.3.4
// VERSION: 0.4.0
// PURPOSE: Arduino library for I2C PCA9685 16 channel PWM
// URL: https://github.com/RobTillaart/PCA9685_RT
//
// HISTORY:
// 0.1.0 2016-04-24 initial BETA version
// 0.1.1 2019-01-30 testing && fixing
// 0.2.0 2020-05-25 refactor; ESP32 begin(sda,scl)
// 0.2.1 2020-06-19 fix library.json
// 0.2.2 2020-09-21 fix #1 + add getFrequency()
// 0.2.3 2020-11-21 fix digitalWrite (internal version only)
// 0.3.0 2020-11-22 fix setting frequency
// 0.3.1 2021-01-05 Arduino-CI + unit test
// 0.3.2 2021-01-14 WireN support
// 0.3.3 2021-12-23 update library.json, license, readme, minor edits
// 0.3.4 2022-01-03 add channelCount()
// 0.4.0 2022-06-09 breaking changes (sync with pca9634)
// rename reset() to configure()
// add mode1 and mode2 parameter to configure.
// add SUB CALL and ALL CALL functions.
// update documentation.
// renamed PCA9685_MODE2_STOP to PCA9685_MODE2_ACK
// add mode parameters to begin()
#include "PCA9685.h"
// REGISTERS CONFIGURATION - check datasheet for details
#define PCA9685_MODE1 0x00
#define PCA9685_MODE2 0x01
// MODE1 REGISTERS
#define PCA9685_RESTART 0x80
#define PCA9685_EXTCLK 0x40
#define PCA9685_AUTOINCR 0x20
#define PCA9685_SLEEP 0x10
#define PCA9685_SUB1 0x08
#define PCA9685_SUB2 0x04
#define PCA9685_SUB3 0x02
#define PCA9685_ALLCALL 0x01
// MODE2 REGISTERS (see datasheet)
#define PCA9685_INVERT 0x10
#define PCA9685_OCH 0x08
#define PCA9685_OUTDRV 0x04
#define PCA9685_OUTNE 0x03
// REGISTERS - CHANNELS
#define PCA9685_CHANNEL_0 0x06 // 0x06 + 4*channel is base per channel
// REGISTERS - FREQUENCY
#define PCA9685_PRE_SCALER 0xFE
// REGISTERS - Subaddressing I2C - not implemented
#define PCA9685_SUBADR(x) (0x01+(x)) // x = 1..3
#define PCA9685_ALLCALLADR 0x05
// REGISTERS - ALL_ON ALL_OFF - partly implemented
#define PCA9685_ALL_ON_L 0xFA
#define PCA9685_ALL_ON_H 0xFB
#define PCA9685_ALL_OFF_L 0xFC
#define PCA9685_ALL_OFF_H 0xFD // used for allOFF()
// NOT IMPLEMENTED YET
#define PCA9685_TESTMODE 0xFF // do not be use. see datasheet.
//////////////////////////////////////////////////////////////
//
@ -69,14 +40,15 @@
//
PCA9685::PCA9685(const uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_error = 0;
_address = deviceAddress;
_wire = wire;
_channelCount = 16;
_error = PCA9685_OK;
}
#if defined (ESP8266) || defined(ESP32)
bool PCA9685::begin(uint8_t sda, uint8_t scl)
bool PCA9685::begin(uint8_t sda, uint8_t scl, uint8_t mode1_mask, uint8_t mode2_mask)
{
_wire = &Wire;
if ((sda < 255) && (scl < 255))
@ -86,17 +58,17 @@ bool PCA9685::begin(uint8_t sda, uint8_t scl)
_wire->begin();
}
if (! isConnected()) return false;
reset();
configure(mode1_mask, mode2_mask);
return true;
}
#endif
bool PCA9685::begin()
bool PCA9685::begin(uint8_t mode1_mask, uint8_t mode2_mask)
{
_wire->begin();
if (! isConnected()) return false;
reset();
configure(mode1_mask, mode2_mask);
return true;
}
@ -109,36 +81,37 @@ bool PCA9685::isConnected()
}
void PCA9685::reset()
void PCA9685::configure(uint8_t mode1_mask, uint8_t mode2_mask)
{
_error = PCA9685_OK;
writeMode(PCA9685_MODE1, PCA9685_AUTOINCR | PCA9685_ALLCALL);
writeMode(PCA9685_MODE2, PCA9685_OUTDRV);
setMode1(mode1_mask);
setMode2(mode2_mask);
}
void PCA9685::writeMode(uint8_t reg, uint8_t value)
uint8_t PCA9685::writeMode(uint8_t reg, uint8_t value)
{
_error = PCA9685_OK;
if ((reg != PCA9685_MODE1) && (reg != PCA9685_MODE2))
if ((reg == PCA9685_MODE1) || (reg == PCA9685_MODE2))
{
_error = PCA9685_ERR_MODE;
return;
writeReg(reg, value);
return PCA9685_OK;
}
writeReg(reg, value);
_error = PCA9685_ERR_MODE;
return PCA9685_ERROR;
}
uint8_t PCA9685::readMode(uint8_t reg)
{
_error = PCA9685_OK;
if ((reg != PCA9685_MODE1) && (reg != PCA9685_MODE2))
if ((reg == PCA9685_MODE1) || (reg == PCA9685_MODE2))
{
_error = PCA9685_ERR_MODE;
return 0;
_error = PCA9685_OK;
uint8_t value = readReg(reg);
return value;
}
uint8_t value = readReg(reg);
return value;
_error = PCA9685_ERR_MODE;
return PCA9685_ERROR;
}
@ -152,7 +125,7 @@ void PCA9685::setPWM(uint8_t channel, uint16_t onTime, uint16_t offTime)
return;
}
offTime &= 0x0FFFF; // non-doc feature - to easy set figure 8 P.17
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
uint8_t reg = PCA9685_CHANNEL(channel);
writeReg2(reg, onTime, offTime);
}
@ -173,7 +146,7 @@ void PCA9685::getPWM(uint8_t channel, uint16_t* onTime, uint16_t* offTime)
_error = PCA9685_ERR_CHANNEL;
return;
}
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
uint8_t reg = PCA9685_CHANNEL(channel);
_wire->beginTransmission(_address);
_wire->write(reg);
_error = _wire->endTransmission();
@ -198,18 +171,20 @@ void PCA9685::setFrequency(uint16_t freq, int offset)
if (_freq < PCA9685_MIN_FREQ) _freq = PCA9685_MIN_FREQ;
if (_freq > PCA9685_MAX_FREQ) _freq = PCA9685_MAX_FREQ;
// removed float operation for speed
// faster but equal accurate
// faster and equal accurate
// uint8_t scaler = round(25e6 / (_freq * 4096)) - 1;
uint8_t scaler = 48828 / (_freq * 8) - 1;
uint8_t mode1 = readMode(PCA9685_MODE1);
writeMode(PCA9685_MODE1, mode1 | PCA9685_SLEEP);
writeMode(PCA9685_MODE1, mode1 | PCA9685_MODE1_SLEEP);
scaler += offset;
writeReg(PCA9685_PRE_SCALER, scaler);
writeMode(PCA9685_MODE1, mode1);
}
// returns the actual used frequency.
// therefore it does not use offset
int PCA9685::getFrequency(bool cache)
{
_error = PCA9685_OK;
@ -233,7 +208,7 @@ void PCA9685::digitalWrite(uint8_t channel, uint8_t mode)
_error = PCA9685_ERR_CHANNEL;
return;
}
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
uint8_t reg = PCA9685_CHANNEL(channel);
if (mode != LOW) writeReg2(reg, 0x1000, 0x0000);
else writeReg2(reg, 0x0000, 0x0000);
}
@ -249,11 +224,112 @@ void PCA9685::allOFF()
int PCA9685::lastError()
{
int e = _error;
_error = 0;
_error = PCA9685_OK;
return e;
}
/////////////////////////////////////////////////////
//
// SUB CALL - ALL CALL
//
bool PCA9685::enableSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t prev = getMode1();
uint8_t reg = prev;
if (nr == 1) reg |= PCA9685_MODE1_SUB1;
else if (nr == 2) reg |= PCA9685_MODE1_SUB2;
else reg |= PCA9685_MODE1_SUB3;
// only update if changed.
if (reg != prev) setMode1(reg);
return true;
}
bool PCA9685::disableSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t prev = getMode1();
uint8_t reg = prev;
if (nr == 1) reg &= ~PCA9685_MODE1_SUB1;
else if (nr == 2) reg &= ~PCA9685_MODE1_SUB2;
else reg &= ~PCA9685_MODE1_SUB3;
// only update if changed.
if (reg != prev) setMode1(reg);
return true;
}
bool PCA9685::isEnabledSubCall(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return false;
uint8_t reg = getMode1();
if (nr == 1) return (reg & PCA9685_MODE1_SUB1) > 0;
if (nr == 2) return (reg & PCA9685_MODE1_SUB2) > 0;
return (reg & PCA9685_MODE1_SUB3) > 0;
}
bool PCA9685::setSubCallAddress(uint8_t nr, uint8_t address)
{
if ((nr == 0) || (nr > 3)) return false;
writeReg(PCA9685_SUBADR(nr), address);
return true;
}
uint8_t PCA9685::getSubCallAddress(uint8_t nr)
{
if ((nr == 0) || (nr > 3)) return 0;
uint8_t address = readReg(PCA9685_SUBADR(nr));
return address;
}
bool PCA9685::enableAllCall()
{
uint8_t prev = getMode1();
uint8_t reg = prev | PCA9685_MODE1_ALLCALL;
// only update if changed.
if (reg != prev) setMode1(reg);
return true;
}
bool PCA9685::disableAllCall()
{
uint8_t prev = getMode1();
uint8_t reg = prev & ~PCA9685_MODE1_ALLCALL;
// only update if changed.
if (reg != prev) setMode1(reg);
return true;
}
bool PCA9685::isEnabledAllCall()
{
uint8_t reg = getMode1();
return reg & PCA9685_MODE1_ALLCALL;
}
bool PCA9685::setAllCallAddress(uint8_t address)
{
writeReg(PCA9685_ALLCALLADR, address);
return true;
}
uint8_t PCA9685::getAllCallAddress()
{
uint8_t address = readReg(PCA9685_ALLCALLADR);
return address;
}
//////////////////////////////////////////////////////////////
//
// PRIVATE

View File

@ -3,7 +3,7 @@
// FILE: PCA9685.h
// AUTHOR: Rob Tillaart
// DATE: 24-apr-2016
// VERSION: 0.3.4
// VERSION: 0.4.0
// PURPOSE: Arduino library for I2C PCA9685 16 channel PWM
// URL: https://github.com/RobTillaart/PCA9685_RT
@ -12,18 +12,65 @@
#include "Wire.h"
#define PCA9685_LIB_VERSION (F("0.3.4"))
#define PCA9685_LIB_VERSION (F("0.4.0"))
// ERROR CODES
#define PCA9685_OK 0x00
#define PCA9685_ERROR 0xFF
#define PCA9685_ERR_CHANNEL 0xFE
#define PCA9685_ERR_MODE 0xFD
#define PCA9685_ERR_I2C 0xFC
#define PCA9685_OK 0x00
#define PCA9685_ERROR 0xFF
#define PCA9685_ERR_CHANNEL 0xFE
#define PCA9685_ERR_MODE 0xFD
#define PCA9685_ERR_I2C 0xFC
// get/setFrequency()
#define PCA9685_MIN_FREQ 24
#define PCA9685_MAX_FREQ 1526
#define PCA9685_MIN_FREQ 24
#define PCA9685_MAX_FREQ 1526
// REGISTERS CONFIGURATION - check datasheet for details
#define PCA9685_MODE1 0x00
#define PCA9685_MODE2 0x01
// Configuration bits MODE1 register
#define PCA9685_MODE1_RESTART 0x80 // 0 = disable 1 = enable
#define PCA9685_MODE1_EXTCLK 0x40 // 0 = internal 1 = external (datasheet)
#define PCA9685_MODE1_AUTOINCR 0x20 // 0 = disable 1 = enable
#define PCA9685_MODE1_SLEEP 0x10 // 0 = normal 1 = sleep
#define PCA9685_MODE1_SUB1 0x08 // 0 = disable 1 = enable
#define PCA9685_MODE1_SUB2 0x04 // 0 = disable 1 = enable
#define PCA9685_MODE1_SUB3 0x02 // 0 = disable 1 = enable
#define PCA9685_MODE1_ALLCALL 0x01 // 0 = disable 1 = enable
#define PCA9685_MODE1_NONE 0x00
// Configuration bits MODE2 register
#define PCA9685_MODE2_BLINK 0x20 // 0 = dim 1 = blink
#define PCA9685_MODE2_INVERT 0x10 // 0 = normal 1 = inverted
#define PCA9685_MODE2_ACK 0x08 // 0 = on STOP 1 = on ACK
#define PCA9685_MODE2_TOTEMPOLE 0x04 // 0 = open drain 1 = totem-pole
#define PCA9685_MODE2_OUTNE 0x03 // datasheet
#define PCA9685_MODE2_NONE 0x00
// (since 0.4.0)
#define PCA9685_SUBADR(x) (0x01 + (x)) // x = 1..3
#define PCA9685_ALLCALLADR 0x05
// REGISTERS - CHANNELS
// 0x06 + 4*channel is base per channel
#define PCA9685_CHANNEL_0 0x06
#define PCA9685_CHANNEL(x) (0x06 + ((x) * 4)) // x = 0..15
// REGISTERS - ALL_ON ALL_OFF - partly implemented
#define PCA9685_ALL_ON_L 0xFA
#define PCA9685_ALL_ON_H 0xFB
#define PCA9685_ALL_OFF_L 0xFC
#define PCA9685_ALL_OFF_H 0xFD // used for allOFF()
// REGISTERS - FREQUENCY
#define PCA9685_PRE_SCALER 0xFE
// NOT IMPLEMENTED
// WARNING: DO NOT USE THIS REGISTER (see datasheet)
#define PCA9685_TESTMODE 0xFF // do not be use. see datasheet.
class PCA9685
@ -32,47 +79,73 @@ public:
explicit PCA9685(const uint8_t deviceAddress, TwoWire *wire = &Wire);
#if defined (ESP8266) || defined(ESP32)
bool begin(uint8_t sda, uint8_t scl);
bool begin(uint8_t sda, uint8_t scl,
uint8_t mode1_mask = PCA9685_MODE1_AUTOINCR | PCA9685_MODE1_ALLCALL,
uint8_t mode2_mask = PCA9685_MODE2_TOTEMPOLE);
#endif
bool begin();
void reset();
bool isConnected();
bool begin(uint8_t mode1_mask = PCA9685_MODE1_AUTOINCR | PCA9685_MODE1_ALLCALL,
uint8_t mode2_mask = PCA9685_MODE2_TOTEMPOLE);
void configure(uint8_t mode1_mask, uint8_t mode2_mask);
bool isConnected();
uint8_t channelCount() { return _channelCount; };
// reg = 1, 2 check datasheet for values
void writeMode(uint8_t reg, uint8_t value);
uint8_t readMode(uint8_t reg);
uint8_t writeMode(uint8_t reg, uint8_t value);
uint8_t readMode(uint8_t reg);
// convenience wrappers
uint8_t setMode1(uint8_t value) { return writeMode(PCA9685_MODE1, value); };
uint8_t setMode2(uint8_t value) { return writeMode(PCA9685_MODE2, value); };
uint8_t getMode1() { return readMode(PCA9685_MODE1); };
uint8_t getMode2() { return readMode(PCA9685_MODE2); };
// single PWM setting, channel = 0..15,
// onTime = 0..4095, offTime = 0..4095
// allows shifted PWM's e.g. 2 servo's that do not start at same time.
void setPWM(uint8_t channel, uint16_t onTime, uint16_t offTime);
void getPWM(uint8_t channel, uint16_t* onTime, uint16_t* offTime);
void setPWM(uint8_t channel, uint16_t onTime, uint16_t offTime);
void getPWM(uint8_t channel, uint16_t* onTime, uint16_t* offTime);
// single PWM setting, channel = 0..15, offTime = 0..4095 (onTime = 0)
void setPWM(uint8_t channel, uint16_t offTime);
void setPWM(uint8_t channel, uint16_t offTime);
// set update frequency for all channels
// freq = 24 - 1526 Hz
// note: as the frequency is converted to an 8 bit prescaler
// note: as the frequency is converted to an 8 bit pre-scaler
// the frequency set will seldom be exact, but best effort.
void setFrequency(uint16_t freq, int offset = 0);
int getFrequency(bool cache = true);
void setFrequency(uint16_t freq, int offset = 0);
int getFrequency(bool cache = true);
// set channel HIGH or LOW (effectively no PWM)
void digitalWrite(uint8_t channel, uint8_t mode);
void digitalWrite(uint8_t channel, uint8_t mode);
// for backwards compatibility; will be removed in future
void setON(uint8_t channel) { digitalWrite(channel, HIGH); };
void setOFF(uint8_t channel) { digitalWrite(channel, LOW); };
void setON(uint8_t channel) { digitalWrite(channel, HIGH); };
void setOFF(uint8_t channel) { digitalWrite(channel, LOW); };
// experimental for 0.3.0
void allOFF();
void allOFF();
int lastError();
int lastError();
/////////////////////////////////////////////////////
//
// SUB CALL - ALL CALL (since 0.4.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:

View File

@ -8,10 +8,10 @@
# PCA9685_RT
Arduino library for I2C PCA9685 16 channel PWM extender.
Arduino library for PCA9685 I2C 12 bit PWM LED driver, 16 channel.
# Description
## Description
This library is to control the I2C PCA9685 PWM extender.
The 16 channels are independently configurable in steps of 1/4096.
@ -29,24 +29,76 @@ Lower frequencies do better than higher frequencies.
## Interface
### Constructor
- **PCA9685(uint8_t deviceAddress, TwoWire \* wire = &Wire)** I2C address + optional I2C interface.
- **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.
- **PCA9685(uint8_t deviceAddress, TwoWire \* wire = &Wire)** Constructor with I2C device address,
and optional the Wire interface as parameter.
- **bool begin(uint8_t mode1_mask = PCA9685_MODE1_AUTOINCR | PCA9685_MODE1_ALLCALL, uint8_t mode2_mask = PCA9685_MODE2_TOTEMPOLE)**
initializes the library after startup. Optionally setting the MODE1 and MODE2 configuration registers.
See PCA9685.h and datasheet for settings possible.
- **bool begin(uint8_t sda, uint8_t scl, uint8_t mode1_mask = PCA9685_MODE1_AUTOINCR | PCA9685_MODE1_ALLCALL, uint8_t mode2_mask = PCA9685_MODE2_TOTEMPOLE)**
idem, ESP32 ESP8266 only.
- **void configure(uint8_t mode1_mask, uint8_t mode2_mask)**
To configure the library after startup one can set the MODE1 and MODE2 configuration registers.
See PCA9685.h and datasheet for settings possible.
- **bool isConnected()** checks if address is available on I2C bus.
- **uint8_t channelCount()** returns the number of channels = 16.
### Mode
### Mode registers
- **writeMode(uint8_t reg, uint8_t value)** configuration of one of the two configuration registers.
check datasheet for details.
- **uint8_t readMode(reg)** reads back the configured mode,
useful to add or remove a single flag (bit masking)
Used to configure the PCA9685 general behaviour.
- **uint8_t writeMode(uint8_t reg, uint8_t value)** configuration of one of the two configuration registers.
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.
- **uint8_t setMode2(uint8_t value)** convenience wrapper.
- **uint8_t getMode1()** convenience wrapper.
- **uint8_t getMode2()** convenience wrapper.
#### Constants for mode registers
(added 0.4.0)
| Name | Value | Description |
|:------------------------|:-----:|:-----------------------------------|
| PCA9685_MODE1_RESTART | 0x80 | 0 = disable 1 = enable |
| PCA9685_MODE1_EXTCLK | 0x40 | 0 = internal 1 = external |
| PCA9685_MODE1_AUTOINCR | 0x20 | 0 = disable 1 = enable |
| PCA9685_MODE1_SLEEP | 0x10 | 0 = normal 1 = sleep |
| PCA9685_MODE1_SUB1 | 0x08 | 0 = disable 1 = enable |
| PCA9685_MODE1_SUB2 | 0x04 | 0 = disable 1 = enable |
| PCA9685_MODE1_SUB3 | 0x02 | 0 = disable 1 = enable |
| PCA9685_MODE1_ALLCALL | 0x01 | 0 = disable 1 = enable |
| PCA9685_MODE1_NONE | 0x00 | |
| | | |
| PCA9685_MODE2_BLINK | 0x20 | 0 = dim 1 = blink |
| PCA9685_MODE2_INVERT | 0x10 | 0 = normal 1 = inverted |
| PCA9685_MODE2_STOP | 0x08 | 0 = on STOP 1 = on ACK |
| PCA9685_MODE2_TOTEMPOLE | 0x04 | 0 = open drain 1 = totem-pole |
| PCA9685_MODE2_OUTNE | 0x03 | check datasheet |
| PCA9685_MODE2_NONE | 0x00 | |
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:
```cpp
ledArray.writeMode(PCA9685_MODE2, 0b00110100);
// would become
uint8_t mode2_mask = PCA9685_MODE2_BLINK | PCA9685_MODE2_INVERT | PCA9685_MODE2_TOTEMPOLE;
ledArray.writeMode(PCA9685_MODE2, mode2_mask);
// or even
ledArray.setMode2(PCA9685_MODE2_BLINK | PCA9685_MODE2_INVERT | PCA9685_MODE2_TOTEMPOLE);
```
### PWM
@ -104,6 +156,48 @@ When using offset, the **getFrequency(false)** will return the adjusted **preSca
| PCA9685_ERR_I2C | 0xFC | PCA9685 I2C communication error |
### SUB CALL and ALL CALL
(new since 0.4.0)
Please read the datasheet to understand the working of **SUB CALL** and **ALL CALL**.
Since version 0.4.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 PCA9685 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 PCA9685 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
@ -113,8 +207,9 @@ See examples
- improve documentation
- add unit tests (if possible)
- investigate set/getFrequency int vs uint16_t ?
-
- investigate int vs uint16_t ?
- **setFrequency(), getFrequency(), \_freq**
- sync with PCA9634/35/85 where possible
- error handling?

View File

@ -6,11 +6,16 @@ PCA9685 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
reset KEYWORD2
configure KEYWORD2
isConnected KEYWORD2
writeMode KEYWORD2
readMode KEYWORD2
setMode1 KEYWORD2
setMode2 KEYWORD2
getMode1 KEYWORD2
getMode2 KEYWORD2
setPWM KEYWORD2
getPWM KEYWORD2
@ -24,6 +29,13 @@ allOFF KEYWORD2
lastError KEYWORD2
enableSubCall KEYWORD2
disableSubCall KEYWORD2
isEnabledSubCall KEYWORD2
enableAllCall KEYWORD2
disableAllCall KEYWORD2
isEnabledAllCall KEYWORD2
# Constants (LITERAL1)
PCA9685_LIB_VERSION LITERAL1
@ -37,3 +49,19 @@ PCA9685_ERR_I2C LITERAL1
PCA9685_MIN_FREQ LITERAL1
PCA9685_MAX_FREQ LITERAL1
PCA9685_MODE1_RESTART LITERAL1
PCA9685_MODE1_EXTCLK LITERAL1
PCA9685_MODE1_AUTOINCR LITERAL1
PCA9685_MODE1_SLEEP LITERAL1
PCA9685_MODE1_SUB1 LITERAL1
PCA9685_MODE1_SUB2 LITERAL1
PCA9685_MODE1_SUB3 LITERAL1
PCA9685_MODE1_ALLCALL LITERAL1
PCA9685_MODE1_NONE LITERAL1
PCA9685_MODE2_BLINK LITERAL1
PCA9685_MODE2_INVERT LITERAL1
PCA9685_MODE2_ACK LITERAL1
PCA9685_MODE2_TOTEMPOLE LITERAL1
PCA9685_MODE2_OUTNE LITERAL1
PCA9685_MODE2_NONE LITERAL1

View File

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

View File

@ -1,5 +1,5 @@
name=PCA9685_RT
version=0.3.4
version=0.4.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for I2C PCA9685 16 channel PWM

View File

@ -49,6 +49,22 @@ unittest_teardown()
unittest(test_constants)
{
fprintf(stderr, "\nregisterss");
assertEqual(PCA9685_MODE1 , 0x00);
assertEqual(PCA9685_MODE2 , 0x01);
assertEqual(PCA9685_ALLCALLADR , 0x05);
assertEqual(PCA9685_CHANNEL_0 , 0x06);
assertEqual(PCA9685_ALL_ON_L , 0xFA);
assertEqual(PCA9685_ALL_ON_H , 0xFB);
assertEqual(PCA9685_ALL_OFF_L , 0xFC);
assertEqual(PCA9685_ALL_OFF_H , 0xFD);
assertEqual(PCA9685_PRE_SCALER , 0xFE);
assertEqual(PCA9685_TESTMODE , 0xFF);
fprintf(stderr, "\nerrorcodes");
assertEqual(PCA9685_OK , 0x00);
assertEqual(PCA9685_ERROR , 0xFF);
assertEqual(PCA9685_ERR_CHANNEL, 0xFE);
@ -62,6 +78,7 @@ unittest(test_constructor)
PCA9685 ledArray(0x20);
assertTrue(ledArray.begin());
assertTrue(ledArray.isConnected());
assertEqual(16, ledArray.channelCount());
}