Closed kaeverens closed 7 years ago
I think the issue is that you are using asynchronous write commands in the I2C library. These may be overlapping, somehow?
I will try converting your JS to use synchronous calls instead to see if that works out any better
@kaeverens Thanks for reporting the issue!
Switching to synchronous calls would solve the problem, but would block the rest of the program whenever you performed a servo command. Instead, the library should ensure that only one servo command is sent at a time. I've pushed version 4.0.0 (as a beta) to npm. Can you see if it works in all cases? You will need to force the version since it is marked as beta:
npm install pca9685@4.0.0
Thanks - I feel that this /is/ an asynchronous issue, but your fix didn't do the trick.
I've made a small video showing the issue. In it, you see two servos, which first do some small movements individually, and then finally try to do one single thing simultaneously. You can also see your debug statements on the laptop in the video.
https://www.youtube.com/watch?v=4I1nyUG9nlQ&feature=youtu.be
I've attached the script I used to create the movements. bot3.js.zip
Hey, just testing this code on one servo, using a led indicating the power, awesome! But, it stops with max power. I want to know how I can stop one channel so it doesn't use any power? If I set the puls to 0 it is max light any way, how can i fix this? Thanks!
@kaeverens
The new code was supposed to line up the commands separately, but I used the wrong stream operator. Can you try out version 4.0.1?
@Dennislampert
Version 4.0.1 also has two new methods: channelOff
and channelOn
to turn the power completely off or on 100%. These are called automatically by setDutyCycle
if the percent is 0 or lower or 100% or higher.
Thanks - I've tried 4.0.1. It still acts just the same as in the video. I used the new channelOff/On functions as well(thanks) instead of setting pulse range (n, 0, 0), so it's clearer in the debug what's going on, but at this point, I feel this is somehow in the module itself.
Latest debug:
pca9685 Reseting PCA9685 +0ms
pca9685 Turning off all channels +52ms
pca9685 Setting PWM frequency to 50 Hz +47ms
pca9685 Pre-scale value: 121 +3ms
pca9685 Setting prescale to: 121 +8ms
pca9685 Restarting controller +20ms
pca9685 Setting PWM channel, channel: 1, pulseLength: 1126, onStep: 0 +7ms
pca9685 Setting PWM channel, channel: 1, onStep: 0, offStep: 230 +3ms
pca9685 Turning off channel: 1 +3s
pca9685 Setting PWM channel, channel: 1, pulseLength: 1875, onStep: 0 +502ms
pca9685 Setting PWM channel, channel: 1, onStep: 0, offStep: 383 +2ms
pca9685 Turning off channel: 1 +3s
pca9685 Setting PWM channel, channel: 1, pulseLength: 1126, onStep: 0 +500ms
pca9685 Setting PWM channel, channel: 1, onStep: 0, offStep: 230 +1ms
pca9685 Turning off channel: 1 +3s
pca9685 Setting PWM channel, channel: 8, pulseLength: 1126, onStep: 0 +498ms
pca9685 Setting PWM channel, channel: 8, onStep: 0, offStep: 230 +1ms
pca9685 Turning off channel: 8 +3s
pca9685 Setting PWM channel, channel: 8, pulseLength: 1875, onStep: 0 +497ms
pca9685 Setting PWM channel, channel: 8, onStep: 0, offStep: 383 +1ms
pca9685 Turning off channel: 8 +3s
pca9685 Setting PWM channel, channel: 8, pulseLength: 1126, onStep: 0 +499ms
pca9685 Setting PWM channel, channel: 8, onStep: 0, offStep: 230 +2ms
pca9685 Turning off channel: 8 +3s
pca9685 Setting PWM channel, channel: 1, pulseLength: 1875, onStep: 0 +500ms
pca9685 Setting PWM channel, channel: 1, onStep: 0, offStep: 383 +1ms
pca9685 Setting PWM channel, channel: 8, pulseLength: 1875, onStep: 0 +2ms
pca9685 Setting PWM channel, channel: 8, onStep: 0, offStep: 383 +2ms
pca9685 Turning off channel: 1 +3s
pca9685 Turning off channel: 8 +1ms
pca9685 Setting PWM channel, channel: 1, pulseLength: 1500, onStep: 0 +501ms
pca9685 Setting PWM channel, channel: 1, onStep: 0, offStep: 306 +1ms
pca9685 Setting PWM channel, channel: 8, pulseLength: 1500, onStep: 0 +1ms
pca9685 Setting PWM channel, channel: 8, onStep: 0, offStep: 306 +1ms
pca9685 Turning off channel: 1 +3s
pca9685 Turning off channel: 8 +2ms
one thing to add - at the end, channel 1 stays on, holding its position (and buzzing loudly...), even though you can see clearly that I've used the channelOff to turn 1 off.
I'll give Adafruit's C library a try after work today to see if it works any better for me. If so, then the only difference I can see is that Adafruit's library sets the bytes as one block, whereas your code sets them in separate i2c commands. https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/blob/master/Adafruit_PWMServoDriver.cpp
This can be achieved in your own code by using the I2C writeI2cBlock function, but there is little reason to make the change if this issue is only affecting me and it eventually turns out not to be a software issue after all.
@kaeverens
I attempted to reproduce your error at home with two servos and couldn't. Did the error you show in the video happen every time for you? I was running on a Beaglebone Black with node 0.10. What board and node version are you using?
In the meantime, I've tried switching to writeI2cBlock
for 4.0.2
so we can see if that works better. Can you try it to see if that works now?
it happens every time.
I'm using a CHIP. node v6.6.0
I'll update the pca9685 package now and try again.
with 4.0.2, nothing happens with the servos at all. the usual debug messages appear, but nothing physical happens.
I went back to 4.0.1 and tried again and it started up again.
one new thing I noticed that suggests maybe this is hardware - at the end of the sequence of moves, the turret servo (servo 1, say) started turning continuously, which then started twisting the cables of servo 2. I pulled servo 2 from the PCA9685, and servo1 suddenly stopped turning.
so I tried something I don't remember trying (although it seems so obvious...) - try running the entire sequence with just one servo plugged in. it worked perfectly. the servo did what it was supposed to do, even in the part where two servos were supposed to be simultaneously active. I tried with the other servo, and it too performed as it was supposed to.
I think this is no longer a software issue!
I can confirm from testing 4.0.1:
Above 100% (eg duty cycle = 1.1) The servo dies, but led's is running on max light and debug says:
pca9685 Setting PWM channel, channel: 3, dutyCycle: %f, onStep: 1.3 +319ms 0
pca9685 Turning on channel: 3 +1ms
pca9685 Setting PWM channel, channel: 3, dutyCycle: %f, onStep: 1.35 +2s 0
pca9685 Turning on channel: 3 +1ms
0% or less (eg duty cycle = 0 or -5) The servo dies and the led dies and debug says:
pca9685 Setting PWM channel, channel: 1, dutyCycle: %f, onStep: 0 +14s
pca9685 Turning off channel: 1 +0ms
pca9685 Setting PWM channel, channel: 1, dutyCycle: %f, onStep: -0.05 +25ms 0
pca9685 Turning off channel: 1 +0ms
Just wanted to share my debug result.
This is super good for me and solves my problem to turn one channel down completely!
Thanks alot! :+1:
@kaeverens @Dennislampert Thanks for testing!
Tonight I will revert to the methods used in 4.0.1
and will tidy up everything before a final release. In the meantime, I've unpublished 4.0.2
and re-tagged 4.0.1
as a beta version.
@kaeverens That is unusual that one servo affects the other. Have you tried different servo ports?
@Dennislampert There is something wrong with the debug message, though. That %f
should hold the duty cycle value.
problem solved. It turns out this was a hardware issue after all.
If I understand it right, it's like this: Having multiple servos running simultaneously causes problems because the current going through the servos cause the ground to rise momentarily. This causes the pulses to the servos to become less distinct, making the servos act erratically.
The solution was to make the grounding more solid. I had been grounding through a breadboard, but that's apparently to be avoided (not sure why yet), so I switched my wires so the PCA9685 was grounding through the Chip.
I think we can close this now. I learned a lot, and I hope I helped improve your library even if it was not broken in the first place!
my setup: servo on channel 0, controls a turret on a model tank servo on channel 8, controls the elevation of the cannon
When I run the below code with staggered timeout offsets (offset1=2000, offset2=4000), it all works perfectly. But if I run with the /same/ offsets (4000 for both, for example), the servos appear to lose track of what they were doing.
I'm not familiar with TypeScript, so am not certain I'll find anything in your code, but what it /appears/ to be is a variable from one servo's controller has been set with global scope and is being referenced by the other servo's controller by accident.