You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi there. I opened this as https://github.com/Pi4J/pi4j/issues/540 , but perhaps it's better for discussion. Basically I am trying to disable the PWM for certain channels, when the servos that make up a robot arm I am using, should not longer apply force - the arm is virtually rested, and turning off the servos would make it completely reset in a particular position, while keeping the servos running would have them constantly work against gravity to sustain the arm.
Now, I am using the PCA9685 code that is part of Pi4j 1.3. That of course talks to the I2CDevice and I2CBus. The code to turn off in the library looks like this:
publicvoidsetAlwaysOff(Pinpin) {
...
finalintchannel = pin.getAddress();
try {
device.write(PCA9685A_LED0_ON_L + 4 * channel, (byte) 0x00);
device.write(PCA9685A_LED0_ON_H + 4 * channel, (byte) 0x00);
device.write(PCA9685A_LED0_OFF_L + 4 * channel, (byte) 0x00);
device.write(PCA9685A_LED0_OFF_H + 4 * channel, (byte) 0x10); // set bit 4 to high
} catch (IOExceptione) {
thrownewRuntimeException("Error while trying to set channel [" + channel + "] always OFF.", e);
}
...
}
The effect I am seeing is that in some cases, perhaps one out of ten, or out of fifteen, some of the servos (arm consists of six channels) make a rapid movement to their minimum position instead of just releasing their force, potentially causing damage.
I would like to understand better what causes this, and how I can avoid it. Looking at the above code, the first thing that strikes me is that there seems to be no transaction in which this happens, so unless I am missing something, those four write commands happen one after the other and asynchronous to whatever the chip is doing. If I understand the specs correctly, the only command that is actually needed is to set the 12th bit, i.e. the 4th bit of the high byte of PCA9685A_LED0_OFF_H to 1. Could it be that the preceding writes are causing the problem, so that sometimes, an oscillator cycle completes between the PCA9685A_LED0_OFF_L and the PCA9685A_LED0_OFF_H write, and thus there is a single cycle with minimum duty cycle, causing the servo to jump to minimum position? Or is the problem located elsewhere? Would it help to use the array-write function instead of four individual byte writes? I don't really understand how a linux device file (RandomAccessFile) is used, and if that comes with any form of atomic updates.
I also notice both from the Pi4j code and the specs, that the chip understands a SLEEP mode. Should I perhaps use that instead? As far as I understand, it will also disconnect the internal oscillator, presumably halting any new levels sent to the servos.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi there. I opened this as https://github.com/Pi4J/pi4j/issues/540 , but perhaps it's better for discussion. Basically I am trying to disable the PWM for certain channels, when the servos that make up a robot arm I am using, should not longer apply force - the arm is virtually rested, and turning off the servos would make it completely reset in a particular position, while keeping the servos running would have them constantly work against gravity to sustain the arm.
Now, I am using the PCA9685 code that is part of Pi4j 1.3. That of course talks to the I2CDevice and I2CBus. The code to turn off in the library looks like this:
The effect I am seeing is that in some cases, perhaps one out of ten, or out of fifteen, some of the servos (arm consists of six channels) make a rapid movement to their minimum position instead of just releasing their force, potentially causing damage.
I would like to understand better what causes this, and how I can avoid it. Looking at the above code, the first thing that strikes me is that there seems to be no transaction in which this happens, so unless I am missing something, those four
write
commands happen one after the other and asynchronous to whatever the chip is doing. If I understand the specs correctly, the only command that is actually needed is to set the 12th bit, i.e. the 4th bit of the high byte ofPCA9685A_LED0_OFF_H
to 1. Could it be that the preceding writes are causing the problem, so that sometimes, an oscillator cycle completes between thePCA9685A_LED0_OFF_L
and thePCA9685A_LED0_OFF_H
write, and thus there is a single cycle with minimum duty cycle, causing the servo to jump to minimum position? Or is the problem located elsewhere? Would it help to use the array-write function instead of four individual byte writes? I don't really understand how a linux device file (RandomAccessFile
) is used, and if that comes with any form of atomic updates.I also notice both from the Pi4j code and the specs, that the chip understands a SLEEP mode. Should I perhaps use that instead? As far as I understand, it will also disconnect the internal oscillator, presumably halting any new levels sent to the servos.
Thanks for help!
Beta Was this translation helpful? Give feedback.
All reactions