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

BIN
INF/Beispiele.zip Normal file

Binary file not shown.

View File

@@ -0,0 +1,32 @@
License Agreement
(3-clause BSD License)
Janelia Research Campus Software Copyright 1.1
Copyright (c) 2014, Howard Hughes Medical Institute
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Howard Hughes Medical Institute nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,16 @@
#+TITLE: PCA9685
#+AUTHOR: Peter Polidoro
#+EMAIL: peterpolidoro@gmail.com
* Library Information
- Name :: PCA9685
- Version :: 2.1.4
- License :: BSD
- URL :: https://github.com/janelia-arduino/PCA9685
- Author :: Peter Polidoro
- Email :: peterpolidoro@gmail.com
The PCA9685 is a 16-channel 12-bit PWM controller. All channels operate at a
programmable frequency between roughly 25 to 1600 Hz with 16 independent
12-bit duty cycles from 0 to 100%. Supports using a single device (for up to
16 channels) or up to 55 devices (for up to 880 channels).

View File

@@ -0,0 +1,18 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 100;
const uint16_t frequency_increment = 10;
}

View File

@@ -0,0 +1,21 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency_increment;
}
#endif

View File

@@ -0,0 +1,41 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint16_t frequency_min;
uint16_t frequency_max;
uint16_t frequency;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setOutputsNotInverted();
uint16_t time_min = pca9685.getTimeMin();
uint16_t time_max = pca9685.getTimeMax();
pca9685.setAllChannelsOnAndOffTime(time_min,time_max/4);
frequency_min = pca9685.getFrequencyMin();
frequency_max = pca9685.getFrequencyMax();
frequency = frequency_min;
}
void loop()
{
if (frequency > frequency_max)
{
frequency = frequency_min;
}
pca9685.setToFrequency(frequency);
frequency += constants::frequency_increment;
delay(constants::loop_delay);
}

View File

@@ -0,0 +1,21 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 100;
const uint16_t frequency = 200;
const uint16_t time_increment = 100;
const uint8_t channel = 0;
}

View File

@@ -0,0 +1,24 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint16_t time_increment;
extern const uint8_t channel;
}
#endif

View File

@@ -0,0 +1,41 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint16_t time_min;
uint16_t time_max;
uint16_t off_time;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setOutputsNotInverted();
pca9685.setToFrequency(constants::frequency);
time_min = pca9685.getTimeMin();
time_max = pca9685.getTimeMax();
off_time = time_min;
pca9685.setChannelOnTime(constants::channel,time_min);
}
void loop()
{
if (off_time > time_max)
{
off_time = time_min;
}
pca9685.setChannelOffTime(constants::channel,off_time);
off_time += constants::time_increment;
delay(constants::loop_delay);
}

View File

@@ -0,0 +1,28 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_addresses[DEVICE_COUNT] =
{
0x40,
0x41,
0x42
};
const uint8_t device_index = 0;
const size_t output_enable_pin = 2;
const size_t loop_delay = 100;
const uint16_t frequency = 200;
const uint16_t time_increment = 100;
const uint8_t channel = 0;
}

View File

@@ -0,0 +1,27 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
enum{DEVICE_COUNT=3};
extern const uint8_t device_addresses[DEVICE_COUNT];
extern const uint8_t device_index;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint16_t time_increment;
extern const uint8_t channel;
}
#endif

View File

@@ -0,0 +1,46 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint16_t time_min;
uint16_t time_max;
uint16_t on_time;
void setup()
{
pca9685.setWire(Wire);
for (uint8_t device_index=0; device_index<constants::DEVICE_COUNT; ++device_index)
{
pca9685.addDevice(constants::device_addresses[device_index]);
}
pca9685.resetAllDevices();
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setAllDevicesOutputsNotInverted();
pca9685.setAllDevicesToFrequency(constants::frequency);
time_min = pca9685.getTimeMin();
time_max = pca9685.getTimeMax();
on_time = time_min;
pca9685.setAllDeviceChannelsOffTime(PCA9685::DEVICE_ADDRESS_ALL,time_max);
}
void loop()
{
if (on_time > time_max)
{
on_time = time_min;
}
pca9685.setAllDeviceChannelsOnTime(constants::device_addresses[constants::device_index],on_time);
on_time += constants::time_increment;
delay(constants::loop_delay);
}

View File

@@ -0,0 +1,23 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 100;
const uint8_t channel = 0;
const uint16_t servo_pulse_duration_min = 900;
const uint16_t servo_pulse_duration_max = 2100;
const uint16_t servo_pulse_duration_increment = 100;
}

View File

@@ -0,0 +1,26 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint8_t channel;
extern const uint16_t servo_pulse_duration_min;
extern const uint16_t servo_pulse_duration_max;
extern const uint16_t servo_pulse_duration_increment;
}
#endif

