GY-63_MS5611/libraries/PCA9685_RT/PCA9685.h
2022-06-10 12:52:02 +02:00

168 lines
5.6 KiB
C++

#pragma once
//
// FILE: PCA9685.h
// AUTHOR: Rob Tillaart
// DATE: 24-apr-2016
// VERSION: 0.4.0
// PURPOSE: Arduino library for I2C PCA9685 16 channel PWM
// URL: https://github.com/RobTillaart/PCA9685_RT
#include "Arduino.h"
#include "Wire.h"
#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
// get/setFrequency()
#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
{
public:
explicit PCA9685(const uint8_t deviceAddress, TwoWire *wire = &Wire);
#if defined (ESP8266) || defined(ESP32)
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(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
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);
// single PWM setting, channel = 0..15, offTime = 0..4095 (onTime = 0)
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 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);
// set channel HIGH or LOW (effectively no PWM)
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); };
// experimental for 0.3.0
void allOFF();
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:
// DIRECT CONTROL
void writeReg(uint8_t reg, uint8_t value);
void writeReg2(uint8_t reg, uint16_t a, uint16_t b);
uint8_t readReg(uint8_t reg);
uint8_t _address;
int _error;
int _freq = 200; // default PWM frequency - P25 datasheet
uint8_t _channelCount = 16;
TwoWire* _wire;
};
// -- END OF FILE --