Search  
Tuesday, January 06, 2009 ..:: Forum ::.. Register  Login
 HomePage Minimize

 Print   

 Products Minimize

 Print   

 MSRS Minimize

 Print   

      
 RoboticsConnection Forum Minimize
SearchForum Home
  Discussions  Serializer Robot Controller  Odd .Net PID mo...
 Odd .Net PID motor problem
 
 11/2/2007 11:36:04 AM
rpg
35 posts


Odd .Net PID motor problem
Hello,

I've got an odd problem when using the Serializer.Net PID motor controller interface in a C# program.  First, everything works fine using a HyperTerm connection to the Serializer.  In particular, I can issue a series of MOGO or DIGO commands and the motors and wheels do exactly the right thing.  However, when I now try to use the TravelDistance(), TravelAtSpeed() or Rotate() commands in a simple C# form, the following occurs.  I have buttons labeled "Left", "Right", "Forward" and "Stop" on the test form.  For example, the event handler for the "Left" button is:

        private void Left_Click(object sender, EventArgs e)
        {
           pidDrive.Speed = 50;
           pidDrive.RotationAngle = -90;
           pidDrive.Rotate();
        }

And for the "Right" button:

        private void Right_Click(object sender, EventArgs e)
        {
            pidDrive.Speed = 50;
            pidDrive.RotationAngle = 90;
            pidDrive.Rotate();
        }

If I now run the program and click "Right" a few times, then click "Left", things work as they should.  However, if I first click "Left", let the rotation complete, then click "Right", the motors rotate left again!  Clicking the "Forward" button also causes the wheels to rotate left again.

I'm guessing there is a problem with the way I am using PumpEvents() but I can't figure it out.  Here now is the entire listing of the test form.  Note that timer1 (for PumpEvents()) fires every 100 ms.  Also, the motors I am using are similar if not identicle to the Traxster motors while the US Digital encoders issue about 6000 ticks per revolution.  My VPID and DPID parameters in the Serializer EEPROM are 10:0:5:5 and 1:0:0:1.  I am using the latest firmware and Serializer.Net library.

Thanks!
patrick

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using RoboticsConnection.Serializer;
using RoboticsConnection.Serializer.Components;
using RoboticsConnection.Serializer.Controllers;
using RoboticsConnection.Serializer.Ids;
using RoboticsConnection.Serializer.Sensors;

namespace TestSerializer
{
    public partial class Form1 : Form
    {
        static Serializer Serializer;
        static PIDMotorController pidDrive;
        delegate void SetRightCallback();
        delegate void SetLeftCallback();

        public Form1()
        {
            InitializeComponent();

            Serializer = new Serializer();

            Serializer.PortName = "COM30";
            Serializer.BaudRate = 19200;

            Serializer.CommunicationStarted += new SerializerEventHandler(serializer_CommunicationStarted);
            Serializer.StartCommunication();
        }

        static void serializer_CommunicationStarted(Serializer sender)
        {
            Console.WriteLine("Communication started");

            pidDrive = new PIDMotorController(Serializer);

            Serializer.Units = Units.English;

            // Set velocity and distance PID parameters:
            pidDrive.VelProportional = 10;
            pidDrive.VelIntegral = 0;
            pidDrive.VelDerivative = 5;
            pidDrive.VelLoop = 5;
            pidDrive.DistProportional = 1;
            pidDrive.DistIntegral = 0;
            pidDrive.DistDerivative = 0;
            pidDrive.DistAcceleration = 1;

            // Set Physical drivetrain configuration parameters.
            pidDrive.EncoderResolution = 5500;
            pidDrive.TicksPerRevolution = 5500;
            pidDrive.GearReduction = 1.0;
            pidDrive.WheelDiameter = 6.25;
            pidDrive.WheelTrack = 12.58;
            pidDrive.VelocityDivider = 0.67;

            pidDrive.Speed = 50;

        }

        private void Forward_Click(object sender, EventArgs e)
        {
            pidDrive.Speed = 50;
            pidDrive.Distance = 30;
            pidDrive.TravelDistance();
        }

        private void Left_Click(object sender, EventArgs e)
        {
           pidDrive.Speed = 50;
           pidDrive.RotationAngle = -90;
           pidDrive.Rotate();
        }