View File

@@ -0,0 +1,32 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint16_t servo_pulse_duration;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setToServoFrequency();
servo_pulse_duration = constants::servo_pulse_duration_min;
}
void loop()
{
if (servo_pulse_duration > constants::servo_pulse_duration_max)
{
servo_pulse_duration = constants::servo_pulse_duration_min;
}
pca9685.setChannelServoPulseDuration(constants::channel,servo_pulse_duration);
servo_pulse_duration += constants::servo_pulse_duration_increment;
delay(constants::loop_delay);
}

View File

@@ -0,0 +1,41 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 8000;
const uint16_t frequency = 200;
const uint8_t channel = 0;
const Example examples[EXAMPLE_COUNT] =
{
{
20.0, // DUTY_CYCLE
10.0, // PERCENT_DELAY
},
{
90.0, // DUTY_CYCLE
90.0, // PERCENT_DELAY
},
{
// Always ON
100.0, // DUTY_CYCLE
0.0, // PERCENT_DELAY
},
{
// Always OFF
0.0, // DUTY_CYCLE
0.0, // PERCENT_DELAY
}
};
}

View File

@@ -0,0 +1,32 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint8_t channel;
enum{EXAMPLE_COUNT=4};
struct Example
{
double duty_cycle;
double percent_delay;
};
extern const Example examples[EXAMPLE_COUNT];
}
#endif

View File

@@ -0,0 +1,33 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint8_t example_index;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setToFrequency(constants::frequency);
example_index = 0;
}
void loop()
{
delay(constants::loop_delay);
if (example_index >= constants::EXAMPLE_COUNT)
{
example_index = 0;
}
constants::Example example = constants::examples[example_index++];
pca9685.setChannelDutyCycle(constants::channel,example.duty_cycle,example.percent_delay);
}

View File

@@ -0,0 +1,43 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 8000;
const uint16_t frequency = 200;
const uint8_t channel = 0;
const Example examples[EXAMPLE_COUNT] =
{
{
// ON_TIME < OFF_TIME
511, // ON_TIME
3071, // OFF_TIME
},
{
// ON_TIME < OFF_TIME
2047, // ON_TIME
767, // OFF_TIME
},
{
// Always ON
4096, // ON_TIME
0, // OFF_TIME
},
{
// Always OFF
0, // ON_TIME
4096, // OFF_TIME
}
};
}

View File

@@ -0,0 +1,32 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint8_t channel;
enum{EXAMPLE_COUNT=4};
struct Example
{
uint16_t on_time;
uint16_t off_time;
};
extern const Example examples[EXAMPLE_COUNT];
}
#endif

View File

@@ -0,0 +1,33 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint8_t example_index;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setToFrequency(constants::frequency);
example_index = 0;
}
void loop()
{
delay(constants::loop_delay);
if (example_index >= constants::EXAMPLE_COUNT)
{
example_index = 0;
}
constants::Example example = constants::examples[example_index++];
pca9685.setChannelOnAndOffTime(constants::channel,example.on_time,example.off_time);
}

View File

@@ -0,0 +1,41 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const size_t loop_delay = 8000;
const uint16_t frequency = 200;
const uint8_t channel = 0;
const Example examples[EXAMPLE_COUNT] =
{
{
819, // PULSE_WIDTH
409, // PHASE_SHIFT
},
{
3686, // PULSE_WIDTH
3685, // PHASE_SHIFT
},
{
// Always ON
4096, // PULSE_WIDTH
0, // PHASE_SHIFT
},
{
// Always OFF
0, // PULSE_WIDTH
0, // PHASE_SHIFT
}
};
}

View File

@@ -0,0 +1,32 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint8_t channel;
enum{EXAMPLE_COUNT=4};
struct Example
{
uint16_t pulse_width;
uint16_t phase_shift;
};
extern const Example examples[EXAMPLE_COUNT];
}
#endif

View File

@@ -0,0 +1,33 @@
#include <Arduino.h>
#include <PCA9685.h>
#include "Constants.h"
PCA9685 pca9685;
uint8_t example_index;
void setup()
{
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setToFrequency(constants::frequency);
example_index = 0;
}
void loop()
{
delay(constants::loop_delay);
if (example_index >= constants::EXAMPLE_COUNT)
{
example_index = 0;
}
constants::Example example = constants::examples[example_index++];
pca9685.setChannelPulseWidth(constants::channel,example.pulse_width,example.phase_shift);
}

View File

@@ -0,0 +1,22 @@
// ----------------------------------------------------------------------------
// Constants.cpp
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#include "Constants.h"
namespace constants
{
const uint8_t device_address = 0x40;
const size_t output_enable_pin = 2;
const long baud = 115200;
const size_t loop_delay = 100;
const uint16_t frequency = 200;
const uint16_t time_increment = 400;
const double epsilon = 0.001;
}

