GY-63_MS5611/libraries/PCA9634/README.md

371 lines
15 KiB
Markdown
Raw Normal View History

2022-01-06 14:09:06 -05:00
[![Arduino CI](https://github.com/RobTillaart/PCA9634/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/PCA9634/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/PCA9634/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/PCA9634/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/PCA9634/actions/workflows/jsoncheck.yml)
2023-09-24 08:23:03 -04:00
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/PCA9634.svg)](https://github.com/RobTillaart/PCA9634/issues)
2022-01-06 14:09:06 -05:00
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/PCA9634/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/PCA9634.svg?maxAge=3600)](https://github.com/RobTillaart/PCA9634/releases)
2023-09-24 08:23:03 -04:00
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/PCA9634.svg)](https://registry.platformio.org/libraries/robtillaart/PCA9634)
2022-01-06 14:09:06 -05:00
# PCA9634
Arduino library for PCA9634 I2C 8 bit PWM LED driver, 8 channel.
## Description
This library is to control the I2C PCA9634 PWM extender.
The 8 channels are independently configurable in steps of 1/256.
2023-03-14 06:37:16 -04:00
This allows for better than 1% fine tuning of the duty-cycle
2023-01-19 13:09:52 -05:00
of the PWM signal.
2022-01-06 14:09:06 -05:00
2023-05-07 12:57:37 -04:00
#### Related
- https://github.com/RobTillaart/PCA9634 (8 channel)
- https://github.com/RobTillaart/PCA9635 (16 channel)
- https://github.com/RobTillaart/PCA9685_RT (16 channel)
2022-01-06 14:09:06 -05:00
## Interface
2023-03-14 06:37:16 -04:00
```cpp
#include "PCA9634.h"
```
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
#### Constructor
2022-01-06 14:09:06 -05:00
2023-01-19 13:09:52 -05:00
- **PCA9634(uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor with I2C device address,
2022-01-06 14:09:06 -05:00
and optional the Wire interface as parameter.
2023-05-25 09:34:00 -04:00
- **bool begin(uint8_t mode1_mask = PCA963X_MODE1_ALLCALL, uint8_t mode2_mask = PCA963X_MODE2_NONE)**
2023-01-19 13:09:52 -05:00
initializes the library after startup. Optionally setting the MODE1 and MODE2 configuration registers.
2022-05-30 11:42:29 -04:00
See PCA9634.h and datasheet for settings possible.
2023-05-25 09:34:00 -04:00
- **bool begin(int sda, int scl, uint8_t mode1_mask = PCA963X_MODE1_ALLCALL, uint8_t mode2_mask = PCA963X_MODE2_NONE)**
2023-01-19 13:09:52 -05:00
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.
2022-09-07 13:22:42 -04:00
See PCA9634.h and datasheet for settings possible.
2023-03-14 06:37:16 -04:00
- **bool isConnected()** checks if address is available on I2C bus.
2022-01-06 14:09:06 -05:00
- **uint8_t channelCount()** returns the number of channels = 8.
2022-05-16 12:24:33 -04:00
2023-03-14 06:37:16 -04:00
#### LedDriverMode
2022-01-06 14:09:06 -05:00
2022-05-30 11:42:29 -04:00
Configure LED behaviour.
2022-01-06 14:09:06 -05:00
- **uint8_t setLedDriverMode(uint8_t channel, uint8_t mode)** mode is 0..3 See datasheet for full details.
2023-05-07 12:57:37 -04:00
- returns error code, see below.
- **uint8_t setLedDriverMode(uint8_t mode)** set same mode for ALL channels.
2022-01-06 14:09:06 -05:00
- **uint8_t getLedDriverMode(uint8_t channel)** returns the current mode of the channel.
2023-03-14 06:37:16 -04:00
| LED mode | Value | Description |
|:--------------------|:-------:|:------------------------------------|
2023-05-07 12:57:37 -04:00
| PCA963X_LEDOFF | 0x00 | led is 100% off, default @startup |
| PCA963X_LEDON | 0x01 | led is 100% on. |
| PCA963X_LEDPWM | 0x02 | set LED in PWM mode, 0..255 |
| PCA963X_LEDGRPPWM | 0x03 | add LED to the GRPPWM* |
2022-01-06 14:09:06 -05:00
2023-01-19 13:09:52 -05:00
2022-01-06 14:09:06 -05:00
\* 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.
2023-03-14 06:37:16 -04:00
#### Read and write
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
Read and write individual values to LED channels.
2022-05-30 11:42:29 -04:00
Requires LEDs' DriverMode of the specific channels to be in PWM mode.
2022-01-06 14:09:06 -05:00
- **uint8_t write1(uint8_t channel, uint8_t value)** writes a single 8 bit PWM value.
2023-03-14 06:37:16 -04:00
- **uint8_t write3(uint8_t channel, uint8_t R, uint8_t G, uint8_t B)**
2022-05-30 11:42:29 -04:00
writes three consecutive PWM registers.
2022-01-06 14:09:06 -05:00
typical use is to write R, G, B values for a full colour LED.
2023-03-14 06:37:16 -04:00
- **uint8_t writeN(uint8_t channel, uint8_t \* array, uint8_t count)**
2023-01-19 13:09:52 -05:00
write count consecutive PWM registers.
2023-05-07 12:57:37 -04:00
May return **PCA963X_ERR_CHAN** if array has too many elements
2022-01-06 14:09:06 -05:00
(including channel as offset).
2022-05-16 12:24:33 -04:00
2023-03-14 06:37:16 -04:00
#### Mode registers
2022-05-16 12:24:33 -04:00
2022-05-30 11:42:29 -04:00
Used to configure the PCA963x general behaviour.
2022-01-06 14:09:06 -05:00
- **uint8_t writeMode(uint8_t reg, uint8_t value)** configuration of one of the two configuration registers.
2022-05-30 11:42:29 -04:00
Check datasheet for details.
2023-03-14 06:37:16 -04:00
- **uint8_t readMode(uint8_t reg)** reads back the configured mode,
2022-01-06 14:09:06 -05:00
useful to add or remove a single flag (bit masking).
2022-05-30 11:42:29 -04:00
- **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.
2022-05-16 12:24:33 -04:00
#### Constants for mode registers
2023-03-14 06:37:16 -04:00
| Name | Value | Description |
|:--------------------------|:-------:|:-------------------------------------|
2023-05-25 09:34:00 -04:00
| PCA963X_MODE1_AUTOINCR2 | 0x80 | Read Only, 0 = disable 1 = enable |
| PCA963X_MODE1_AUTOINCR1 | 0x40 | Read Only, bit1 |
| PCA963X_MODE1_AUTOINCR0 | 0x20 | Read Only, bit0 |
| PCA963X_MODE1_SLEEP | 0x10 | 0 = normal 1 = sleep |
| PCA963X_MODE1_SUB1 | 0x08 | 0 = disable 1 = enable |
| PCA963X_MODE1_SUB2 | 0x04 | 0 = disable 1 = enable |
| PCA963X_MODE1_SUB3 | 0x02 | 0 = disable 1 = enable |
| PCA963X_MODE1_ALLCALL | 0x01 | 0 = disable 1 = enable |
| PCA963X_MODE1_NONE | 0x00 | |
2023-03-14 06:37:16 -04:00
| ---- | | |
2023-05-25 09:34:00 -04:00
| PCA963X_MODE2_BLINK | 0x20 | 0 = dim 1 = blink |
| PCA963X_MODE2_INVERT | 0x10 | 0 = normal 1 = inverted |
| PCA963X_MODE2_STOP | 0x08 | 0 = on STOP 1 = on ACK |
| PCA963X_MODE2_TOTEMPOLE | 0x04 | 0 = open drain 1 = totem-pole |
| PCA963X_MODE2_NONE | 0x00 | |
2022-05-16 12:24:33 -04:00
2023-01-19 13:09:52 -05:00
2022-05-16 12:24:33 -04:00
These constants makes it easier to set modes without using a non descriptive
2022-05-30 11:42:29 -04:00
bit mask. The constants can be merged by OR-ing them together, see snippet:
2022-05-16 12:24:33 -04:00
```cpp
2023-05-07 12:57:37 -04:00
ledArray.writeMode(PCA963X_MODE2, 0b00110100);
2022-05-16 12:24:33 -04:00
// would become
2023-05-25 09:34:00 -04:00
uint8_t mode2_mask = PCA963X_MODE2_BLINK | PCA963X_MODE2_INVERT | PCA963X_MODE2_TOTEMPOLE;
2023-05-07 12:57:37 -04:00
ledArray.writeMode(PCA963X_MODE2, mode2_mask);
2022-05-16 12:24:33 -04:00
// or even
2023-05-25 09:34:00 -04:00
ledArray.setMode2(PCA963X_MODE2_BLINK | PCA963X_MODE2_INVERT | PCA963X_MODE2_TOTEMPOLE);
2022-05-16 12:24:33 -04:00
```
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
#### Group PWM and frequency
2022-01-06 14:09:06 -05:00
2022-05-30 11:42:29 -04:00
Check datasheet for the details.
2022-01-06 14:09:06 -05:00
- **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.
2023-03-14 06:37:16 -04:00
- **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.
2022-05-30 11:42:29 -04:00
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.
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
#### Miscellaneous
2022-01-06 14:09:06 -05:00
2023-05-07 12:57:37 -04:00
- **int lastError()** returns **PCA963X_OK** if all is OK, and other error codes otherwise.
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
| Error code | Value | Description |
|:--------------------|:-------:|:-----------------------|
2023-05-07 12:57:37 -04:00
| PCA963X_OK | 0x00 | Everything went well
| PCA963X_ERROR | 0xFF | Generic error
| PCA963X_ERR_WRITE | 0xFE | Tries to write more elements than PWM channels
| PCA963X_ERR_CHAN | 0xFD | Channel out of range
| PCA963X_ERR_MODE | 0xFC | Invalid mode
| PCA963X_ERR_REG | 0xFB | Invalid register
| PCA963X_ERR_I2C | 0xFA | I2C communication error
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
## SUB CALL and ALL CALL
2022-05-30 11:42:29 -04:00
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.
2023-01-19 13:09:52 -05:00
2022-05-30 11:42:29 -04:00
#### 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.
2023-03-14 06:37:16 -04:00
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
2022-05-30 11:42:29 -04:00
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.
2022-09-07 13:22:42 -04:00
2022-05-30 11:42:29 -04:00
#### 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()**
2023-03-14 06:37:16 -04:00
#### OutputEnable
Since 0.2.6 (experimental) support to control the OE (Output Enable) pin of the PCA9634.
This OE pin can control all LEDs simultaneously.
2023-05-25 09:34:00 -04:00
It also allows to control multiple devices by connecting the OE pins.
2023-03-14 06:37:16 -04:00
Think of simultaneous switching ON/OFF or get dimming with a high frequency PWM.
Or use 2 modules alternatively by placing an inverter in between.
See datasheet for the details
2023-05-25 09:34:00 -04:00
- **bool setOutputEnablePin(uint8_t pin = 255)** sets the IO pin to connect to the OE pin of the device.
2023-03-14 06:37:16 -04:00
A value of 255 indicates no pin set/selected.
Sets the OE pin to HIGH.
Returns true on success.
- **bool setOutputEnable(uint8_t value)** Sets the OE pin HIGH or LOW.
All non zero values are LOW.
Returns true on success.
- **uint8_t getOutputEnable()** get the current value of the OE pin.
If pin is not set/selected it will return HIGH.
Note: the OE is LOW active.
2023-05-07 12:57:37 -04:00
The user has to set the power on value by means of a PULL UP / DOWN resistor.
2023-03-14 06:37:16 -04:00
#### I2C Software reset
2022-09-07 13:22:42 -04:00
2023-05-07 12:57:37 -04:00
The goal of this function is to reset ALL devices on the bus.
2022-09-11 10:10:12 -04:00
When using the software reset, ALL devices attached to the bus are set to their hardware startup conditions.
2023-03-14 06:37:16 -04:00
Generally, there are multiple definitions of software resets by the I2C inventor NXP.
2022-09-11 10:10:12 -04:00
To accommodate this, two different modes for this function have been defined and tested (library version 0.2.2).
2022-09-07 13:22:42 -04:00
2022-09-11 10:10:12 -04:00
- Method 1 is a tested method which is specific to the PCA9634.
2023-03-14 06:37:16 -04:00
Since the number of different types of I2C chips is very large, side-effects on other chips might be possible.
2022-09-11 10:10:12 -04:00
Before using this method, consult the data sheets of all chips on the bus to mitigate potential undefined states.
2023-03-14 06:37:16 -04:00
- Method 0 is a somewhat “general” method which resets many chips on the I2C-bus.
2023-01-19 13:09:52 -05:00
However, this method DOES NOT reset the PCA9634 chip.
2022-09-11 10:10:12 -04:00
Therefore, consult the data sheet of all different chips on the bus to mitigate potential undefined states.
2022-09-07 13:22:42 -04:00
2022-09-11 10:10:12 -04:00
When only working with PCA9634 chips on a bus, only method 1 is required.
2022-09-07 13:22:42 -04:00
2022-09-11 10:10:12 -04:00
```cpp
2023-01-19 13:09:52 -05:00
ledArray.I2C_SoftwareReset(1); // for method 1
ledArray.I2C_SoftwareReset(0); // for method 0
2022-09-11 10:10:12 -04:00
```
2022-09-07 13:22:42 -04:00
2023-01-19 13:09:52 -05:00
In case you experience issues with this function on your chips (non-PCA9634),
2022-09-11 10:10:12 -04:00
please give feedback, so the documentation can be improved.
2022-09-07 13:22:42 -04:00
2022-09-11 10:10:12 -04:00
For further details of the development, see - #10 (comment)
2022-09-07 13:22:42 -04:00
2023-05-07 12:57:37 -04:00
#### LEDOUT
Experimental, needs testing, read datasheet 7.3.6
The LEDOUT0 (12) and LEDOUT1 (13) registers can be used to set the
operational mode how each channel / LED is controlled.
The typical use case is to use PWM per channel
but one can also set a channel / LED fully ON or OFF.
These functions are a fast way to switch multiple LEDs ON/OFF.
The two registers LEDOUT0 .. LEDOUT1 each control 4 channels
| register | channels | mask layout | notes |
|:----------:|:----------:|:-------------:|:-------:|
| 0 | 0 .. 3 | 33221100 | every channel has 2 bits.
| 1 | 4 .. 7 | idem |
- **uint8_t writeLedOut(uint8_t reg, uint8_t mask)**
- reg = 0..1, if larger than 1 **PCA963X_ERROR** returned.
- mask see below.
- **uint8_t readLedOut(uint8_t reg)**
- reg = 0..1, if larger than 1 **0x00** is returned. Use with care.
- returns the register
To set channel 6 OFF and 7 ON simultaneously:
```cpp
uint8_t mask = PCA.readLedOut(1);
mask &= 0b00001111; // set OFF both 6 and 7
mask |= 0b01000000; // set ON 7
PCA.writeLedOut(1, mask);
```
2023-03-14 06:37:16 -04:00
## Synchronous multi-chip multi-LED operation
2022-01-06 14:09:06 -05:00
2023-03-14 06:37:16 -04:00
In scenarios in which multiple LED states should be updated synchronously, the datasheet specifies a specific sequence.
Therefore, it is possible to update multiple LED registers in one or more PCA963x chips synchronously and have them
change their state at a final STOP command. For this only a few configurations are required.
2023-05-25 09:34:00 -04:00
1. Make sure, the `PCA963X_MODE2_ACK` bit in the `MODE2` register is not set (it should be set to 0).
2023-03-14 06:37:16 -04:00
Therefore, the LED states will be updated at the STOP command of the I2C master and not during the ACK command of the PCA963x slave
2. Do NOT use the `write1()`, `write3()` or `writeN()` functions for changing LED states.
These commands already include a STOP command.
3. Use consecutive `writeN_noStop()` commands for multiple LEDs (can be on the same or different chips) and finish
the communication with the `writeStop()` command. The latter will send a STOP command and end the transmission.
If the PCA963x chips are configured to update their states on the STOP command, this will be the point in time,
when all previously send commands since the last STOP command will be executed.
4. DISCLAIMER:
- This should not be used during the configuration of the chips as the library has not been tested for this.
Furthermore, the configuration functions `writeMode` have STOP commands included
- This function has not been tested for edge cases (what happened when no STOP command is send?
In theory nothing should happen until the next transmission with an STOP command has been send).
Test functionality before implementation into your projects.
2022-01-06 14:09:06 -05:00
2023-05-07 12:57:37 -04:00
2022-01-06 14:09:06 -05:00
## Future
2023-01-19 13:09:52 -05:00
#### Must
2022-01-06 14:09:06 -05:00
- improve documentation
2023-05-07 12:57:37 -04:00
- restructure readme.md
2022-11-19 10:53:05 -05:00
2023-01-19 13:09:52 -05:00
#### Should
2023-05-07 12:57:37 -04:00
- improve error handling
2023-03-14 06:37:16 -04:00
- return values etc.
- documentation.
2023-05-07 12:57:37 -04:00
- keep in sync with PCA9634/5 developments
2022-11-19 10:53:05 -05:00
2023-01-19 13:09:52 -05:00
#### Could
2023-05-07 12:57:37 -04:00
- unit tests
- SUB CALL if possible?
- ALL CALL if possible?
- add examples
- read/writeLedOut()
2023-03-14 06:37:16 -04:00
- **setOutputEnablePWM(uint16_t value)** PWM support ?
- getter?
- restructure function groups
- in .cpp to match .h
- readme.md
2023-05-07 12:57:37 -04:00
- **setGroupFreq()**
- set time in milliseconds and round to nearest value?
2023-03-14 06:37:16 -04:00
#### Wont
2023-05-25 09:34:00 -04:00
2023-05-07 12:57:37 -04:00
- consider implementing
- clearMode1() and clearMode2() functions.
- only upon request.
- merge with PCA9634/5 and a PCA963X base class if possible
2023-05-25 09:34:00 -04:00
- not easy, more alignment is desirable.
2023-05-07 12:57:37 -04:00
- only upon request.
2023-05-25 09:34:00 -04:00
- **setGroupPWM()**
- PWM also in %% ? (trivial for user)
2023-09-24 08:23:03 -04:00
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,