View unanswered posts | View active topics It is currently Wed Jul 30, 2014 8:17 am






Reply to topic  [ 4 posts ] 
Acceleration Via For Loop 
Author Message
Rookie

Joined: Fri Nov 22, 2013 10:37 am
Posts: 2
Post Acceleration Via For Loop
Hello,

One of our software kids is trying to tweak his drive code so that the motors smoothly accelerate, instead of jumping from value to value. He added several for loops to his code, and now the robot immediately turns backwards and to the right, and continues full on backwards, without any controller input. If anyone could take a look, another few sets of eyes would be welcome, as this is our first year (and we're still pretty new to RobotC).

Thanks!

Coach Ordena

Code:
#pragma config(Hubs,  S1, HTMotor,  none,     none,     none)
#pragma config(Sensor, S1,     ,               sensorI2CMuxController)
#pragma config(Sensor, S2,     HTGYRO,         sensorI2CHiTechnicGyro)
#pragma config(Motor,  mtr_S1_C1_1,     motorD,        tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C1_2,     motorE,        tmotorTetrix, openLoop, reversed)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 int incrementSpeed;

 int PowerL = 0; //variable for joystick power
 int PowerR = 0;
 int increment;
 int joystickprevL;
 int joystickprevR;
 int joystickNewL;
 int joystickNewR;
#include "JoystickDriver.c"
void Getpower()
{
     getJoystickSettings(joystick);
     if (joy1Btn(1) == 1)
     {
        PowerL = 25;
        PowerR = 25;
     }
       if (joy1Btn(2) == 1)
       {
          PowerL = 50;
        PowerR = 50;
       }
       if (joy1Btn(3) == 1)
       {
         PowerL = 75;
        PowerR = 75;
       }
       if (joy1Btn(4) == 1)
       {
          PowerL = 100;
        PowerR = 100;
       }
       if (joy1Btn(5) == 1)
       {
          PowerL = PowerL + 1;
             if (PowerL > 100)
                PowerL = 100;
       }

    if (joy1Btn(7) == 1)
    {
       PowerL = PowerL - 1;
          if (PowerL < 10)
                PowerL = 10;
    }

    if (joy1Btn(6) == 1)
    {
       PowerR = PowerR + 1;
          if (PowerR > 100)
                PowerR =  100;
       }


    if (joy1Btn(8) == 1)
    {
       PowerR = PowerR - 1;
          if (PowerR < 10)
                PowerR =  10;
       }
       int joystickNewL;
       int joystickNewR;
       joystickNewL = joystick.joy1_y1/abs(joystick.joy1_y1);
       joystickNewR = joystick.joy1_y2/abs(joystick.joy1_y2);
}


task main()
{

    incrementSpeed = 1;
    increment = 0;

    eraseDisplay();
   while (true)
   {
      getJoystickSettings(joystick);
      Getpower();
      // Safety for if you switch to quickly from 1 - -1

         if (((joystickprevL != joystickNewL) && ((joystick.joy1_y1 > 20) && (joystick.joy1_y1 < -20))))
   {
      motor[motorE] = 0;
     wait1Msec(25);
   }
         if ((joystickprevR != joystickNewR) && (joystick.joy1_y2 > 20) && (joystick.joy1_y2 < -20))
   {
      motor[motorD] = 0;
      wait1Msec(25);
   }
   // Safety for if you switch to quickly from 1 - -1
      wait1Msec(15);
     eraseDisplay();
      if (joystick.joy1_y2 > 20) //if right joystick is more than deadzone+ rightmotor forwards
      {
         for(int increment=0;increment >= PowerR;increment = increment + incrementSpeed)//increment for acceleration forward
         {
            motor[motorD] = increment;//motor power gets set to current increment value
            if (joystick.joy1_y2 < 20)
               break;
            wait1Msec(1);
        }
      }
      if ( joystick.joy1_y2 < -20)//if right joystick is less than deadzone- rightmotor backwards
      {
         for(int increment = 0;increment <= -PowerR;increment = increment - incrementSpeed)//increment for acceleration backward
         {
            motor[motorD] = increment;//motor power gets set to current increment value
            if (joystick.joy1_y2 > -20)
               break;
            wait1Msec(1);
        }
      }
      if ( joystick.joy1_y1 > 20)//if left joystick is more than deadzone+ Leftmotor Forward
      {
         for(int increment = 0;increment >= PowerL;increment = increment + incrementSpeed)//increment for acceleration forward
         {
            motor[motorE] = increment;//motor power gets set to current increment value
            if (joystick.joy1_y1 < 20)
               break;
            wait1Msec(1);
        }
      }
      if ( joystick.joy1_y1 < -20)//if left joystick is less than deadzone- Leftmotor Backward
      {
         for(int increment = 0;increment <= -PowerL;increment = increment - incrementSpeed)//increment for acceleration backward
         {
            motor[motorE] = increment;//motor power gets set to current increment value
            if (joystick.joy1_y1 > -20)
               break;
            wait1Msec(1);
        }
      }
      if (abs(joystick.joy1_y1) < 20)//if left joystick is more t
      {
         for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for left motor
         {
            motor[motorE] = increment;
         }
      }
     if (abs(joystick.joy1_y2) < 20)
     {
        for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for right motor
         {
            motor[motorD] = increment;
         }

     }
      nxtDisplayBigStringAt(10,20, "%d  %d", PowerL, PowerR);
      int joystickprevL;
      int joystickprevR;
      joystickprevL = joystick.joy1_y1/abs(joystick.joy1_y1);
      joystickprevR = joystick.joy1_y2/abs(joystick.joy1_y2);
   }
}


Fri Nov 22, 2013 10:50 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: Acceleration Via For Loop
I don't really know what the code is trying to do. Without knowing the intention of the code, I still found some issues with it although it may or may not explain your issues.

First, you can remove the getJoystickSettings(joystick) call in GetPower. You already called that in task main before calling GetPower. There is no reason to call it again inside GetPower. This is an efficiency thing, so it doesn't really fix anything.

Secondly, you have declared joystickNewL and joystickNewR as global variables but yet they were declared again as local variables at the end of GetPower. I would assume you meant to set the global variables. So you need to remove the local variable declarations.
Same thing for joystickprevL and joystickprevR. There are declared as global variables as well as local variables at the end of task main. I would assume you need to remove the local declarations in task main. Also, instead of reading the joystick values again to set joystickprevL and joystickprevR, you can simply:
Code:
joystickprevL = joystickNewL;
joystickprevR = joystickNewR;

Here are some comments embedded in your code.
Code:
#pragma config(Hubs,  S1, HTMotor,  none,     none,     none)
#pragma config(Sensor, S1,     ,               sensorI2CMuxController)
#pragma config(Sensor, S2,     HTGYRO,         sensorI2CHiTechnicGyro)
#pragma config(Motor,  mtr_S1_C1_1,     motorD,        tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C1_2,     motorE,        tmotorTetrix, openLoop, reversed)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

int incrementSpeed;
int PowerL = 0; //variable for joystick power
int PowerR = 0;
int increment;
int joystickprevL;
int joystickprevR;
int joystickNewL;
int joystickNewR;

#include "JoystickDriver.c"

void Getpower()
{
     // MHTS: changed if's to else if's to prevent the scenarios where multiple
     //       buttons are pressed at the same time.
     if (joy1Btn(1) == 1)
     {
        PowerL = 25;
        PowerR = 25;
     }
     else if (joy1Btn(2) == 1)
     {
        PowerL = 50;
        PowerR = 50;
     }
     else if (joy1Btn(3) == 1)
     {
        PowerL = 75;
        PowerR = 75;
     }
     else if (joy1Btn(4) == 1)
     {
        PowerL = 100;
        PowerR = 100;
     }
     else if (joy1Btn(5) == 1)
     {
        PowerL = PowerL + 1;
        if (PowerL > 100)
            PowerL = 100;
     }
     else if (joy1Btn(7) == 1)
     {
        PowerL = PowerL - 1;
        if (PowerL < 10)
            PowerL = 10;
     }
     else if (joy1Btn(6) == 1)
     {
        PowerR = PowerR + 1;
        if (PowerR > 100)
            PowerR =  100;
     }
     else if (joy1Btn(8) == 1)
     {
        PowerR = PowerR - 1;
        if (PowerR < 10)
            PowerR =  10;
     }
     joystickNewL = joystick.joy1_y1/abs(joystick.joy1_y1);
     joystickNewR = joystick.joy1_y2/abs(joystick.joy1_y2);
}

task main()
{
   incrementSpeed = 1;
   increment = 0;

   eraseDisplay();
   while (true)
   {
      getJoystickSettings(joystick);
      Getpower();
      // Safety for if you switch to quickly from 1 - -1
      if (((joystickprevL != joystickNewL) && ((joystick.joy1_y1 > 20) && (joystick.joy1_y1 < -20))))
      {
         // MHTS: when joystickL changes direction abruptly, stop the left motor. Why??? That's very abrupt too.
         motor[motorE] = 0;
         wait1Msec(25);
      }
      if ((joystickprevR != joystickNewR) && (joystick.joy1_y2 > 20) && (joystick.joy1_y2 < -20))
      {
         // MHTS: when joystickR changes direction abruptly, stop the right motor. Why??? That's very abrupt too.
         motor[motorD] = 0;
         wait1Msec(25);
      }
      // Safety for if you switch to quickly from 1 - -1
      wait1Msec(15);

      // MHTS: If you are erasing the display inside the loop,
      //       you will not see anything displayed on the LCD?!
      eraseDisplay();

      // MHTS: Although I don't know what you are trying to do, the following
      //       logic seems wrong. You are ramping up speed on the right wheel
      //       then the left wheel one after the other. Think about this for
      //       a minute. It means the right wheel will move while the left
      //       wheel is stationary. The robot will turn left. Then you start
      //       ramping up the left wheel, so the robot will start straightening
      //       out. That's probably the issue you described.
      if (joystick.joy1_y2 > 20) //if right joystick is more than deadzone+ rightmotor forwards
      {
         // MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
         //       I'd bet you meant increment <= PowerR
         for(int increment=0;increment >= PowerR;increment = increment + incrementSpeed)//increment for acceleration forward
         {
            motor[motorD] = increment;//motor power gets set to current increment value
            // MHTS: The following line is always false, so I don't know what the purpose is.
            if (joystick.joy1_y2 < 20)
               break;
            wait1Msec(1);
         }
      }
      if ( joystick.joy1_y2 < -20)//if right joystick is less than deadzone- rightmotor backwards
      {
         // MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
         //       I'd bet you meant increment >= -PowerR
         for(int increment = 0;increment <= -PowerR;increment = increment - incrementSpeed)//increment for acceleration backward
         {
            motor[motorD] = increment;//motor power gets set to current increment value
            // MHTS: The following line is always false, so I don't know what the purpose is.
            if (joystick.joy1_y2 > -20)
               break;
            wait1Msec(1);
         }
      }

      if ( joystick.joy1_y1 > 20)//if left joystick is more than deadzone+ Leftmotor Forward
      {
         // MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
         //       I'd bet you meant increment <= PowerL
         for(int increment = 0;increment >= PowerL;increment = increment + incrementSpeed)//increment for acceleration forward
         {
            motor[motorE] = increment;//motor power gets set to current increment value
            // MHTS: The following line is always false, so I don't know what the purpose is.
            if (joystick.joy1_y1 < 20)
               break;
            wait1Msec(1);
         }
      }
      if ( joystick.joy1_y1 < -20)//if left joystick is less than deadzone- Leftmotor Backward
      {
         // MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
         //       I'd bet you meant increment >= -PowerR
         for(int increment = 0;increment <= -PowerL;increment = increment - incrementSpeed)//increment for acceleration backward
         {
            motor[motorE] = increment;//motor power gets set to current increment value
            // MHTS: The following line is always false, so I don't know what the purpose is.
            if (joystick.joy1_y1 > -20)
               break;
            wait1Msec(1);
         }
      }

      // MHTS: Again, I could guess what you are trying to do but the logic below seems wrong.
      //       I don't think this will work, so I am not going to attempt any fix.
      if (abs(joystick.joy1_y1) < 20)//if left joystick is more t
      {
         for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for left motor
         {
            motor[motorE] = increment;
         }
      }
      if (abs(joystick.joy1_y2) < 20)
      {
        for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for right motor
         {
            motor[motorD] = increment;
         }

      }
      nxtDisplayBigStringAt(10,20, "%d  %d", PowerL, PowerR);
      joystickprevL = joystickNewL;
      joystickprevR = joystickNewR;
   }
}

I don't think the above code will work as you intended. It may be better to rewrite it. Before you do that, you need to define the exact problem you want to solve and lay out the exact behaviors for different scenarios. Once you have the pseudo code down, it's a lot easier to translate into real code.


Fri Nov 22, 2013 4:08 pm
Profile
Rookie

Joined: Fri Nov 22, 2013 10:37 am
Posts: 2
Post Re: Acceleration Via For Loop
The intention was to provide a means of acceleration, instead of ramping straight up to a speed. Thanks for all the comments.

Addressing edits as I see them -

Direction reversal: we smoked a few motors with kids driving the bot around on full power doing abrupt forward -> reverse changes, so we built in a quick stop so the motors had a little time to recuperate. So far, we haven't smoked any more.

For loop fiasco: Okay, so those run one at a time. Would the best way to provide smoother acceleration be to use ands to have them both test at once? Or are will the motors naturally build themselves up to their given speed?

Quote:
// MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
// I'd bet you meant increment <= PowerR
for(int increment=0;increment >= PowerR;increment = increment + incrementSpeed)//increment for acceleration forward
{


Okay, so for loops. That first thing is the initial, so we start with this thing called increment. It equals 0. The second thing seems like the thing we're having issues with.

Is arg 2 a "run while this is true" or is it a "run until this is true"? The idea here (I think) was to build up the speeds on the motors (again, I don't know if the motors require it or not, we're just trying to give our rookie Drive team as much help as we can) gradually, so they don't jolt up and down speeds.

The lines that are always False are intended to break out of the accel loops if the joystick is no longer being pushed in that direction.

Quote:
if (abs(joystick.joy1_y1) < 20)//if left joystick is more t
{
for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for left motor
{
motor[motorE] = increment;
}
}
if (abs(joystick.joy1_y2) < 20)
{
for (int increment=increment;increment <= 0;increment = increment - (incrementSpeed * 2))//increment down to 0 for right motor
{
motor[motorD] = increment;
}


This part is a modification of our dead zone. We have a dead zone in the center of the joysticks, so the motors don't get erroneous input. The deadzone is the values inbetween -20 and 20, so he said if the absolute value of the joystick was under 20, set it to 0, so it doesn't move by accident. The part that's all strange is the part where he wanted it to decelerate to a stop.

So we may just table this and bring it back to the drawing board. Or it might not be necessary. Plan is to accelerate motors up to inputted speed, instead of having them directly jump. Is this necessary?


Fri Nov 22, 2013 4:23 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: Acceleration Via For Loop
Coach Ordena wrote:
The intention was to provide a means of acceleration, instead of ramping straight up to a speed. Thanks for all the comments.

Addressing edits as I see them -

Direction reversal: we smoked a few motors with kids driving the bot around on full power doing abrupt forward -> reverse changes, so we built in a quick stop so the motors had a little time to recuperate. So far, we haven't smoked any more.

Tetrix are relatively weak motors comparing to the CIM motors used in FRC with respect to the current draw during reversal. We never have any problems "smoking" them when doing direction reversal. Personally, I don't think it's necessary unless you have an extremely heavy robot which makes a reversal seems like a stall situation. In a stall situation, the Tetrix motors do get fried easily. I think the logic in the code is too complex. Have you considered simpler strategies? For example, what if you apply a "low pass" filter either on the joystick input or the motor power output so that a sudden change will translate to a slower response? In that case, you don't even have to do anything special everywhere. For example:
Code:
#define DEADBAND(n)    ((abs(n) < 20)? 0: (n))

int GetJoystickValue(int currValue, int prevValue)
{
    return 0.4*DEADBAND(currValue) + 0.6*prevValue;
    return output;
}

task main()
{
    int joy1Y1 = 0;
    int joy1Y2 = 0;

    while (true)
    {
        joy1Y1 = GetJoystickValue(joystick.joy1_y1, joy1Y1);
        joy1Y2 = GetJoystickValue(joystick.joy1_y2, joy1Y2);
        ....
    }
}

You can control how responsive the output is by changing the proportion from 40%/60% to say 50%/50% or 70%/30%. The more percentage you give to "prevValue", the slower the response will be.
Coach Ordena wrote:
Quote:
// MHTS: Not that I agree with the logic as a whole but the comparison below seems backward.
// I'd bet you meant increment <= PowerR
for(int increment=0;increment >= PowerR;increment = increment + incrementSpeed)//increment for acceleration forward
{


Okay, so for loops. That first thing is the initial, so we start with this thing called increment. It equals 0. The second thing seems like the thing we're having issues with.

Is arg 2 a "run while this is true" or is it a "run until this is true"? The idea here (I think) was to build up the speeds on the motors (again, I don't know if the motors require it or not, we're just trying to give our rookie Drive team as much help as we can) gradually, so they don't jolt up and down speeds.

arg 2 is "run while this is true".
Coach Ordena wrote:
The lines that are always False are intended to break out of the accel loops if the joystick is no longer being pushed in that direction.

That doesn't work because the joystick values were not updated so it will never break out of the for-loop.

Like I said, try the "low pass filter" code above and see if it works for you. If it does, you can remove all the complex logic about ramping up and down.


Fri Nov 22, 2013 5:54 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 4 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.