初始化提交
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit 16-channel PWM & Servo driver
|
||||
GPIO test - this will set a pin high/low
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/815
|
||||
|
||||
These drivers use I2C to communicate, 2 pins are required to
|
||||
interface.
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_PWMServoDriver.h>
|
||||
|
||||
// called this way, it uses the default address 0x40
|
||||
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
|
||||
// you can also call it with a different address you want
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
|
||||
// you can also call it with a different address and I2C interface
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("GPIO test!");
|
||||
|
||||
pwm.begin();
|
||||
pwm.setPWMFreq(1000); // Set to whatever you like, we don't use it in this demo!
|
||||
|
||||
// if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode
|
||||
// some i2c devices dont like this so much so if you're sharing the bus, watch
|
||||
// out for this!
|
||||
Wire.setClock(400000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Drive each pin in a 'wave'
|
||||
for (uint8_t pin=0; pin<16; pin++) {
|
||||
pwm.setPWM(pin, 4096, 0); // turns pin fully on
|
||||
delay(100);
|
||||
pwm.setPWM(pin, 0, 4096); // turns pin fully off
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit 16-channel PWM & Servo driver
|
||||
to calibrate the frequency of the oscillator clock of the PCA9685.
|
||||
|
||||
CAUTION: DO NOT CONNECT ANY VOLTAGE HIGHER THAN THE BOARD LIMITS.
|
||||
For 3.3V boards, like the ESP8266, remove any 5V input. The setup will
|
||||
feed the voltage back into the board to measure the frequency.
|
||||
KABOEM, SMOKE if you use too much VOLTAGE.
|
||||
|
||||
Connect the PCA9685 with I2C (Ground, VCC, SCL, SCA) and apply
|
||||
voltage on V+. See above not higher than board limits.
|
||||
Connect the signal (yellow pin, PWM) of the PCA9685 to your board:
|
||||
Default is pin 3, last of first block.
|
||||
Default is pin 14 (of your ESP8266).
|
||||
|
||||
Formula for prescale to get the targetted frequency (=update_rate) is:
|
||||
prescale = round ( osc_clock / 4096 * update_rate) - 1
|
||||
rewritten: osc_clock = (prescale + 1) * 4096 * update_rate
|
||||
We will measure the real update_rate to assert the real osc_clock.
|
||||
|
||||
***************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_PWMServoDriver.h>
|
||||
|
||||
// called this way, it uses the default address 0x40
|
||||
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);
|
||||
// you can also call it with a different address you want
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
|
||||
// you can also call it with a different address and I2C interface
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);
|
||||
|
||||
#if (defined(ESP8266) || defined(ESP32))
|
||||
|
||||
// Applied frequency in the test: can be changed to get the optimal
|
||||
// oscillator calibration for your targetted frequency.
|
||||
#define FREQUENCY 50
|
||||
|
||||
// CAUTION: ONLY CONNECT server and ESP WITHOUT 5V ON V+ or green breakout supply pins. Use 3.3V on V+
|
||||
#define PIN_SERVO_FEEDBACK 3 // Connect Yellow PWM pin, 3 = last on first block
|
||||
#define PIN_BOARD_FEEDBACK 14 // 14 => D5 on NodeMCU
|
||||
|
||||
uint8_t prescale = 0;
|
||||
// loop
|
||||
#define INTERVAL 1000 // 1 sec
|
||||
int32_t lastEvaluation = 0;
|
||||
uint16_t frozenCounter = 0;
|
||||
uint16_t countDeviations = 0;
|
||||
|
||||
uint32_t totalCounter = 0;
|
||||
uint32_t totalTime = 0; // in millis
|
||||
uint32_t realOsciFreq = 0;
|
||||
uint32_t multiplier = 4096;
|
||||
|
||||
// interrupt
|
||||
volatile uint16_t interruptCounter = 0;
|
||||
|
||||
ICACHE_RAM_ATTR void handleInterrupt() {
|
||||
interruptCounter++;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("PCA9685 Oscillator test");
|
||||
|
||||
// set PCA9685
|
||||
pwm.begin();
|
||||
pwm.setPWMFreq(FREQUENCY); // Set some frequency
|
||||
pwm.setPWM(PIN_SERVO_FEEDBACK,0,2048); // half of time high, half of time low
|
||||
prescale = pwm.readPrescale(); // read prescale
|
||||
Serial.printf("Target frequency: %u\n", FREQUENCY);
|
||||
Serial.printf("Applied prescale: %u\n", prescale);
|
||||
|
||||
// prepare interrupt on ESP pin
|
||||
pinMode(PIN_BOARD_FEEDBACK, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_BOARD_FEEDBACK), handleInterrupt, RISING);
|
||||
|
||||
// take a breath and reset to zero
|
||||
delay(10);
|
||||
interruptCounter = 0;
|
||||
lastEvaluation = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (millis() - lastEvaluation > INTERVAL)
|
||||
{
|
||||
// first freeze counters and adjust for new round
|
||||
frozenCounter = interruptCounter; // first freeze counter
|
||||
interruptCounter -= frozenCounter;
|
||||
lastEvaluation += INTERVAL;
|
||||
|
||||
totalCounter += frozenCounter;
|
||||
totalTime += 1;
|
||||
|
||||
// only print deviations from targetted frequency
|
||||
//if (frozenCounter != FREQUENCY)
|
||||
{
|
||||
multiplier = 4096;
|
||||
realOsciFreq = (prescale + 1) * totalCounter; // first part calcutlation
|
||||
// now follows an ugly hack to have maximum precision in 32 bits
|
||||
while (((realOsciFreq & 0x80000000) == 0) && (multiplier != 1))
|
||||
{
|
||||
realOsciFreq <<= 1;
|
||||
multiplier >>= 1;
|
||||
}
|
||||
realOsciFreq /= totalTime;
|
||||
if (multiplier) realOsciFreq *= multiplier;
|
||||
|
||||
countDeviations++;
|
||||
Serial.printf("%4u", countDeviations);
|
||||
Serial.printf(" Timestamp: %4u ", totalTime);
|
||||
Serial.printf(" Freq: %4u ", frozenCounter);
|
||||
Serial.printf(" Counter: %6u ", totalCounter);
|
||||
Serial.printf(" calc.osci.freq: %9u\n",realOsciFreq);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("PCA9685 Oscillator test");
|
||||
Serial.println("yet not available for your board."); // please help adapt the code!
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
|
||||
#endif // ESP8266/ESP32
|
||||
@@ -0,0 +1,69 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit 16-channel PWM & Servo driver
|
||||
PWM test - this will drive 16 PWMs in a 'wave'
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/815
|
||||
|
||||
These drivers use I2C to communicate, 2 pins are required to
|
||||
interface.
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_PWMServoDriver.h>
|
||||
|
||||
// called this way, it uses the default address 0x40
|
||||
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
|
||||
// you can also call it with a different address you want
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
|
||||
// you can also call it with a different address and I2C interface
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("16 channel PWM test!");
|
||||
|
||||
pwm.begin();
|
||||
/*
|
||||
* In theory the internal oscillator (clock) is 25MHz but it really isn't
|
||||
* that precise. You can 'calibrate' this by tweaking this number until
|
||||
* you get the PWM update frequency you're expecting!
|
||||
* The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
|
||||
* is used for calculating things like writeMicroseconds()
|
||||
* Analog servos run at ~50 Hz updates, It is importaint to use an
|
||||
* oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
|
||||
* 1) Attach the oscilloscope to one of the PWM signal pins and ground on
|
||||
* the I2C PCA9685 chip you are setting the value for.
|
||||
* 2) Adjust setOscillatorFrequency() until the PWM update frequency is the
|
||||
* expected value (50Hz for most ESCs)
|
||||
* Setting the value here is specific to each individual I2C PCA9685 chip and
|
||||
* affects the calculations for the PWM update frequency.
|
||||
* Failure to correctly set the int.osc value will cause unexpected PWM results
|
||||
*/
|
||||
pwm.setOscillatorFrequency(27000000);
|
||||
pwm.setPWMFreq(1600); // This is the maximum PWM frequency
|
||||
|
||||
// if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode
|
||||
// some i2c devices dont like this so much so if you're sharing the bus, watch
|
||||
// out for this!
|
||||
Wire.setClock(400000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Drive each PWM in a 'wave'
|
||||
for (uint16_t i=0; i<4096; i += 8) {
|
||||
for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {
|
||||
pwm.setPWM(pwmnum, 0, (i + (4096/16)*pwmnum) % 4096 );
|
||||
}
|
||||
#ifdef ESP8266
|
||||
yield(); // take a breather, required for ESP8266
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit 16-channel PWM & Servo driver
|
||||
Servo test - this will drive 8 servos, one after the other on the
|
||||
first 8 pins of the PCA9685
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/815
|
||||
|
||||
These drivers use I2C to communicate, 2 pins are required to
|
||||
interface.
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_PWMServoDriver.h>
|
||||
|
||||
// called this way, it uses the default address 0x40
|
||||
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
|
||||
// you can also call it with a different address you want
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
|
||||
// you can also call it with a different address and I2C interface
|
||||
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);
|
||||
|
||||
// Depending on your servo make, the pulse width min and max may vary, you
|
||||
// want these to be as small/large as possible without hitting the hard stop
|
||||
// for max range. You'll have to tweak them as necessary to match the servos you
|
||||
// have!
|
||||
#define SERVOMIN 150 // This is the 'minimum' pulse length count (out of 4096)
|
||||
#define SERVOMAX 600 // This is the 'maximum' pulse length count (out of 4096)
|
||||
#define USMIN 600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
|
||||
#define USMAX 2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
|
||||
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
|
||||
|
||||
// our servo # counter
|
||||
uint8_t servonum = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("8 channel Servo test!");
|
||||
|
||||
pwm.begin();
|
||||
/*
|
||||
* In theory the internal oscillator (clock) is 25MHz but it really isn't
|
||||
* that precise. You can 'calibrate' this by tweaking this number until
|
||||
* you get the PWM update frequency you're expecting!
|
||||
* The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
|
||||
* is used for calculating things like writeMicroseconds()
|
||||
* Analog servos run at ~50 Hz updates, It is importaint to use an
|
||||
* oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
|
||||
* 1) Attach the oscilloscope to one of the PWM signal pins and ground on
|
||||
* the I2C PCA9685 chip you are setting the value for.
|
||||
* 2) Adjust setOscillatorFrequency() until the PWM update frequency is the
|
||||
* expected value (50Hz for most ESCs)
|
||||
* Setting the value here is specific to each individual I2C PCA9685 chip and
|
||||
* affects the calculations for the PWM update frequency.
|
||||
* Failure to correctly set the int.osc value will cause unexpected PWM results
|
||||
*/
|
||||
pwm.setOscillatorFrequency(27000000);
|
||||
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
|
||||
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// You can use this function if you'd like to set the pulse length in seconds
|
||||
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. It's not precise!
|
||||
void setServoPulse(uint8_t n, double pulse) {
|
||||
double pulselength;
|
||||
|
||||
pulselength = 1000000; // 1,000,000 us per second
|
||||
pulselength /= SERVO_FREQ; // Analog servos run at ~60 Hz updates
|
||||
Serial.print(pulselength); Serial.println(" us per period");
|
||||
pulselength /= 4096; // 12 bits of resolution
|
||||
Serial.print(pulselength); Serial.println(" us per bit");
|
||||
pulse *= 1000000; // convert input seconds to us
|
||||
pulse /= pulselength;
|
||||
Serial.println(pulse);
|
||||
pwm.setPWM(n, 0, pulse);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Drive each servo one at a time using setPWM()
|
||||
Serial.println(servonum);
|
||||
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
|
||||
pwm.setPWM(servonum, 0, pulselen);
|
||||
}
|
||||
|
||||
delay(500);
|
||||
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
|
||||
pwm.setPWM(servonum, 0, pulselen);
|
||||
}
|
||||
|
||||
delay(500);
|
||||
|
||||
// Drive each servo one at a time using writeMicroseconds(), it's not precise due to calculation rounding!
|
||||
// The writeMicroseconds() function is used to mimic the Arduino Servo library writeMicroseconds() behavior.
|
||||
for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
|
||||
pwm.writeMicroseconds(servonum, microsec);
|
||||
}
|
||||
|
||||
delay(500);
|
||||
for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
|
||||
pwm.writeMicroseconds(servonum, microsec);
|
||||
}
|
||||
|
||||
delay(500);
|
||||
|
||||
servonum++;
|
||||
if (servonum > 7) servonum = 0; // Testing the first 8 servo channels
|
||||
}
|
||||
Reference in New Issue
Block a user