inf sachen

This commit is contained in:
danielvici123
2024-12-02 11:49:11 +01:00
parent fc1eca66a4
commit c810f9541d
31 changed files with 2290 additions and 0 deletions

View File

@@ -0,0 +1,363 @@
// ----------------------------------------------------------------------------
// PCA9685.h
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef PCA9685_H
#define PCA9685_H
#include <Arduino.h>
#include <Wire.h>
class PCA9685
{
public:
PCA9685();
const static uint8_t CHANNELS_PER_DEVICE = 16;
enum {DEVICE_COUNT_MAX=55};
// Convenience method when using a single device
void setupSingleDevice(TwoWire & wire=Wire,
uint8_t device_address=0x40,
bool fast_mode_plus=false);
// Methods for using a single device or multiple devices
void setupOutputEnablePin(size_t output_enable_pin);
void enableOutputs(size_t output_enable_pin);
void disableOutputs(size_t output_enable_pin);
uint16_t getFrequencyMin();
uint16_t getFrequencyMax();
void setToFrequency(uint16_t frequency);
uint16_t getFrequency();
void setToServoFrequency();
uint16_t getServoFrequency();
uint8_t getChannelCount();
double getDutyCycleMin();
double getDutyCycleMax();
double getPercentDelayMin();
double getPercentDelayMax();
void setChannelDutyCycle(uint8_t channel,
double duty_cycle,
double percent_delay=0);
void getChannelDutyCycle(uint8_t channel,
double & duty_cycle,
double & percent_delay);
void setAllChannelsDutyCycle(double duty_cycle,
double percent_delay=0);
uint16_t getPulseWidthMin();
uint16_t getPulseWidthMax();
uint16_t getPhaseShiftMin();
uint16_t getPhaseShiftMax();
void setChannelPulseWidth(uint8_t channel,
uint16_t pulse_width,
uint16_t phase_shift=0);
void getChannelPulseWidth(uint8_t channel,
uint16_t & pulse_width,
uint16_t & phase_shift);
void setAllChannelsPulseWidth(uint16_t pulse_width,
uint16_t phase_shift=0);
void setChannelServoPulseDuration(uint8_t channel,
uint16_t pulse_duration_microseconds);
void getChannelServoPulseDuration(uint8_t channel,
uint16_t & pulse_duration_microseconds);
void setAllChannelsServoPulseDuration(uint16_t pulse_duration_microseconds);
uint16_t getTimeMin();
uint16_t getTimeMax();
void setChannelOnAndOffTime(uint8_t channel,
uint16_t on_time,
uint16_t off_time);
void getChannelOnAndOffTime(uint8_t channel,
uint16_t & on_time,
uint16_t & off_time);
void setAllChannelsOnAndOffTime(uint16_t on_time,
uint16_t off_time);
void setChannelOnTime(uint8_t channel,
uint16_t on_time);
void getChannelOnTime(uint8_t channel,
uint16_t & on_time);
void setAllChannelsOnTime(uint16_t on_time);
void setChannelOffTime(uint8_t channel,
uint16_t off_time);
void getChannelOffTime(uint8_t channel,
uint16_t & off_time);
void setAllChannelsOffTime(uint16_t off_time);
void setOutputsInverted();
void setOutputsNotInverted();
void setOutputsToTotemPole();
void setOutputsToOpenDrain();
void setOutputsLowWhenDisabled();
void setOutputsHighWhenDisabled();
void setOutputsHighImpedanceWhenDisabled();
// Methods for using multiple devices
// Take care when using fast_mode_plus with non-PCA9685 devices
void setWire(TwoWire & wire=Wire,
bool fast_mode_plus=false);
// device_address=0x40 when all device address
// hardware select lines are low
// cannot use reserved addresses
void addDevice(uint8_t device_address);
void resetAllDevices();
void addDeviceToGroup0(uint8_t device_address);
void removeDeviceFromGroup0(uint8_t device_address);
void addDeviceToGroup1(uint8_t device_address);
void removeDeviceFromGroup1(uint8_t device_address);
void addDeviceToGroup2(uint8_t device_address);
void removeDeviceFromGroup2(uint8_t device_address);
void setSingleDeviceToFrequency(uint8_t device_address,
uint16_t frequency);
uint16_t getSingleDeviceFrequency(uint8_t device_address);
void setAllDevicesToFrequency(uint16_t frequency);
void setSingleDeviceToServoFrequency(uint8_t device_address);
uint16_t getSingleDeviceServoFrequency(uint8_t device_address);
void setAllDevicesToServoFrequency();
uint8_t getDeviceChannelCount();
// Use these device address to set more than one device at a time
// with the methods below
const static uint8_t DEVICE_ADDRESS_ALL = 0x70;
const static uint8_t DEVICE_ADDRESS_GROUP0 = 0x71;
const static uint8_t DEVICE_ADDRESS_GROUP1 = 0x72;
const static uint8_t DEVICE_ADDRESS_GROUP2 = 0x73;
void setDeviceChannelDutyCycle(uint8_t device_address,
uint8_t device_channel,
double duty_cycle,
double percent_delay=0);
void setAllDeviceChannelsDutyCycle(uint8_t device_address,
double duty_cycle,
double percent_delay=0);
void setDeviceChannelPulseWidth(uint8_t device_address,
uint8_t device_channel,
uint16_t pulse_width,
uint16_t phase_shift=0);
void setAllDeviceChannelsPulseWidth(uint8_t device_address,
uint16_t pulse_width,
uint16_t phase_shift=0);
void setDeviceChannelServoPulseDuration(uint8_t device_address,
uint8_t device_channel,
uint16_t pulse_duration_microseconds);
void setAllDeviceChannelsServoPulseDuration(uint8_t device_address,
uint16_t pulse_duration_microseconds);
void setDeviceChannelOnAndOffTime(uint8_t device_address,
uint8_t device_channel,
uint16_t on_time,
uint16_t off_time);
void setAllDeviceChannelsOnAndOffTime(uint8_t device_address,
uint16_t on_time,
uint16_t off_time);
void setDeviceChannelOnTime(uint8_t device_address,
uint8_t device_channel,
uint16_t on_time);
void setAllDeviceChannelsOnTime(uint8_t device_address,
uint16_t on_time);
void setDeviceChannelOffTime(uint8_t device_address,
uint8_t device_channel,
uint16_t off_time);
void setAllDeviceChannelsOffTime(uint8_t device_address,
uint16_t off_time);
void setSingleDeviceOutputsInverted(uint8_t device_address);
void setAllDevicesOutputsInverted();
void setSingleDeviceOutputsNotInverted(uint8_t device_address);
void setAllDevicesOutputsNotInverted();
void setSingleDeviceOutputsToTotemPole(uint8_t device_address);
void setAllDevicesOutputsToTotemPole();
void setSingleDeviceOutputsToOpenDrain(uint8_t device_address);
void setAllDevicesOutputsToOpenDrain();
void setSingleDeviceOutputsLowWhenDisabled(uint8_t device_address);
void setAllDevicesOutputsLowWhenDisabled();
void setSingleDeviceOutputsHighWhenDisabled(uint8_t device_address);
void setAllDevicesOutputsHighWhenDisabled();
void setSingleDeviceOutputsHighImpedanceWhenDisabled(uint8_t device_address);
void setAllDevicesOutputsHighImpedanceWhenDisabled();
private:
const static uint8_t DEVICE_ADDRESS_MIN = 0x40;
const static uint8_t DEVICE_ADDRESS_MAX = 0x7B;
uint8_t device_count_;
uint8_t device_addresses_[DEVICE_COUNT_MAX];
TwoWire * wire_ptr_;
const static long FAST_MODE_PLUS_CLOCK_FREQUENCY = 1000000;
const static int NO_OUTPUT_ENABLE_PIN = -1;
const static int DEVICE_INDEX_NONE = -1;
const static int DEVICE_INDEX_ALL = -2;
const static int DEVICE_INDEX_GROUP0 = -3;
const static int DEVICE_INDEX_GROUP1 = -4;
const static int DEVICE_INDEX_GROUP2 = -5;
int deviceAddressToDeviceIndex(uint8_t device_address);
const static uint8_t GENERAL_CALL_DEVICE_ADDRESS = 0x00;
const static uint8_t SWRST = 0b110;
// Can write to one or more device at a time
// so use address rather than index
template<typename T>
void write(uint8_t device_address,
uint8_t register_address,
T data);
// Can only read from one device at a time
// so use index rather than address
template<typename T>
void read(uint8_t device_index,
uint8_t register_address,
T & data);
const static uint8_t MODE1_REGISTER_ADDRESS = 0x00;
union Mode1Register
{
struct
{
uint8_t allcall : 1;
uint8_t sub3 : 1;
uint8_t sub2 : 1;
uint8_t sub1 : 1;
uint8_t sleep : 1;
uint8_t ai : 1;
uint8_t extclk : 1;
uint8_t restart : 1;
} fields;
uint8_t data;
};
Mode1Register readMode1Register(uint8_t device_index);
const static uint8_t MODE2_REGISTER_ADDRESS = 0x01;
union Mode2Register
{
struct
{
uint8_t outne : 2;
uint8_t outdrv : 1;
uint8_t och : 1;
uint8_t invrt : 1;
uint8_t space : 3;
} fields;
uint8_t data;
};
Mode2Register readMode2Register(uint8_t device_index);
void sleep(uint8_t device_index);
void wake(uint8_t device_index);
void wakeAll();
void setPrescale(uint8_t device_index,
uint8_t prescale);
void getPrescale(uint8_t device_index,
uint8_t & prescale);
uint8_t frequencyToPrescale(uint16_t frequency);
uint16_t prescaleToFrequency(uint8_t prescale);
uint8_t channelToDeviceIndex(uint8_t channel);
uint8_t channelToDeviceChannel(uint8_t channel);
void dutyCycleAndPercentDelayToPulseWidthAndPhaseShift(double duty_cycle,
double percent_delay,
uint16_t & pulse_width,
uint16_t & phase_shift);
void pulseWidthAndPhaseShiftToDutyCycleAndPercentDelay(uint16_t pulse_width,
uint16_t phase_shift,
double & duty_cycle,
double & percent_delay);
void pulseWidthAndPhaseShiftToOnTimeAndOffTime(uint16_t pulse_width,
uint16_t phase_shift,
uint16_t & on_time,
uint16_t & off_time);
void onTimeAndOffTimeToPulseWidthAndPhaseShift(uint16_t on_time,
uint16_t off_time,
uint16_t & pulse_width,
uint16_t & phase_shift);
void servoPulseDurationToPulseWidthAndPhaseShift(uint16_t pulse_duration_microseconds,
uint16_t & pulse_width,
uint16_t & phase_shift);
void pulseWidthAndPhaseShiftToServoPulseDuration(uint16_t pulse_width,
uint16_t phase_shift,
uint16_t & pulse_duration_microseconds);
void setOutputsInverted(uint8_t device_index);
void setOutputsNotInverted(uint8_t device_index);
void setOutputsToTotemPole(uint8_t device_index);
void setOutputsToOpenDrain(uint8_t device_index);
void setOutputsLowWhenDisabled(uint8_t device_index);
void setOutputsHighWhenDisabled(uint8_t device_index);
void setOutputsHighImpedanceWhenDisabled(uint8_t device_index);
const static uint8_t DOES_NOT_RESPOND = 0;
const static uint8_t DOES_RESPOND = 1;
const static uint8_t SUBADR1_REGISTER_ADDRESS = 0x02;
const static uint8_t SUBADR2_REGISTER_ADDRESS = 0x03;
const static uint8_t SUBADR3_REGISTER_ADDRESS = 0x04;
const static uint8_t ALLCALLADR_REGISTER_ADDRESS = 0x05;
const static uint8_t LED0_ON_L_REGISTER_ADDRESS = 0x06;
const static uint8_t LED0_OFF_L_REGISTER_ADDRESS = 0x08;
const static uint8_t ALL_LED_ON_L_REGISTER_ADDRESS = 0xFA;
const static uint8_t ALL_LED_OFF_L_REGISTER_ADDRESS = 0xFC;
const static uint8_t LED_REGISTERS_SIZE = 4;
const static uint8_t BITS_PER_BYTE = 8;
const static uint8_t BITS_PER_TWO_BYTES = 16;
const static uint8_t BYTE_MAX = 0xFF;
const static uint16_t TWO_BYTE_MAX = 0xFFFF;
const static uint8_t PRE_SCALE_REGISTER_ADDRESS = 0xFE;
const static uint8_t PRE_SCALE_MIN = 0x03;
const static uint8_t PRE_SCALE_MAX = 0xFF;
// Use period instead of frequency to calculate prescale since it is linear
// Measured 1620 Hz at prescale value 0x03, 1E6/1620=617
// Datasheet says it should be 1526 Hz, 1E6/1526=655
const static uint16_t PWM_PERIOD_MIN_US = 617;
// Measured 25.3 Hz at prescale value 0xFF, 1E6/25.3=39525
// Datasheet says it should be 24 Hz, 1E6/24=41666
const static uint16_t PWM_PERIOD_MAX_US = 39525;
const static uint32_t MICROSECONDS_PER_SECOND = 1000000;
const static uint8_t OUTPUTS_INVERTED = 1;
const static uint8_t OUTPUTS_NOT_INVERTED = 0;
const static uint8_t OUTPUTS_TOTEM_POLE = 1;
const static uint8_t OUTPUTS_OPEN_DRAIN = 0;
const static uint8_t OUTPUTS_LOW_WHEN_DISABLED = 0b00;
const static uint8_t OUTPUTS_HIGH_WHEN_DISABLED = 0b01;
const static uint8_t OUTPUTS_HIGH_IMPEDANCE_WHEN_DISABLED = 0b10;
const static uint8_t SLEEP = 1;
const static uint8_t WAKE = 0;
const static uint8_t AUTO_INCREMENT_ENABLED = 1;
const static uint8_t AUTO_INCREMENT_DISABLED = 0;
const static uint8_t RESTART_ENABLED = 1;
const static uint8_t RESTART_DISABLED = 0;
const static uint8_t RESTART_CLEAR = 1;
const static uint16_t TIME_MIN = 0;
const static uint16_t TIME_MAX = 4096;
const static uint8_t PERCENT_MIN = 0;
const static uint8_t PERCENT_MAX = 100;
const static uint16_t SERVO_FREQUENCY = 50;
const static uint16_t SERVO_PERIOD_MICROSECONDS = 20000;
};
#include "PCA9685/PCA9685Definitions.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
// ----------------------------------------------------------------------------
// PCA9685.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef PCA9685_DEFINITIONS_H
#define PCA9685_DEFINITIONS_H
template<typename T>
void PCA9685::write(uint8_t device_address,
uint8_t register_address,
T data)
{
int byte_count = sizeof(data);
wire_ptr_->beginTransmission(device_address);
wire_ptr_->write(register_address);
for (int byte_n=0; byte_n<byte_count; ++byte_n)
{
wire_ptr_->write((data >> (BITS_PER_BYTE * byte_n)) & BYTE_MAX);
}
wire_ptr_->endTransmission();
}
template<typename T>
void PCA9685::read(uint8_t device_index,
uint8_t register_address,
T & data)
{
int byte_count = sizeof(data);
int device_address = device_addresses_[device_index];
wire_ptr_->beginTransmission(device_address);
wire_ptr_->write(register_address);
wire_ptr_->endTransmission();
wire_ptr_->requestFrom(device_address,byte_count);
data = 0;
for (int byte_n=0; byte_n<byte_count; ++byte_n)
{
data |= (wire_ptr_->read()) << (BITS_PER_BYTE * byte_n);
}
}
#endif