Encoders and gyro

So i have two questions for you people on CD

  1. When we put in our encoder code it stops the robot from driving, why?

here is what we do

Encoder en1;
         DigitalInput *en1a;
         DigitalInput *en1b; 
     
         en1(en1a,en1b);
 
         en1a = new DigitalInput(6);
         enba = new DigitalInput(6);

         en1.Reset();
         printf("encoder =%f
",  encoder.GetDistante());

The second question is this:
When we drive our robot in mecanum drive with the gyro it works ok but a few glitches:
strafe left works
strafe right turns 180 degrees and then strafes left…
rotation dosent really rotate just swings the back end of the robot left or right…

any ideas?

Your creation of the encoder is kind of scrambled, you don’t need to create Digital Inputs for the Encoder, the Encoder class understands DIs already.

Here’s a complete robot program with an encoder. It has limit switches and a pot used for limits as well. I wrote it for the WRRF pre-season worshops here in the Silicon Valley and it still has the Watchdog in it.


/* Demo program for WRRF workshops Dec 11, 2010. Basic cRIO C++ program for driving
** and controlling one arm, and an extendable boom. This robot has four motors:
** There is one drive motor per side (left and right), one motor for raising the arm,
** and one motor for extending/retracting the boom.
**
** Each motor is controlled by a "Victor" motor controller. These controllers take 
** instructions from our program, running on the cRIO, and drive the motors fast and
** slow as well as reversing the direction of the motor. "Jaguars" are the newer version
** of the motor controllers, and we could have used them. This robot is from the 2005 FRC
** game "Triple Threat" and it still has Victors.
** 
** Our program will take its inputs from the two joysticks and drive the four motors
** accordingly. One joystick controls the wheel motors (left and right). The joystick works
** in Arcade style, Y deflection makes the 'bot go forwards/backwards, X deflection makes the
** robot turn.
**
** Y deflection of the arm joysick controls the arm motor to move the arm up and down. It's 
** hinged at its base and the motor actually turns a winch to lift the far end of the
** boom up. As the winch unwinds, gravity pulls the arm back down. A potentiometer at the
** hinge turns as the arm angle increases and decreases, telling us the angle of the arm.
** Pots are analog devices (give a continuously variable value, like a volume control
** knob, or the temperature knob of an oven.)
**
** X deflection of the arm joystick extends and retracts the boom, which is inside the
** arm. The boom motor is fitted to a garage-door jackscrew and it's used to
** extend and retract the arm. At the base of the arm there's a mechanical switch that
** is pushed as the boom comes close to the end of its mechanical travel. There's an
** optical sensor(swtich) that detects when the boom is extended to the limit.
** These switches are digital devices: they are either on or off.
**
** Our program has to take input from ("read") the pot and the switches and turn off the 
** motors before the arm/boom extend past the end of their mechanical travel. If the
** program didn't do this the motors would keep going and the robot would be damaged
** and/or the motors overloaded, blow their fuse or overheat and be damaged.
**
** All four motors are controlled by PWM (Pulse-Width Modulation) outputs from the cRIO.
** You don't need to know what PWM really means, just that each motor has its own PWM
** output.
**
** There are several analog inputs, digital inputs, and PWM outputs available on the
** cRIO, and each is numbered. 
*/

/* these are the various constants used in the program. They are all here, as #defines,
** so they can be easily found, identified, and changed as necessary.
** #defines are simple. The compiler (on WindRiver Workbench) sees the text and substitutes
** the number. For example, "DRIVE_JOYSTICK" that appears in the program causes a "1" to
** be substituted in its place - simple as that.
*/

/* you can tell which joystick is which: on the Drivers Station, click on Setup, and
** watch "Joystick Setup" as you pull the trigger(s) of the Joysticks. You can drag the
** order of the JS(s).
*/

#define DRIVE_JOYSTICK 1 // the joysticks are numbered by the Classmate Drivers station.
#define ARM_JOYSTICK   2 // assignments can be seen with the Drivers Station "Setup" tab.

#define LEFT_MOTOR_PWM      2
#define RIGHT_MOTOR_PWM     3 
#define ARM_WINCH_MOTOR_PWM 5
#define BOOM_MOTOR_PWM      6

// identifiers for the sensors.
// boom limit switches are wired to Digital Inputs:

#define BOOM_LIMIT_SWITCH_DI_LOW 10
#define BOOM_LIMIT_SWITCH_DI_HIGH 2

// encoder digital inputs:

#define ENCODER_DI_A 8
#define ENCODER_DI_B 9
#define ENCODER_RESET_BUTTON 2


// Potentiometers ("pots") are wired to Analog Inputs:
#define ARM_POT_ANALOG_IN         3

#define ARM_POT_LIMIT_HIGH  950
#define ARM_POT_LIMIT_LOW   790
#define ARM_SLOW_RATIO      0.5

// how many loops pass between our debug prints:
#define PRINT_COUNT 10000 

#define AUTON_DRIVE_SPEED  -0.5 // half speed
#define AUTON_TURN   0.0 // no turn, go straight 
#define AUTON_ARM_DOWN_SPEED -0.5 // negative for down

#include "WPILib.h"

class RobotDemo : public SimpleRobot
  {

  RobotDrive *myRobot; // WPILib has given us easy-to-use drive software system.

  Joystick *drive_stick; // this joystick will control the driving
  Joystick *arm_stick; // Y deflection will raise the arm up and down, X deflection
  // will extend/retract the boom.

  Victor *arm_motor, *boom_motor;

  AnalogChannel *arm_pot;

  DigitalInput *boom_limit_retract, *boom_limit_extend;

  Encoder *koder;

public:
  RobotDemo(void)
    {

      // Create the WPILib robot drive software subsystem:
      myRobot = new RobotDrive(LEFT_MOTOR_PWM, RIGHT_MOTOR_PWM);

      /* these statemets tell RobotDrive if the direction of the motor(s)
       ** need to be reversed in order to make the robot drive properly.
       ** The direction of the motor turning depends on how they are geared
       ** and wired.
       */

      myRobot->SetInvertedMotor(RobotDrive::kFrontLeftMotor, false);
      myRobot->SetInvertedMotor(RobotDrive::kFrontRightMotor, false);

      // the following turn out to be our two motors. We just changed the "false" to "true"
      // one by one and watched how the motors turned, to find this out. Leaving the
      // above two statements in doesn't hurt anything.

      myRobot->SetInvertedMotor(RobotDrive::kRearLeftMotor, true);
      myRobot->SetInvertedMotor(RobotDrive::kRearRightMotor, true);

      drive_stick = new Joystick(DRIVE_JOYSTICK);
      arm_stick = new Joystick(ARM_JOYSTICK);

      arm_motor = new Victor(ARM_WINCH_MOTOR_PWM); // + moves it up
      boom_motor = new Victor(BOOM_MOTOR_PWM); // + pulls it in

      arm_pot = new AnalogChannel(ARM_POT_ANALOG_IN); // 950 at top, 
      // 790 at bottom

      boom_limit_retract = new DigitalInput(BOOM_LIMIT_SWITCH_DI_LOW);
      boom_limit_extend = new DigitalInput(BOOM_LIMIT_SWITCH_DI_HIGH);

      koder = new Encoder(ENCODER_DI_A,ENCODER_DI_B,false,Encoder::k4X);

      /* the Watchdog is easy to understand after you understand the rest of the program.
       ** it's hard to explain without that understanding. It's explained at the very
       ** end of the program. Please ignore it for now.
       */
      GetWatchdog().SetExpiration(0.5);
    } // end of RobotDemo()


  void Autonomous(void)
    {

      GetWatchdog().SetEnabled(false); // don't use WD in Autonomous.

      myRobot->Drive(AUTON_DRIVE_SPEED, AUTON_TURN);
      Wait(1.0); // drive 1 second
      myRobot->Drive(0.0, 0.0); // then stop

      // if the arm isn't lowered, lower it:

      if (arm_pot->GetValue() > ARM_POT_LIMIT_LOW)
        { // arm isn't all the way down, lower it

          arm_motor->Set(AUTON_ARM_DOWN_SPEED);

          while ((arm_pot->GetValue() > ARM_POT_LIMIT_LOW) && IsAutonomous())
            ; // loop here over and over 'till arm
          // pot reads <= ARM_POT_LIMIT_DOWN
          // or auton ends, whichever comes first!

          arm_motor->Set(0.0); // then stop arm

        } // arm wasn't all the way down

    } // Auton
    /* The above code avoids the problem of failure of lowering
     ** the arm. The loop will continue as long as the auton
     ** mode is running. When auton mode ends, IsAutonomous()
     ** returns false, and that ends the while() loop
     ** regardless of the reading of the pot.
     */
  void OperatorControl(void)

    {
      int print_counter=0;
      float arm_drive, boom_drive;
      int arm_pot_value;
      int koder_value, koder_value_raw;

      koder->Start();

      // please ignore the Watchdog for now.

      GetWatchdog().SetEnabled(true);

      // keep repeating the Teleop loop for the time (2 minutes so far) of the match:

      while (IsOperatorControl())
        {
          GetWatchdog().Feed();

#if 0

          // this is test code to help explain how the watchdog works. it's only for a demo,
          // it NEVER should go in regular (match) code. The "#if 0" above disables the code.
          // change the 0 to a 1 to enable it.

          while (drive_stick->GetTrigger())
          ; // do nothing really fast!

#endif
          myRobot->ArcadeDrive(drive_stick);

          /*================================== arm winch drive ==========================*/
          // JS Y-value forwards is NEGATIVE, not what you'd expect.
          // JS X value left is NEGATIVE too.
          
          arm_drive = arm_stick->GetY(); // Y deflection raises and lowers arm

 /* if the arm stick trigger is pulled, slow down the
  ** arm motor to give the driver finer control.
  */
          if (arm_stick->GetTrigger())
            {
              arm_drive = arm_drive * ARM_SLOW_RATIO;
            }
          
/* the pot tells us if we've reached the arm's limits
** (the end of its mechanical travel), we have to stop
** the arm from moving if so, otherwise the
** robot or motor will be damaged.
*/
          arm_pot_value = arm_pot->GetValue();

          // if winch is at bottom, keep it from going lower 
          if ((arm_pot_value < ARM_POT_LIMIT_LOW) && (arm_drive < 0))
            {
              arm_drive=0;
            }

          // or at top, stop it from going up
          if ((arm_pot_value > ARM_POT_LIMIT_HIGH)&& (arm_drive > 0))
            {
              arm_drive=0;
            }

          arm_motor->Set(arm_drive); // + pulls arm up


          /* ================================ boom drive ==========================*/

          boom_drive = arm_stick->GetX();

          // we must stop the boom motor at the ends of its
          // mechanical travel, just as we do with the winch:

          // note the "!" below, this means "NOT"

          if ( ((!boom_limit_extend->Get()) && (boom_drive < 0)) // boom extended AND
              // JS says extend?
              || // OR

              ((!boom_limit_retract->Get()) && (boom_drive > 0)) // boom retracted AND                                                                     // JS says retract?
          // JS says retract?
          )

            {
              boom_drive = 0; // if any of these, stop boom motor
            }

          boom_motor->Set(boom_drive);
          
/* If button is pressed on the arm_stick, reset the
 ** encoder to 0. More likely our program would reset
 ** the enoder before it started a drive or turn, 
 ** but this is how you read a joystick button by
 ** the number printed on the button.
 */
          
          if (arm_stick->GetRawButton(ENCODER_RESET_BUTTON))
            
            {
              koder->Reset();
            }

          koder_value = koder->Get();
          koder_value_raw= koder->GetRaw();

          // change the 0 to a 1 below to enable debug printfs. THESE MUST BE DISABLED IN NORMAL
          // OPERATION AND IN COMPETITION!! They slow down execution!

#if 0
          print_counter=print_counter+1;

          if (print_counter > PRINT_COUNT)
            {
              printf("Arm JS y,x; limits, encoders: %f %f %d  %d %d  %d  %d
",
                  arm_stick->GetY(),
                  arm_stick->GetX(),
                  arm_pot->GetValue(),

                  boom_limit_retract->Get(),
                  boom_limit_extend->Get(),

                  koder_value,
                  koder_value_raw);

              print_counter=0;

            } // time to print??

#endif
        } // while
    } // OperatorConrol
  };

START_ROBOT_CLASS(RobotDemo)
;

#if 0

2010 12 09 Complete version! Drive, arm, and boom work and have limits. BOOM LIMIT GOING
UP DOESN'T WORK WELL WHEN PRINTFS ARE ENABLED!!

Made auton more robust
#endif


I know our code is scambled but thanks for the example code

Anyone know about the gyro

Also your code is in java not c++

looks like c++ to me

I’d like to rule out any issues with the hardware before diving into the code. Can you take a picture of your wheels and show us how you have them mounted?

they are not in a perfect square

o=wheel

|----|
o o
| |
| |
o o
|----|

coulde it be the wheels are backwards?

I think he’s asking if the formation of the wheels is correct. There are two kinds, an “X” formation and an “O” formation.

This is the “O” formation. The slash is the angle of the roller that is touching the ground. It will appear the opposite from the top.

++++++
/+++++
++++++
++++++
++++++
+++++/
++++++

This is the “X” formation. If your wheel base was a square in this formation then you wouldn’t be able to spin, but it doesn’t sound like that’s the case.

++++++
+++++/
++++++
++++++
++++++
/+++++
++++++

Make sure your wheels are in one of these two formations.

Another thing to think about is the weight on each wheel. A mecanum drive should have about equal weight on all wheels to maneuver correctly.

EDIT:
Also, you should make sure that your gyro is being reset at the right time. You might want to make a button for manual gyro reset just in case.

We’ll be at the 10,000 lakes regional as well in case you still need help. (assuming our problems are sorted out…)

If the wheels are mounted so the X configuration appears on the bottom, you will encounter 2 issues:

  1. You must change the sign of the strafe command if using the WPILib mec functions, and

  2. The available rotating torque will be dramatically decreased, and it will be easier for an opponent to spin you.

**