        private void Right_Click(object sender, EventArgs e)
        {
            pidDrive.Speed = 50;
            pidDrive.RotationAngle = 90;
            pidDrive.Rotate();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Serializer.PumpEvents();
        }

        private void StopMotors_Click(object sender, EventArgs e)
        {
            pidDrive.Stop();
        }
    }
}

 11/5/2007 9:05:32 AM
rpg
35 posts


Re: Odd .Net PID motor problem
It just occurred to me to try the PID Controller example code included in the Serializer documentation.  This code does not use a form interface and so provides a simpler test.  Playing with the example code, it appears that one needs to use the Thread.Sleep() function just right to get the desired behavior.  For example, I would have thought that issuing a TravelDistance() command followed immediately by a pair of RotationAngle=X and Rotate() statements would execute the TravelDistance command through completion, then the Rotate() command.  However, if I don't include a Thread.Sleep() call of sufficient duration after the TravelDistance() command, the Rotate() command is not executed at all.  Is this the expected behavior?  If so, is there a less manual way to determine when one PID command has completed?  I don't see any PID events listed in the documentation that might provide this function.

Thanks!
patrick

 11/6/2007 10:36:59 AM
jason
158 posts
5th


Re: Odd .Net PID motor problem

Patrick,

Both TravelDistance() and Rotate() use the DIGO command.  Every time the DIGO command is sent to the Serializer, the firmware will reset the internal PID variables/counts and encoder counts, and start it's counting for the latest DIGO command.

I can see how it would be useful to send a notification back that the PID methods have finished, however, the Serializer would have to block all other communications while the PID stuff finishes.  This wouldn't be good, because you might want to issue a STOP command, or overwrite the current PID job.

We could add a command (e.g. pidstate) that can be sent to query the state of the PID loop, to see if it has finsihed.  The PID algorithms could update an internal variable to 0 when the PID algorithm starts, and set it to 1 when it's finished.  The 'pidstate' command would always return the value of this variable, and then you could poll it to see when it's finished.


Jason Summerour
President,
Summerour Robotics Corp
Microsoft MVP
www.roboticsconnection.com
 11/6/2007 10:56:38 AM
rpg
35 posts


Re: Odd .Net PID motor problem
Hi Jason,

Thanks for the clarification.  The addition of a pidstate command would be very useful--especially for coordinating a series of PID motor actions.  (BTW, the kind of programming you guys do at the lower firmware/API levels is magic to me, so I really appreciate these kinds of efforts!)

In the meantime, were you able to make any sense of the first part of my question?  Namely, that when using my simple form buttons to issue Rotate and Travel commands, the Serializer gets "stuck" in left rotate mode as soon as I rotate through a negative rotation?

Thanks!
patrick



 11/7/2007 9:18:28 AM
rpg
35 posts


Re: Odd .Net PID motor problem
Just in case my PID control problem wasn't clear from my original post, I did some more testing with the following results:  I have a simple form (code posted below) consisting of four buttons, Forward, Reverse, Left and Right.  You can see the PID code attached to each button below.  I am not using PumpEvents() anywhere for this test.

First, here is what works: clicking  "Forward" or "Reverse" (which is the TravelDistance command) always makes the wheels go forward or backward the correct distance in each case.

Things go wrong if I throw in a rotate left or right (not just left as I originally posted).  For example, if I click the sequence Forward, Reverse, Forward, Right, Forward, Right.  The last Right click actually makes the wheels go forward, not right.  Similarly, if I click Forward, Left, Forward, the last click turns the wheels left, not forward.  This kind of behavior is quite repeatable.

Note that when I say "clicks the sequence", I am allowing each action to complete, then waiting a couple seconds just to be safe, then clicking the next button in the sequence.

Finally, here is one perfectly repeatable observation: the right rotate behavior never works a second time if it is followed by any action besides another right rotate (as illustrated in the first example above.)  The only way to get a right rotation working gain is to shutdown the application and start it up again.

--patrick

  Discussions  Serializer Robot Controller  Odd .Net PID mo...

SearchSearch  Forum HomeForum Home    Print   

Copyright 2004-2007 Summerour Robotics Corp   Terms Of Use  Privacy Statement
DotNetNuke® is copyright 2002-2009 by DotNetNuke Corporation