View File

@@ -0,0 +1,24 @@
// ----------------------------------------------------------------------------
// Constants.h
//
//
// Authors:
// Peter Polidoro peterpolidoro@gmail.com
// ----------------------------------------------------------------------------
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <Arduino.h>
namespace constants
{
extern const uint8_t device_address;
extern const size_t output_enable_pin;
extern const long baud;
extern const size_t loop_delay;
extern const uint16_t frequency;
extern const uint16_t time_increment;
extern const double epsilon;
}
#endif

View File

@@ -0,0 +1,105 @@
#include <Arduino.h>
#include <PCA9685.h>
#include <Streaming.h>
#include "Constants.h"
PCA9685 pca9685;
uint16_t time_min;
uint16_t time_max;
uint8_t channel;
uint16_t on_time_set;
uint16_t off_time_set;
uint16_t on_time_get;
uint16_t off_time_get;
uint16_t pulse_width_set;
uint16_t phase_shift_set;
uint16_t pulse_width_get;
uint16_t phase_shift_get;
double duty_cycle_set;
double percent_delay_set;
double duty_cycle_get;
double percent_delay_get;
void setup()
{
Serial.begin(constants::baud);
pca9685.setupSingleDevice(Wire,constants::device_address);
pca9685.setupOutputEnablePin(constants::output_enable_pin);
pca9685.enableOutputs(constants::output_enable_pin);
pca9685.setOutputsNotInverted();
pca9685.setToServoFrequency();
time_min = pca9685.getTimeMin();
time_max = pca9685.getTimeMax();
channel = 0;
on_time_set = time_min;
off_time_set = time_max;
}
void checkMatch(const char * s, bool match)
{
if (match)
{
Serial << s << " get matches set.\n";
}
else
{
Serial << s << " get does not match set!\n";
}
}
void loop()
{
if (on_time_set > off_time_set)
{
on_time_set = time_min;
off_time_set = time_max;
}
for (uint8_t channel=0; channel < pca9685.getChannelCount(); ++channel)
{
Serial << "frequency: " << pca9685.getFrequency() << "\n";
Serial << "channel: " << channel << ", on_time_set: " << on_time_set << ", off_time_set: " << off_time_set << "\n";
pca9685.setChannelOnAndOffTime(channel,on_time_set,off_time_set);
pca9685.getChannelOnAndOffTime(channel,on_time_get,off_time_get);
checkMatch("ChannelOnAndOffTime",((on_time_set == on_time_get) && (off_time_set == off_time_get)));
pca9685.setChannelOnTime(channel,on_time_set);
pca9685.getChannelOnTime(channel,on_time_get);
checkMatch("ChannelOnTime",(on_time_set == on_time_get));
pca9685.setChannelOffTime(channel,off_time_set);
pca9685.getChannelOffTime(channel,off_time_get);
checkMatch("ChannelOffTime",(off_time_set == off_time_get));
pulse_width_set = off_time_set - on_time_set;
phase_shift_set = on_time_set;
Serial << "channel: " << channel << ", pulse_width_set: " << pulse_width_set << ", phase_shift_set: " << phase_shift_set << "\n";
pca9685.setChannelPulseWidth(channel,pulse_width_set,phase_shift_set);
pca9685.getChannelPulseWidth(channel,pulse_width_get,phase_shift_get);
checkMatch("ChannelPulseWidth",((pulse_width_set == pulse_width_get) && (phase_shift_set == phase_shift_get)));
duty_cycle_set = (pulse_width_set * pca9685.getDutyCycleMax()) / pca9685.getTimeMax();
percent_delay_set = (phase_shift_set * pca9685.getPercentDelayMax()) / pca9685.getTimeMax();
Serial << "channel: " << channel << ", duty_cycle_set: " << duty_cycle_set << ", percent_delay_set: " << percent_delay_set << "\n";
pca9685.setChannelDutyCycle(channel,duty_cycle_set,percent_delay_set);
pca9685.getChannelDutyCycle(channel,duty_cycle_get,percent_delay_get);
checkMatch("ChannelDutyCycle",((abs(duty_cycle_set - duty_cycle_get) < constants::epsilon) && (abs(percent_delay_set - percent_delay_get) < constants::epsilon)));
Serial << "\n";
delay(constants::loop_delay);
}
on_time_set += constants::time_increment;
off_time_set -= constants::time_increment;
}

View File

@@ -0,0 +1,9 @@
name=PCA9685
version=2.1.4
author=Peter Polidoro <peterpolidoro@gmail.com>
maintainer=Peter Polidoro <peterpolidoro@gmail.com>
sentence=PCA9685 16-channel 12-bit PWM controller.
paragraph=Like this project? Please star it on GitHub!
category=Device Control
url=https://github.com/janelia-arduino/PCA9685.git
architectures=*

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