New PWM class

This commit is contained in:
shrkey
2016-10-10 18:36:15 +01:00
parent 166427041c
commit d6091a1030
2 changed files with 58 additions and 21 deletions

View File

@@ -4,6 +4,8 @@ Written by Mikhail Avkhimenia (mikhail.avkhimenia@emlid.com)
Copyright (c) 2014, Emlid Limited, www.emlid.com Copyright (c) 2014, Emlid Limited, www.emlid.com
All rights reserved. All rights reserved.
Modified by Dark Water (team@darkwater.io)
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
@@ -72,12 +74,16 @@ void PCA9685::sleep() {
* @see PCA9685_MODE1_RESTART_BIT * @see PCA9685_MODE1_RESTART_BIT
*/ */
void PCA9685::restart() { void PCA9685::restart() {
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, (1 << PCA9685_MODE1_SLEEP_BIT));
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, ((1 << PCA9685_MODE1_SLEEP_BIT) I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, 0x00);
| (1 << PCA9685_MODE1_EXTCLK_BIT))); I2Cdev::writeByte(devAddr, PCA9685_RA_MODE2, 0x04);
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, ((1 << PCA9685_MODE1_RESTART_BIT)
| (1 << PCA9685_MODE1_EXTCLK_BIT) // I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, (1 << PCA9685_MODE1_SLEEP_BIT));
| (1 << PCA9685_MODE1_AI_BIT))); // I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, ((1 << PCA9685_MODE1_SLEEP_BIT)
// | (1 << PCA9685_MODE1_EXTCLK_BIT)));
// I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, ((1 << PCA9685_MODE1_RESTART_BIT)
// | (1 << PCA9685_MODE1_EXTCLK_BIT)
// | (1 << PCA9685_MODE1_AI_BIT)));
} }
/** Calculate prescale value based on the specified frequency and write it to the device. /** Calculate prescale value based on the specified frequency and write it to the device.
@@ -96,12 +102,23 @@ float PCA9685::getFrequency() {
* @see PCA9685_RA_PRE_SCALE * @see PCA9685_RA_PRE_SCALE
*/ */
void PCA9685::setFrequency(float frequency) { void PCA9685::setFrequency(float frequency) {
sleep(); sleep();
usleep(10000); usleep(10000);
uint8_t prescale = roundf(24576000.f / 4096.f / frequency) - 1; uint8_t prescale = roundf(25000000.f / 4096.f / frequency) - 1;
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, 0x10);
I2Cdev::writeByte(devAddr, PCA9685_RA_PRE_SCALE, prescale); I2Cdev::writeByte(devAddr, PCA9685_RA_PRE_SCALE, prescale);
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, 0x80);
I2Cdev::writeByte(devAddr, PCA9685_RA_MODE1, 0x04);
this->frequency = getFrequency(); this->frequency = getFrequency();
restart(); restart();
// sleep();
// usleep(10000);
// uint8_t prescale = roundf(24576000.f / 4096.f / frequency) - 1;
// I2Cdev::writeByte(devAddr, PCA9685_RA_PRE_SCALE, prescale);
// this->frequency = getFrequency();
// restart();
} }
/** Set channel start offset of the pulse and it's length /** Set channel start offset of the pulse and it's length
@@ -111,18 +128,25 @@ void PCA9685::setFrequency(float frequency) {
* @see PCA9685_RA_LED0_ON_L * @see PCA9685_RA_LED0_ON_L
*/ */
void PCA9685::setPWM(uint8_t channel, uint16_t offset, uint16_t length) { void PCA9685::setPWM(uint8_t channel, uint16_t offset, uint16_t length) {
uint8_t data[4] = {0, 0, 0, 0};
if(length == 0) {
data[3] = 0x10; I2Cdev::writeByte(devAddr, PCA9685_RA_LED0_ON_L + LED_MULTIPLYER * channel, offset & 0xFF);
} else if(length >= 4096) { I2Cdev::writeByte(devAddr, PCA9685_RA_LED0_ON_H + LED_MULTIPLYER * channel, offset >> 8);
data[1] = 0x10; I2Cdev::writeByte(devAddr, PCA9685_RA_LED0_OFF_L + LED_MULTIPLYER * channel, length & 0xFF);
} else { I2Cdev::writeByte(devAddr, PCA9685_RA_LED0_OFF_H + LED_MULTIPLYER * channel, length >> 8);
data[0] = offset & 0xFF;
data[1] = offset >> 8; // uint8_t data[4] = {0, 0, 0, 0};
data[2] = length & 0xFF; // if(length == 0) {
data[3] = length >> 8; // data[3] = 0x10;
} // } else if(length >= 4096) {
I2Cdev::writeBytes(devAddr, PCA9685_RA_LED0_ON_L + 4 * channel, 4, data); // data[1] = 0x10;
// } else {
// data[0] = offset & 0xFF;
// data[1] = offset >> 8;
// data[2] = length & 0xFF;
// data[3] = length >> 8;
// }
// I2Cdev::writeBytes(devAddr, PCA9685_RA_LED0_ON_L + 4 * channel, 4, data);
} }
/** Set channel's pulse length /** Set channel's pulse length
@@ -158,8 +182,14 @@ void PCA9685::setPWMuS(uint8_t channel, float length_uS) {
* @see PCA9685_RA_ALL_LED_ON_L * @see PCA9685_RA_ALL_LED_ON_L
*/ */
void PCA9685::setAllPWM(uint16_t offset, uint16_t length) { void PCA9685::setAllPWM(uint16_t offset, uint16_t length) {
uint8_t data[4] = {offset & 0xFF, offset >> 8, length & 0xFF, length >> 8};
I2Cdev::writeBytes(devAddr, PCA9685_RA_ALL_LED_ON_L, 4, data); I2Cdev::writeByte(devAddr, PCA9685_RA_ALL_LED_ON_L, offset & 0xFF);
I2Cdev::writeByte(devAddr, PCA9685_RA_ALL_LED_ON_H, offset >> 8);
I2Cdev::writeByte(devAddr, PCA9685_RA_ALL_LED_OFF_L, length & 0xFF);
I2Cdev::writeByte(devAddr, PCA9685_RA_ALL_LED_OFF_H, length >> 8);
// uint8_t data[4] = {offset & 0xFF, offset >> 8, length & 0xFF, length >> 8};
// I2Cdev::writeBytes(devAddr, PCA9685_RA_ALL_LED_ON_L, 4, data);
} }
/** Set pulse length for all channels /** Set pulse length for all channels

View File

@@ -4,6 +4,8 @@ Written by Mikhail Avkhimenia (mikhail.avkhimenia@emlid.com)
Copyright (c) 2014, Emlid Limited Copyright (c) 2014, Emlid Limited
All rights reserved. All rights reserved.
Modified by Dark Water (team@darkwater.io)
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
@@ -43,10 +45,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define PCA9685_RA_MODE1 0x00 #define PCA9685_RA_MODE1 0x00
#define PCA9685_RA_MODE2 0x01 #define PCA9685_RA_MODE2 0x01
#define PCA9685_RA_SUBADR1 0x02 //I2C-bus subaddress 1
#define PCA9685_RA_SUBADR2 0x03 //I2C-bus subaddress 2
#define PCA9685_RA_SUBADR3 0x04 //I2C-bus subaddress 3
#define PCA9685_RA_ALLCALLADR 0x05 //LED All Call I2C-bus address
#define PCA9685_RA_LED0_ON_L 0x06 #define PCA9685_RA_LED0_ON_L 0x06
#define PCA9685_RA_LED0_ON_H 0x07 #define PCA9685_RA_LED0_ON_H 0x07
#define PCA9685_RA_LED0_OFF_L 0x08 #define PCA9685_RA_LED0_OFF_L 0x08
#define PCA9685_RA_LED0_OFF_H 0x09 #define PCA9685_RA_LED0_OFF_H 0x09
#define LED_MULTIPLYER 4 // For the other 15 channels
#define PCA9685_RA_ALL_LED_ON_L 0xFA #define PCA9685_RA_ALL_LED_ON_L 0xFA
#define PCA9685_RA_ALL_LED_ON_H 0xFB #define PCA9685_RA_ALL_LED_ON_H 0xFB
#define PCA9685_RA_ALL_LED_OFF_L 0xFC #define PCA9685_RA_ALL_LED_OFF_L 0xFC