-
Notifications
You must be signed in to change notification settings - Fork 303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getPWM returns random numbers #56
Comments
I concur with dreadlordrider, in my test getPWM() method does return only random numbers before the first call to setPWM() and thereafter returns only 0. |
I'm not even sure what
It appears that the internal address will be interpreted as the number of bytes that should be sent, and the |
I have tried modifying that code in the cpp file based on the PCA9685 datasheet and gotten close. But not there yet. |
I modified the get function this way:
//_i2c->requestFrom((int)_i2caddr, LED0_ON_L + 4 * num, (int)4); byte regAddress = LED0_ON_L + (channel << 2); _i2c->requestFrom((uint8_t)_i2caddr, (uint8_t)4); return retVal; |
hiya @Michele61 would you be interested in submitting this as a PR so we can get it included/fixed :) |
He ladyada, yes you can. |
great, we'll review when you make the PR |
Excuse me ladyada, but i don't know how the create a pull request, after that i have created a repository, where i written the code (https://github.com/Michele61/Adafruit-PWM-Servo-Driver-Library-fixed), what should i do ? |
Use a fork |
I took a look at your code: the OFF moment can be lower or higher than the ON moment and both numbers are 12 bits. |
I rethought this issue. Of course the function can calculate the number of ticks it is ON [0-4096]. But I think this will not suffice as a mirror of setPWM().
So I guess the function should return more information than just the length. Opinions? |
In the above example I calculate phaseBegin and phaseEnd, if the function has to return more information you can define them as a 'struct', in this way you obtain the same information of setPwm(). |
@Michele61, could you (and others) add use examples? |
Use Case, I can't think of one here. I don't think you can get any useful information back, it's not like the pins can be used for reading digital or analog data, not sure what the purpose would be. Click to expand my attempt at reading the code, parent libraries, and chip documentation to find a solutionI'm not sure If I'm following this right... but it seems digging deeper we are calling
so we get between 6 and 66 bytes in the return and input an int for the stop value (I'm assuming that int 4 is ignored in the bool field). Am I reading that right? Seems like this function is not using So the question is how many bytes should be requested from the PCA9685 chip for the relevant information on each pin?
this is my start... needs to adjust the bytes see reference this is a brute force attempt at fixing (again untested) uint8_t Adafruit_PWMServoDriver::getPWM(uint8_t num)
{
_i2c->requestFrom((int)_i2caddr, 16);
if(_i2c->available()<=16)
{
uint8_t X0 = _i2c->read(); // Reads the data from the register0
uint8_t X1 = _i2c->read(); // Reads the data from the register1
uint8_t X2 = _i2c->read(); // Reads the data from the register2
uint8_t X3 = _i2c->read(); // Reads the data from the register3
uint8_t X4 = _i2c->read(); // Reads the data from the register4
uint8_t X5 = _i2c->read(); // Reads the data from the register5
uint8_t X6 = _i2c->read(); // Reads the data from the register6
uint8_t X7 = _i2c->read(); // Reads the data from the register7
uint8_t X8 = _i2c->read(); // Reads the data from the register8
uint8_t X9 = _i2c->read(); // Reads the data from the register9
uint8_t X10 = _i2c->read(); // Reads the data from the register10
uint8_t X11 = _i2c->read(); // Reads the data from the register11
uint8_t X12 = _i2c->read(); // Reads the data from the register12
uint8_t X13 = _i2c->read(); // Reads the data from the register13
uint8_t X14 = _i2c->read(); // Reads the data from the register14
uint8_t X15 = _i2c->read(); // Reads the data from the register15
}
switch (num) {
case 0:
return X0;
break;
case 1:
return X1;
break;
case 2:
return X2;
break;
case 3:
return X3;
break;
case 4:
return X4;
break;
case 5:
return X5;
break;
case 6:
return X6;
break;
case 7:
return X7;
break;
case 8:
return X8;
break;
case 9:
return X9;
break;
case 10:
return X10;
break;
case 11:
return X11;
break;
case 12:
return X12;
break;
case 13:
return X13;
break;
case 14:
return X14;
break;
case 15:
return X15;
break;
} So the question is how many bytes should be requested from the PCA9685 chip for the relevant information on each pin? Is there a better way to do this... or even why are we not just using the uint8_t Adafruit_PWMServoDriver::getPWM(uint8_t registerAddress)
{
uint8_t read8(PCA9685_LED0_ON_L + 4 * registerAddress)
} |
I can imagine some use cases. When writing software for a four legged robot you usually use invert kinematics to calculate the degrees/dutycicles with the given coordinates an actuator should move to. If for error handling or validation you could read out the pwm. Also the InMoov project relies on potentiometers for the arms to read out positions. I read a blog post by the creator that the power consumed by the robot was way too high to get it untethered. Reducing the amount of electronic parts would be a step in that direction. I know a poti is not a big amount of power consumption but it's a start. I have to admit that I am a bit inexperienced in electrical engineering on higher levels so I am open to be schooled ;). I just like to tinker. @Bolukan maybe the function should get split into three functions like getPWMStart(), getPWMEnd() and getPWMLength() with all three taking the pin number as input parameter? |
I agree that knowing the current pwm value of a pin might be use full. However, I can't think of a situation where it wouldn't be better to just store the value on the micro controller after sending it to the pwm board. Reading the values back over the i2c buss is so slow that you would have to be really memory starved to consider it an option, and even then there would probably be several better solutions available. |
Seems to always return 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);
Serial.println("PWM: " + String(pwm.getPWM(0)));
}
delay(500);
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(servonum, 0, pulselen);
Serial.println("PWM: " + String(pwm.getPWM(0))); }
delay(500);
} |
For anyone having this issue, please update this library to latest release and try again. Note you may also need to install this library as it is now a dependency: Closing. Can't recreated. Possibly fixed with BusIO update? Test sketch: #include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("PCA9685 PWM set/get test.");
pwm.begin();
pwm.setPWM(0, 1234, 5678);
Serial.print("ON = "); Serial.println(pwm.getPWM(0, false));
Serial.print("OFF = "); Serial.println(pwm.getPWM(0, true));
}
void loop() {
} |
I realized that I was getting garbage values and so reverted to a very basic code.
`void setup() {
Serial.begin(9600);
Serial.println("8 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(50);
delay(10);
}
void loop() {
if (Serial.available())
pwm.setPWM(0, 0, Serial.parseInt());
delay(2500);
uint8_t pwmout = pwm.getPWM(0);
Serial.println(pwmout);
}`
I have tried just printing out the value and also typecasting it to char.
I am using a MG996R servo.
I just kept getting values like 4, 6, 19, 224 etc.
The text was updated successfully, but these errors were encountered: