Io60p16 and multiple servos

I have a io60p16 board and 2 servos hooked into it. I can move the servos but if I have more than one in the code running, the state is forgotten and then I can move them with my thumb rather than the servo fighting to keep its state. If I comment out the SetServo with the _tilt, the pan servo updates and remembers state. If I use a phidget board, I can have multiple servos just fine.

Code is pretty simple.


private ModulePWM _pan;
private ModulePWM _tilt;

void ProgramStarted()
{
    Debug.Print("Program Started");
            
    var timer = new GT.Timer(100);

    timer.Tick += TimerTick;
    timer.Start();

    _pan = io60p16.CreatePwm(PwmPin.Pwm0, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);
    _tilt = io60p16.CreatePwm(PwmPin.Pwm1, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);
}

private double _x;
private double _y;

void TimerTick(GT.Timer timer)
{
    if (_pan == null || _tilt == null)
        return;

    var position = joystick.GetJoystickPosition();

    SetServo(position.X, ref _x, _pan);
    SetServo(position.Y, ref _y, _tilt);
}

private static void SetServo(double position, ref double state, ModulePWM servo)
{
    // attempting to reduce jittering
    if (Math.Abs(state - position) > 0.003)
    {
        state = position;
        servo.Duration = (uint)((1100 + state * 800) * 1000);
        servo.Start();
    }
}

Not sure about the io board as I don’t have one but with regular pwm you would start them after declaring them and not everytime you set the frequency.

@ crutkas - check this thread
http://www.tinyclr.com/forum/topic?id=8542

@ Justin - declaring then starting without doing a start after the duration update doesn’t cause an update

@ dobova - can you provide what I should be doing. looking at that post, it isn’t screaming “this is what you should do” Switching to SetPwm still causes it to happen where I can physically adjust the servo with just my thumb.


void ProgramStarted()
        {
            Debug.Print("Program Started");
            
            var timer = new GT.Timer(10);

            timer.Tick += TimerTick;
            timer.Start();

            _pan = io60p16.CreatePwm(PwmPin.Pwm0, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);
            _tilt = io60p16.CreatePwm(PwmPin.Pwm1, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);

            _pan.Start();
            _tilt.Start();
        }

        private double _x;
        private double _y;

        void TimerTick(GT.Timer timer)
        {
            if (_pan == null || _tilt == null)
                return;

            var position = joystick.GetJoystickPosition();

            SetServo(position.X, ref _x, _pan, 0);
            SetServo(position.Y, ref _y, _tilt, 1);
        }

private void SetServo(double position, ref double state, ModulePWM servo, byte pin)
{
    // attempting to reduce jittering
    if (Math.Abs(state - position) > 0.003)
    {
        state = position;
        servo.Duration = (uint)((1100 + state * 800) * 1000);
        servo.SetPwm(6, pin, 20 * 1000 * 1000, (uint)((1100 + state * 800) * 1000));
        //servo.Start();
    }
}

Looks like we need to revisit this driver. We did some testing on it but I am seeing multiple posts with issues so we are not sure if it is user error or driver has a problem.

How are you powering up your servos? Can you please post a picture? I am mainly concerned on how the servo is powered.

They are under a 5v 4A power supply. Plugged into the V+ and the Ground.

Here is where we just viewed the pin under an oscilloscope.

If I only do one servo, the servo holds, as soon as you introduce multiple servos then stuff starts acting up.

Hmmm… I never tried multiple servos at the same time during our tests. Try the same thing but with the servos on different ports and see if you get the same result.

@ ianlee74 - explain different port? You mean the other side with the pins 9-16? I need to support 8 servos total.

What I did was a basic use case that someone would do with the module.

I’ve used many weeks ago 2 servo on same port 7 and I didn’t face this problem for what I remember. So this need better further testing.

Here you can see it in action.
http://www.tinyclr.com/forum/topic?id=6860&page=23

@ dobova - did you apply load to the servo? Can you provide the source much like I did so I can see if I’m doing something wrong?

I can move my servos just fine, it is when you apply load on them that they fail. More so, moving them fast I noticed what I would call “incomplete” movements where they should have gone to a certain position but they didn’t.

When it was hooked up to the oscilloscope, that kind of make me go, something is bad is going on here.

Yes. That’s what I meant. I was just trying to narrow down the possible problems. If you could run them fine on different ports then that helps us narrow down the possibilities.

What power source are you providing to the V+ pin?

I don’t know what power source you’re using, but when I see that they work fine with no load and then “fail” under load, it seems to me your power supply can’t provide enough current to the servo - your stall current on the servo is exceeding what the power supply can reliably offer and it causes the other weird behaviour.

Are you sure these servos are okay with 5v? Some servos need 6v.

I beg your pardon cructas but I didn’t undertand your problem, so I was thinking something related to the driver. I haven’t loaded the servos except with my fingers. I’m using a Meanwell power supply like yours and it’s good enough for 5V so I don’t think is ps problem.
But take care of this:

  • the PWM period need to be 20ms minimum and dutycycle from 10% to 20% (1ms to 2ms). This is not always true, you need to check docs about your specific servos.
  • As Gus stated, servos are not always 5V, they may need 6V.
  • It seems stupid but may be wires connecting ps and board V+ may not be enough to support starving current.
  • Using the scope you can check if voltage is dropping down with load.

I don’t think this is software related problem, except if the servo let drain current on PWM wire for some strange reason when under load.

Power only to the V+, not to 5v. I switched to the 5v power supply from a 6v since I was afraid they may be not getting enough amps to operate when I was using a 6v PS.

This works just fine with a single servo, as soon as the code was increased to two servos, you start seeing the jumping and load issue. Hooking up an oscilloscope (see the picture) with the first set of code in this post, you see the jump in the signal. That is with zero load. Ignore the fact I’m using servos. The signal is not constant when it should be.

@ dobova, can you provide a source sample that I can try? I based my code off a post. Have you tried your stuff with what is currently released as your post was 2 months ago.

Lets take a step back, what can i do to provide you guys with a proper repo? Right now I’m getting frustrated as I have an extremely simple thing I want to get done and it isn’t working properly.

Are these assupmtions correct?

[ul]power to V+ and Ground to the side I with the servos will be.[/ul]

For basic code for a single servo:

var servo = io60p16.CreatePwm(PwmPin.Pwm0, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);
servo.Duration = (uint)((1500) * 1000);
servo.Start();

For basic sample for multiple servos:

var servo1 = io60p16.CreatePwm(PwmPin.Pwm0, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);
var servo2 = io60p16.CreatePwm(PwmPin.Pwm1, 20 * 1000 * 1000, 1500 * 1000, ModulePWM.ScaleFactor.Nanoseconds, false);

servo1.Duration = (uint)((1500) * 1000);
servo2.Duration = (uint)((1500) * 1000);

servo1.Start();
servo2.Start();

I’ll try setting this up tonight. You may want to try it without using the explicit servo.Duration. In the code that was delivered to GHI, this was not yet implemented and I haven’t seen the final source code that was delivered in the last SDK. So, they may not have finished it. The duration is specified in the constructor. So, just stick with that for now w/o using the .Duration and see if you get different results.

@ Gus

Are those are hardware PWM, or are they software PWM? Curious if it’s an issue of whether or not the framework can support that number of outputs and maintain timing.

@ Clint

Nice to see you here :slight_smile: I don’t have a bunch of servos hanging around, or else I’d try this out as well. Sounds like Ian is going to, though.

Pete

facepalm - oh that Clint.