View unanswered posts | View active topics It is currently Sun Aug 19, 2018 7:04 am






Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next
Question for MHTS 
Author Message
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
Sorry, got a little busy with FRC. I did a quick scan of your code. There are a few things I don't understand.
First, what does the Failsafe task do? It looks like it is monitoring button 10 of joystick 1. If pressed and released, it will stop motor H (looks like the lift motor) and restart the Controller2 task. I can't figure out the purpose of it. In any case, since the code does not have too much useful comments so it is hard to figure out what it is trying to do. In general, you are using 5 concurrent tasks (including the main task). Each task has a forever-loop which is fine but in particular, controller1 and controller2 tasks are monitoring the joystick/button activities of the corresponding controllers. In controller1 task, you are calling IRLineUp when button 2 is pressed and MoveForward when button 4 is pressed. Notice that both IRLineUp and MoveForward have while-loops in them. It means when calling IRLineUp, the function won't return until either the ultrasonic sensor reads an obstacle within 23cm or button 3 is pressed. In the mean time, the controller1 task cannot monitor other joystick/button activities while IRLineUp is doing its job. Same thing goes to when controller1 task is calling MoveForward. MoveForward won't return until it finishes the operation. So in the meantime, the controller1 task is ignoring all other joystick/button activities. That caused the "non-responsiveness" you talked about.
Similarly, in the controller2 task, you are calling LiftGoal which contains multiple while loops. That means while you are doing the LiftGoal operation, the controller2 task will ignore everything else until LiftGoal returns. In fact, LiftGoal looks very complicated. I am guessing you are trying to keep the lift in mid-air while you are pressing and releasing button 4 to operate the dumping mechanism.
In general, what you have is a classic multi-tasking problem that is around the question "how do you do multiple operations concurrently and be able to monitor all operations at the same time?". One way to solve it is to use the RobotC "task" for each blocking operation. However, it gets tricky using "task" because RobotC task is preemptive multitasking meaning that the task could be interrupted at unpredictable point and switched to another task. If you don't understand multi-tasking programming, you could get into nasty situations that are hard to debug. In addition, it is very complicated if you need to "synchronize" and communicate between tasks. This is a whole college level class on this subject.
Another way to solve this is to use state machines. You convert each blocking operation to use a state machine so they don't block. A state machine breaks down blocking operations into steps. When the state machine is executing and needs to wait for something, instead of blocking in a loop, it remembers the "step" it is on and returns so that other operations can make progress. When the state machine is called again, it "resumes" the step it was on and make progress. In other words, we are implementing cooperative multi-tasking with a single task. This allows all operations executing concurrently and all making progress without the true multi-tasking pitfalls to deal with.
An example of how state machines work is to consider doing laundry and baking a pizza at the same time. These are two separate operations but with a lot of waiting time. First you break down the steps of each operation.
Code:
Bake a pizza:
1. take the frozen pizza out of the freezer.
2. preheat the oven at 400 degrees and wait for the oven to reach the preheat temperature.
3. put the frozen pizza into the oven.
4. set a timer for 15 minutes and wait for the timer to go off.
5. check if the pizza is thoroughly cooked. If not, put it back in the oven and add 5 more minutes to the timer.
6. repeat step 5 until the pizza is done.
7. take the pizza out, cut it and eat it.

Doing laundry:
2. put clothes into the washing machine.
3. put in laundry detergent and start the washing machine. Wait for the washing machine to finish.
4. transfer the clothes into the dryer, put in the fabric softener and start it. Wait for the dryer to finish.
5. take clothes out of the dry and fold them.
6. put them away back into the closet or dresser.

You can do the above two jobs in sequence one after another but it will take a long time because you don't start the laundry until you have finished baking and eating the pizza. Or, you can do the two concurrently but when it's time to "wait for something", you note down what step you are on and instead of waiting, you leave to attend the other job checking on the laundry. When the laundry step is to wait for something, again you note down the step you are on and go back to the pizza job and resume the last step you are on. You go back and forth between the two tasks until both are done. This is the core concept of multitasking. In this case, you have two separate state machines, one to keep track of the "baking a pizza" task and the other to keep track of the "laundry" task.


Mon Mar 02, 2015 4:32 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
akash329dsouza wrote:
Yes! We made it to super regionals in Iowa. We finished 9th place in robot runs. (We won 2nd place inspire!)

BTW, are you in the same team as Damien and Maximilain? I helped them a couple years back. They went to the Iowa regional also.


Mon Mar 02, 2015 4:57 pm
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
No, I'm on a team from Minnesota. Thanks for your tips by the way! Working on converting it now. (I'll show you the code when I'm done)
What the failsafe task does is it checks on the first controller for button 10, if the lift is stuck/second controller is not working he can just press that button and it will abort lift and restart the second controller in order to reset all encoder counts and exit while loops.

_________________
Thanks!


Mon Mar 02, 2015 8:01 pm
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
Ok, so I tried to do the it but I can't even figure out how to start, I thought of a few ways to add in state machines at first but then figured out none of them would work. I tried looking at your teams code but it was way to confusing. Since you've done this before, how would you go converting the code? I'm kind of just trying to improve the teleop in general. I also attached the code in a zip file and added it to message.

Here is teleop functions code (I commented confusing part):
Code:
#pragma config(Hubs,  S2, HTMotor,  HTMotor,  HTMotor,  HTServo)
#pragma config(Sensor, S1,     Mux,            sensorI2CCustom)
#pragma config(Sensor, S2,     ,               sensorI2CMuxController)
#pragma config(Sensor, S4,     Ultra,          sensorSONAR)
#pragma config(Motor,  mtr_S2_C1_1,     motorD,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C1_2,     motorE,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C2_1,     motorF,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C2_2,     motorG,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C3_1,     motorH,        tmotorTetrix, openLoop, encoder)
#pragma config(Motor,  mtr_S2_C3_2,     motorI,        tmotorTetrix, openLoop)
#pragma config(Servo,  srvo_S2_C4_1,    Ball_Reel_L,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_2,    Goal_Grab,            tServoStandard)
#pragma config(Servo,  srvo_S2_C4_3,    Ball_Reel_R,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_4,    Lift,                 tServoStandard)
#pragma config(Servo,  srvo_S2_C4_5,    servo5,               tServoNone)
#pragma config(Servo,  srvo_S2_C4_6,    servo6,               tServoNone)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
int Sensitivity = 1;   //Set beginning sensitivity for controller
int DesiredAngle;   //Creates Desired Angle Variable
int speed2 = 0;
#include "HDStuff.h" //Includes some drivers and Variables.
GYRO HDGyro;   //Create Gyro struct
const tMUXSensor leftIR = msensor_S1_2;
const tMUXSensor rightIR = msensor_S1_1;
const tMUXSensor frontUS = msensor_S1_4;
#include "Teleop(StateMachine).h"   //Teleop functions
task Controller_1()
{
   int Threshold = 10;    //Threshold for joysticks
   int VLFinUse = 10;
   while(true){
      wait1Msec(30);   //Wait so Loop dosen't get stuck
      if(joy1Btn(02) == 1){    //If joystick button is pressed do IR Lineup
         IRLineUp();
      }
      else if(joy1Btn(04) == 1){
         MoveForward(85,30);
      }
      else   if(joystick.joy1_TopHat == 0) //Up button on the D-Pad
      {
         Sensitivity = 1; //Sets the joystick sensitivity controlls to 1
      }
      else if(joystick.joy1_TopHat == 4) //Down button on the D-Pad
      {
         Sensitivity = 3; //Sets the joystick sensitivity controlls to 4
      }
      else if(joystick.joy1_TopHat == 6) //Up button on the D-Pad
      {
         Sensitivity = 3; //Sets the joystick sensitivity controlls to 3
      }
      else if(joystick.joy1_TopHat == 2) //Down button on the D-Pad
      {
         Sensitivity = 2; //Sets the joystick sensitivity controlls to 2
      }
      if(joystick.joy1_y1 > 100 && joystick.joy1_y2 > 100)   //If the left and right y axis are past 100.
      {
         if(VLFinUse == 0) //If VLF(Virtual line follower that uses the gyro with a preportional loop to follow a line) Was not running previously
         {
            DesiredAngle = HDGyro.heading; //Set the desired angle to the current heading
         }
         VLFinUse = 1; //Set VLFinUse to 1
         VLFforward();   //Turn on VLFforward
      }
      else if(joystick.joy1_y1 < -100 && joystick.joy1_y2 < -100) //If the left and right y axis are less than -100.
      {
         if(VLFinUse == 0) //If VLF was not in use
         {
            DesiredAngle = HDGyro.heading;   //Set desired angle to current heading
         }
         VLFinUse = 1;   //Vlf is set to in use
         VLFbackward();   //Turn on VLFbackward
      }
      else if(abs(joystick.joy1_y1) > Threshold || abs(joystick.joy1_y2) > Threshold)   //If joystick y1 is larger than threshold or joystick y2 is larger than threshold
      {
         VLFinUse = 0;   //VLF is not in use
         motor[motorF] = joystick.joy1_y1/Sensitivity;   //Set motorF to joystick joy1 devided by sensitivity
         motor[motorG] = joystick.joy1_y1/Sensitivity; //Set motorG to joystick joy1 devided by sensitivity
         motor[motorD] = joystick.joy1_y2/Sensitivity; //Set motorD to joystick joy2 devided by sensitivity
         motor[motorE] = joystick.joy1_y2/Sensitivity; //Set motorE to joystick joy2 devided by sensitivity
      }
      else   //If none of other conditions are met
      {
         Brake(); //Break
         VLFinUse = 0; //Set VLFinUse to 0
      }
   }
}

task Controller_2()
{
   while (true){
      wait1Msec(30);
      if(joy2Btn(07) == 1){
      BallReelStop();
      }
      else if(joy2Btn(08) == 1){
      BallReelStart();
      }
      else if(joy2Btn(04) == 1) //Up Center Goal
      {
         LiftGoal(2850,2800);
      }
      else if(joy2Btn(03) == 1) //Up Small Goal
      {
         LiftGoal(1235,1185);
      }
      else if(joy2Btn(02) == 1) //Up Medium
      {
         LiftGoal(1665,1615);
      }
      else if(joy2Btn(01) == 1) //Up Large
      {
         LiftGoal(2300,2250);
      }
      else if(joystick.joy2_y1 > 100 && joystick.joy2_y2 > 100)
      {
         ManualLiftUp();
      }
      else if(joystick.joy2_y1 < -100 && joystick.joy2_y2 < -100)
      {
         motor[motorH] = -2;
      }
      else if(joystick.joy2_TopHat == 0)
      {
         if(nMotorEncoder[motorH] < -3500)
         {
            servoChangeRate[Lift] = 8;
            servo[Lift] = 245;
         }
      }
      else{
         servoChangeRate[Lift] = 10;
         motor[motorH] = 0;
         servo[Lift] = 115;
      }
      if(joy2Btn(05) == 1)   //If joystick left button is pressed
      {
         servo[Goal_Grab] = 0;   //Move the ball hook to up position
      }
      else if(joy2Btn(06) == 1) //If joystick right button is pressed
      {
         servo[Goal_Grab] = 75;   //Move the ball hook to down position
      }
   }
}

task Failsafe()
{
   while(true)
   {
      wait1Msec(30);
      if(joy1Btn(10) == 1)   //If button is pressed
      {
         while(joy1Btn(10) == 1){   //While button is pressed wait, continue when button is unpressed
            wait1Msec(30);
         }
         motor[motorH] = 0;   //Stop Lift Task
         stopTask(Controller_2);   //Stop Second Controller to stop while loops and reset encoders
         wait1Msec(700);   //Wait 700 milliseconds
         startTask(Controller_2);      //Start Task Again
      }
   }
}

task main()
{
   GyroInit(HDGyro,S3);   //Initilise gyro
   startTask(Failsafe);
   startTask(GyroUpdate);   //Start Gyro Update task to keep track of heading
   startTask(Controller_1);
   startTask(Controller_2);
   servo[Lift] = 115;   //Make sure servo is initilized to correct position in beginning of program.
   while(true)   //While true (Forever while loop)
   {
      wait1Msec(30);   //Wait 30 milliseconds to reduce latency
      getJoystickSettings(joystick);   //Get the joystick settings
   }
}


Thanks! :mrgreen:


Attachments:
File comment: Teleop Code(Called w/State Machine but no changes have been made)
Teleop.zip [8.18 KiB]
Downloaded 409 times

_________________
Thanks!
Mon Mar 02, 2015 8:30 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
I just did a quick conversion of your code basically taking out all the while loops and wait statements and convert them to state machines when appropriate. Since I may not understand some part of the code correctly, I may have translated it incorrectly. I have attempted to optimize some part of the code where I felt it may improve efficiency. Other part of the code seems too complicated to simplify so I left them alone but it probably would benefit from some sort of optimization. For example, in the controller 2 task, there is this complicated waiting for button 4 to be pressed, then released, then pressed then released. I think you were trying to implement a toggling button. If so, that logic is too complicated. I think there is an easier way but I am not sure if that's what your code was trying to do. Also notice that I got rid of all your RobotC tasks to show you an example of doing multi-tasking using only a single task.
Code:
#pragma config(Hubs,  S2, HTMotor,  HTMotor,  HTMotor,  HTServo)
#pragma config(Sensor, S1,     Mux,            sensorI2CCustom)
#pragma config(Sensor, S2,     ,               sensorI2CMuxController)
#pragma config(Sensor, S4,     Ultra,          sensorSONAR)
#pragma config(Motor,  mtr_S2_C1_1,     motorD,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C1_2,     motorE,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C2_1,     motorF,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C2_2,     motorG,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C3_1,     motorH,        tmotorTetrix, openLoop, encoder)
#pragma config(Motor,  mtr_S2_C3_2,     motorI,        tmotorTetrix, openLoop)
#pragma config(Servo,  srvo_S2_C4_1,    Ball_Reel_L,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_2,    Goal_Grab,            tServoStandard)
#pragma config(Servo,  srvo_S2_C4_3,    Ball_Reel_R,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_4,    Lift,                 tServoStandard)
#pragma config(Servo,  srvo_S2_C4_5,    servo5,               tServoNone)
#pragma config(Servo,  srvo_S2_C4_6,    servo6,               tServoNone)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

int Sensitivity = 1;   //Set beginning sensitivity for controller
int DesiredAngle;   //Creates Desired Angle Variable
int speed2 = 0;
#include "HDStuff.h" //Includes some drivers and Variables.
GYRO HDGyro;   //Create Gyro struct
const tMUXSensor leftIR = msensor_S1_2;
const tMUXSensor rightIR = msensor_S1_1;
const tMUXSensor frontUS = msensor_S1_4;

bool IRLineUpEnabled = false;
int MoveForwardDistance = 0;
int MoveForwardSpeed = 0;
bool MoveForwardEnabled = false;
int LiftGoalUp = 0;
int LiftGoalDown = 0;
int LiftGoalState = -1;

void FailsafeTask()
{
    static int state = 0;
    switch (state)
    {
    case 0:
        if (joy1Btn(10) == 1)
        {
            state++;
        }
        break;

    case 1:
        if (joy1Btn(10) == 0)
        {
            state++;
        }
        break;

    case 2:
        motor[motorH] = 0;   //Stop Lift Task
        // I still don't understand why you need to restart controller 2 task.
        // I will leave this to you to think about what you need here.
        break;

    case 3:
        state = 0;
        break;
    }
}

void IRLineUpTask()
{
    static const int Speed = -30;
    static const int Kp = 7;

    if (IRLineUpEnabled)
    {
        if ((USreadDist(frontUS) > 23) && (joy1Btn(0) == 0))
        {
            float irDir = IRGetACDir(leftIR,1) + IRGetACDir(rightIR,2);
            float error = irDir - 10.0;
            nxtDisplayTextLine(3, "Error=%d,Dir=%5.1f", error, 1);
            motor[motorF] =Speed + (Kp*error);
            motor[motorG] = Speed + (Kp*error);
            motor[motorD] = Speed - (Kp*error);
            motor[motorE] = Speed - (Kp*error);
        }
        else
        {
            motor[motorF] =0;
            motor[motorG] = 0;
            motor[motorD] = 0;
            motor[motorE] = 0;
            IRLineUpEnabled = false;
        }
    }
}

void MoveForward(int degrees, int speed)//Move function
{
    MoveForwardDistance = degrees;
    MoveForwardSpeed = speed;
    nMotorEncoder[motorD] = 0;      //Reset Encoders
    nMotorEncoder[motorE] = 0;  //Reset Encoders
    nMotorEncoder[motorF] = 0;  //Reset Encoders
    nMotorEncoder[motorG] = 0;  //Reset Encoders
    MoveForwardEnabled = true;
}

void MoveForwardTask()
{
    if (MoveForwardEnabled)
    {
        if (((nMotorEncoder[motorD] + nMotorEncoder[motorE] + nMotorEncoder[motorF] + nMotorEncoder[motorG])/4) < (MoveForwardDistance*4) || joy1Btn(03) == 1)
        {
            motor[motorD] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorE] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorF] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorG] = MoveForwardSpeed;  //Motors go at specified speed
        }
        else
        {
            motor[motorD] = 0;      //Set motor speed to 0
            motor[motorE] = 0;  //Set motor speed to 0
            motor[motorF] = 0;  //Set motor speed to 0
            motor[motorG] = 0;  //Set motor speed to 0
            MoveForwardEnabled = false;
        }
    }
}

void LiftGoal(int Up, int Down)
{
    nMotorEncoder[motorH] = 0;      //Reset Encoder
    LiftGoalUp = Up;
    LiftGoalDown = Down;
    LiftGoalState = 0;
}

void LiftGoalTask()
{
    if (LiftGoalState >= 0)
    {
        switch (LiftGoalState)
        {
        case 0:
            if (nMotorEncoder[motorH]/4 > -LiftGoalUp)
            {
                displayTextLine(2, "Speed :  %4d", speed2);  //Make lift go up preportionally
                displayTextLine(3, "LiftEncoder :  %4d", nMotorEncoder[motorH]/4);
                speed2 = 25 + (abs(nMotorEncoder[motorH]/4)/200);
                motor[motorH] = speed2;
            }
            else
            {
                motor[motorH] = 0;      //Stop Lift motor
                LiftGoalState++;
            }
            break;

        case 1:
            if (joy2Btn(04) == 0)
            {
                motor[motorH] = 5;
            }
            else
            {
                servoChangeRate[Lift] = 8;      //Slow servo to protect part
                servo[Lift] = 240;      //Make servo drop balls
                LiftGoalState++;
            }
            break;

        case 2:
            if (joy2Btn(04) == 1)
            {
                motor[motorH] = 5;
            }
            else
            {
                LiftGoalState++;
            }
            break;

        case 3:
            if (joy2Btn(04) == 0)
            {
                motor[motorH] = 5;
            }
            else
            {
                nMotorEncoder[motorH] = 0;
                servo[Lift] = 115;
                servoChangeRate[Lift] = 10;
                LiftGoalState++;
            }
            break;

        case 4:
            if (nMotorEncoder[motorH]/4 < LiftGoalDown)
            {
                displayTextLine(3, "Color :  %4d", nMotorEncoder[motorH]/4);
                motor[motorH] = -2;
            }
            else
            {
                motor[motorH] = 0;
                LiftGoalState = -1;
            }
            break;
        }
    }
}

void Controller1Task()
{
    static const int Threshold = 10;    //Threshold for joysticks
    static const int VLFinUse = 10;
    if (joy1Btn(02) == 1){    //If joystick button is pressed do IR Lineup
        IRLineUpEnabled = true;   //Start the IRLineUpTask
    }
    else if (joy1Btn(04) == 1) {
        MoveForward(85, 30);
    }
    else if(joystick.joy1_TopHat == 0) //Up button on the D-Pad
    {
        Sensitivity = 1; //Sets the joystick sensitivity controlls to 1
    }
    else if(joystick.joy1_TopHat == 4) //Down button on the D-Pad
    {
        Sensitivity = 3; //Sets the joystick sensitivity controlls to 4
    }
    else if(joystick.joy1_TopHat == 6) //Up button on the D-Pad
    {
        Sensitivity = 3; //Sets the joystick sensitivity controlls to 3
    }
    else if(joystick.joy1_TopHat == 2) //Down button on the D-Pad
    {
        Sensitivity = 2; //Sets the joystick sensitivity controlls to 2
    }

    if(joystick.joy1_y1 > 100 && joystick.joy1_y2 > 100)   //If the left and right y axis are past 100.
    {
        if(VLFinUse == 0) //If VLF(Virtual line follower that uses the gyro with a preportional loop to follow a line) Was not running previously
        {
            DesiredAngle = HDGyro.heading; //Set the desired angle to the current heading
        }
        VLFinUse = 1; //Set VLFinUse to 1
        VLFforward();   //Turn on VLFforward
    }
    else if(joystick.joy1_y1 < -100 && joystick.joy1_y2 < -100) //If the left and right y axis are less than -100.
    {
        if(VLFinUse == 0) //If VLF was not in use
        {
            DesiredAngle = HDGyro.heading;   //Set desired angle to current heading
        }
        VLFinUse = 1;   //Vlf is set to in use
        VLFbackward();   //Turn on VLFbackward
    }
    else if(abs(joystick.joy1_y1) > Threshold || abs(joystick.joy1_y2) > Threshold)   //If joystick y1 is larger than threshold or joystick y2 is larger than threshold
    {
        VLFinUse = 0;   //VLF is not in use
        motor[motorF] = joystick.joy1_y1/Sensitivity;   //Set motorF to joystick joy1 devided by sensitivity
        motor[motorG] = joystick.joy1_y1/Sensitivity; //Set motorG to joystick joy1 devided by sensitivity
        motor[motorD] = joystick.joy1_y2/Sensitivity; //Set motorD to joystick joy2 devided by sensitivity
        motor[motorE] = joystick.joy1_y2/Sensitivity; //Set motorE to joystick joy2 devided by sensitivity
    }
    else   //If none of other conditions are met
    {
        Brake(); //Break
        VLFinUse = 0; //Set VLFinUse to 0
    }
}

void Controller2Task()
{
    if(joy2Btn(07) == 1){
        BallReelStop();
    }
    else if(joy2Btn(08) == 1){
        BallReelStart();
    }
    else if(joy2Btn(04) == 1) //Up Center Goal
    {
        LiftGoal(2850,2800);
    }
    else if(joy2Btn(03) == 1) //Up Small Goal
    {
        LiftGoal(1235,1185);
    }
    else if(joy2Btn(02) == 1) //Up Medium
    {
        LiftGoal(1665,1615);
    }
    else if(joy2Btn(01) == 1) //Up Large
    {
        LiftGoal(2300,2250);
    }
    else if(joystick.joy2_y1 > 100 && joystick.joy2_y2 > 100)
    {
        ManualLiftUp();
    }
    else if(joystick.joy2_y1 < -100 && joystick.joy2_y2 < -100)
    {
        motor[motorH] = -2;
    }
    else if(joystick.joy2_TopHat == 0)
    {
        if(nMotorEncoder[motorH] < -3500)
        {
            servoChangeRate[Lift] = 8;
            servo[Lift] = 245;
        }
    }
    else{
        servoChangeRate[Lift] = 10;
        motor[motorH] = 0;
        servo[Lift] = 115;
    }

    if(joy2Btn(05) == 1)   //If joystick left button is pressed
    {
        servo[Goal_Grab] = 0;   //Move the ball hook to up position
    }
    else if(joy2Btn(06) == 1) //If joystick right button is pressed
    {
        servo[Goal_Grab] = 75;   //Move the ball hook to down position
    }
}

task main()
{
    GyroInit(HDGyro,S3);   //Initilise gyro
    servo[Lift] = 115;      //Make sure servo is initilized to correct position in beginning of program.
    while (true)
    {
        getJoystickSettings(joystick);   //Get the joystick settings
        GyroTask(HDGyro);
        FailsafeTask();
        Controller1Task();
        Controller2Task();
        IRLineUpTask();
        MoveForwardTask();
        LiftGoalTask();
        wait1Msec(30);   //Wait 30 milliseconds to reduce latency
    }
}


Tue Mar 03, 2015 5:55 am
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
Thanks so much for your help! So I adjusted our code and removed redundant stuff:
(Main Code)
Code:
#pragma config(Hubs,  S2, HTMotor,  HTMotor,  HTMotor,  HTServo)
#pragma config(Sensor, S1,     Mux,            sensorI2CCustom)
#pragma config(Sensor, S2,     ,               sensorI2CMuxController)
#pragma config(Sensor, S4,     Ultra,          sensorSONAR)
#pragma config(Motor,  mtr_S2_C1_1,     motorD,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C1_2,     motorE,        tmotorTetrix, PIDControl, encoder)
#pragma config(Motor,  mtr_S2_C2_1,     motorF,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C2_2,     motorG,        tmotorTetrix, PIDControl, reversed, encoder)
#pragma config(Motor,  mtr_S2_C3_1,     motorH,        tmotorTetrix, openLoop, encoder)
#pragma config(Motor,  mtr_S2_C3_2,     motorI,        tmotorTetrix, openLoop)
#pragma config(Servo,  srvo_S2_C4_1,    Ball_Reel_L,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_2,    Goal_Grab,            tServoStandard)
#pragma config(Servo,  srvo_S2_C4_3,    Ball_Reel_R,          tServoContinuousRotation)
#pragma config(Servo,  srvo_S2_C4_4,    Lift,                 tServoStandard)
#pragma config(Servo,  srvo_S2_C4_5,    servo5,               tServoNone)
#pragma config(Servo,  srvo_S2_C4_6,    servo6,               tServoNone)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

int Sensitivity = 1;   //Set beginning sensitivity for controller
int DesiredAngle;   //Creates Desired Angle Variable
int speed2 = 0;
#include "HDStuff.h" //Includes some drivers and Variables.
GYRO HDGyro;   //Create Gyro struct
const tMUXSensor leftIR = msensor_S1_2;
const tMUXSensor rightIR = msensor_S1_1;
const tMUXSensor frontUS = msensor_S1_4;
#include "Teleop(StateMachine).h"

bool IRLineUpEnabled = false;
int MoveForwardDistance = 0;
int MoveForwardSpeed = 0;
bool MoveForwardEnabled = false;
int LiftGoalUp = 0;
int LiftGoalDown = 0;
int LiftGoalState = -1;

void FailsafeTask()
{
    static int state = 0;
    switch (state)
    {
    case 0:
        if (joy1Btn(10) == 1)
        {
            state++;
        }
        break;

    case 1:
        if (joy1Btn(10) == 0)
        {
            state++;
        }
        break;

    case 2:
        motor[motorH] = 0;   //Stop Lift Task
        // I still don't understand why you need to restart controller 2 task.
        // I will leave this to you to think about what you need here.
        break;

    case 3:
        state = 0;
        break;
    }
}

void IRLineUpTask()
{
    static const int Speed = -30;
    static const int Kp = 7;

    if (IRLineUpEnabled)
    {
        if ((USreadDist(frontUS) > 23) && (joy1Btn(0) == 0))
        {
            float irDir = IRGetACDir(leftIR,1) + IRGetACDir(rightIR,2);
            float error = irDir - 10.0;
            nxtDisplayTextLine(3, "Error=%d,Dir=%5.1f", error, 1);
            motor[motorF] =Speed + (Kp*error);
            motor[motorG] = Speed + (Kp*error);
            motor[motorD] = Speed - (Kp*error);
            motor[motorE] = Speed - (Kp*error);
        }
        else
        {
            motor[motorF] =0;
            motor[motorG] = 0;
            motor[motorD] = 0;
            motor[motorE] = 0;
            IRLineUpEnabled = false;
        }
    }
}

void MoveForward(int degrees, int speed)//Move function
{
    MoveForwardDistance = degrees;
    MoveForwardSpeed = speed;
    nMotorEncoder[motorD] = 0;      //Reset Encoders
    nMotorEncoder[motorE] = 0;  //Reset Encoders
    nMotorEncoder[motorF] = 0;  //Reset Encoders
    nMotorEncoder[motorG] = 0;  //Reset Encoders
    MoveForwardEnabled = true;
}

void MoveForwardTask()
{
    if (MoveForwardEnabled)
    {
        if (((nMotorEncoder[motorD] + nMotorEncoder[motorE] + nMotorEncoder[motorF] + nMotorEncoder[motorG])/4) < (MoveForwardDistance*4) || joy1Btn(03) == 1)
        {
            motor[motorD] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorE] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorF] = MoveForwardSpeed;  //Motors go at specified speed
            motor[motorG] = MoveForwardSpeed;  //Motors go at specified speed
        }
        else
        {
            motor[motorD] = 0;      //Set motor speed to 0
            motor[motorE] = 0;  //Set motor speed to 0
            motor[motorF] = 0;  //Set motor speed to 0
            motor[motorG] = 0;  //Set motor speed to 0
            MoveForwardEnabled = false;
        }
    }
}

void LiftGoal(int Up, int Down)
{
    nMotorEncoder[motorH] = 0;      //Reset Encoder
    LiftGoalUp = Up;
    LiftGoalDown = Down;
    LiftGoalState = 0;
}

void LiftGoalTask()
{
    if (LiftGoalState >= 0)
    {
        switch (LiftGoalState)
        {
        case 0:
            if (nMotorEncoder[motorH]/4 > -LiftGoalUp)
            {
                displayTextLine(2, "Speed :  %4d", speed2);  //Make lift go up preportionally
                displayTextLine(3, "LiftEncoder :  %4d", nMotorEncoder[motorH]/4);
                speed2 = 25 + (abs(nMotorEncoder[motorH]/4)/200);
                motor[motorH] = speed2;
            }
            else
            {
                motor[motorH] = 0;      //Stop Lift motor
                LiftGoalState++;
            }
            break;

        case 1:
            if (joy2Btn(04) == 0)
            {
                motor[motorH] = 5;
            }
            else
            {
                servoChangeRate[Lift] = 8;      //Slow servo to protect part
                servo[Lift] = 240;      //Make servo drop balls
                LiftGoalState++;
            }
            break;

        case 2:
            if (joy2Btn(04) == 1)
            {
                motor[motorH] = 5;
            }
            else
            {
                LiftGoalState++;
            }
            break;

        case 3:
            if (joy2Btn(04) == 0)
            {
                motor[motorH] = 5;
            }
            else
            {
                nMotorEncoder[motorH] = 0;
                servo[Lift] = 115;
                servoChangeRate[Lift] = 10;
                LiftGoalState++;
            }
            break;

        case 4:
            if (nMotorEncoder[motorH]/4 < LiftGoalDown)
            {
                displayTextLine(3, "Color :  %4d", nMotorEncoder[motorH]/4);
                motor[motorH] = -2;
            }
            else
            {
                motor[motorH] = 0;
                LiftGoalState = -1;
            }
            break;
        }
    }
}

void Controller1Task()
{
    static const int Threshold = 10;    //Threshold for joysticks
    static int VLFinUse = 10;
    if (joy1Btn(02) == 1){    //If joystick button is pressed do IR Lineup
        IRLineUpEnabled = true;   //Start the IRLineUpTask
    }
    else if (joy1Btn(04) == 1) {
        MoveForward(85, 30);
    }
    else if(joystick.joy1_TopHat == 0) //Up button on the D-Pad
    {
        Sensitivity = 1; //Sets the joystick sensitivity controlls to 1
    }
    else if(joystick.joy1_TopHat == 4) //Down button on the D-Pad
    {
        Sensitivity = 3; //Sets the joystick sensitivity controlls to 4
    }
    else if(joystick.joy1_TopHat == 6) //Up button on the D-Pad
    {
        Sensitivity = 3; //Sets the joystick sensitivity controlls to 3
    }
    else if(joystick.joy1_TopHat == 2) //Down button on the D-Pad
    {
        Sensitivity = 2; //Sets the joystick sensitivity controlls to 2
    }

    if(joystick.joy1_y1 > 100 && joystick.joy1_y2 > 100)   //If the left and right y axis are past 100.
    {
        if(VLFinUse == 0) //If VLF(Virtual line follower that uses the gyro with a preportional loop to follow a line) Was not running previously
        {
            DesiredAngle = HDGyro.heading; //Set the desired angle to the current heading
        }
        VLFinUse = 1; //Set VLFinUse to 1
        VLFforward();   //Turn on VLFforward
    }
    else if(joystick.joy1_y1 < -100 && joystick.joy1_y2 < -100) //If the left and right y axis are less than -100.
    {
        if(VLFinUse == 0) //If VLF was not in use
        {
            DesiredAngle = HDGyro.heading;   //Set desired angle to current heading
        }
        VLFinUse = 1;   //Vlf is set to in use
        VLFbackward();   //Turn on VLFbackward
    }
    else if(abs(joystick.joy1_y1) > Threshold || abs(joystick.joy1_y2) > Threshold)   //If joystick y1 is larger than threshold or joystick y2 is larger than threshold
    {
        VLFinUse = 0;   //VLF is not in use
        motor[motorF] = joystick.joy1_y1/Sensitivity;   //Set motorF to joystick joy1 devided by sensitivity
        motor[motorG] = joystick.joy1_y1/Sensitivity; //Set motorG to joystick joy1 devided by sensitivity
        motor[motorD] = joystick.joy1_y2/Sensitivity; //Set motorD to joystick joy2 devided by sensitivity
        motor[motorE] = joystick.joy1_y2/Sensitivity; //Set motorE to joystick joy2 devided by sensitivity
    }
    else   //If none of other conditions are met
    {
        Brake(); //Break
        VLFinUse = 0; //Set VLFinUse to 0
    }
}

void Controller2Task()
{
    if(joy2Btn(07) == 1){
        BallReelStop();
    }
    else if(joy2Btn(08) == 1){
        BallReelStart();
    }
    else if(joy2Btn(04) == 1) //Up Center Goal
    {
        LiftGoal(2850,2800);
    }
    else if(joy2Btn(03) == 1) //Up Small Goal
    {
        LiftGoal(1235,1185);
    }
    else if(joy2Btn(02) == 1) //Up Medium
    {
        LiftGoal(1665,1615);
    }
    else if(joy2Btn(01) == 1) //Up Large
    {
        LiftGoal(2300,2250);
    }
    else if(joystick.joy2_y1 > 100 && joystick.joy2_y2 > 100)
    {
        ManualLiftUp();
    }
    else if(joystick.joy2_y1 < -100 && joystick.joy2_y2 < -100)
    {
        motor[motorH] = -2;
    }
    else if(joystick.joy2_TopHat == 0)
    {
        if(nMotorEncoder[motorH] < -3500)
        {
            servoChangeRate[Lift] = 8;
            servo[Lift] = 245;
        }
    }
    else{
        servoChangeRate[Lift] = 10;
        motor[motorH] = 0;
        servo[Lift] = 115;
    }

    if(joy2Btn(05) == 1)   //If joystick left button is pressed
    {
        servo[Goal_Grab] = 0;   //Move the ball hook to up position
    }
    else if(joy2Btn(06) == 1) //If joystick right button is pressed
    {
        servo[Goal_Grab] = 75;   //Move the ball hook to down position
    }
}

task main()
{
    GyroInit(HDGyro,S3);   //Initilise gyro
    servo[Lift] = 115;      //Make sure servo is initilized to correct position in beginning of program.
    while (true)
    {
        getJoystickSettings(joystick);   //Get the joystick settings
        GyroTask(HDGyro);
        FailsafeTask();
        Controller1Task();
        Controller2Task();
        IRLineUpTask();
        MoveForwardTask();
        LiftGoalTask();
        wait1Msec(30);   //Wait 30 milliseconds to reduce latency
    }
}


(Some Functions)
Code:
/*
This is our function library that holds all of our functions for Teleop.

*/
#pragma systemFile

float IRGetACDir(tMUXSensor link, int line)
{
   static float prevDir = 0.0; //Create variables
   float currDir;
   int acS[5];
   int idx;
   idx = HTIRS2readACDir(link);  //Read current zone and store in idx
   currDir = (float)idx; //Store current zone as a float instead of an integer
   if (idx == 0)// if HTIRS2readACDir returns 0, it means it lost the IR beacon. In that case we use the ACDir determined previously.
   {
      currDir = prevDir;
   }
   else if (HTIRS2readAllACStrength(link, acS[0], acS[1], acS[2], acS[3], acS[4])) //Read the strength values of all 5 sensors.
   {
      idx = (idx - 1)/2; //translate the zone value into the sensor number 0 to 4. For example, zone 4 yielded idx 1.
      if ((idx < 4) && (acS[idx] != 0) && (acS[idx + 1] != 0)) //if sensor number and sensor number + 1 are still within 0 through 4 and if sensor number and sensor number + 1 both have non-zero strength
      {
         // calculate the .x proportion value from the relative strength of the two adjacent sensors. The result could be a positive or a negative number smaller than 1.0. Then add this .x number to the original zone number from HTIRS2readACDir.
         currDir += (float)(acS[idx + 1] - acS[idx])/
         max(acS[idx], acS[idx + 1]);
      }
      nxtDisplayTextLine(line, "Idx=%d,Dir=%5.1f", idx, currDir);
   }
   prevDir = currDir; // remember the current zone value in case the next time we lost the IR beacon.

   return currDir;
}

void ManualLiftUp()    //Makes lift go up preportionally adding power as it goes up.
{
         displayTextLine(2, "Speed :  %4d", speed2);
         displayTextLine(3, "LiftEncoder :  %4d", nMotorEncoder[motorH]/4);
         speed2 = 25 + (abs(nMotorEncoder[motorH]/4)/200);
         motor[motorH] = speed2;
}

void BallReelStop()
{
   servo[Ball_Reel_L] = 127;   //Send servo commands to stop the ball reel
   servo[Ball_Reel_R] = 127;
}

void BallReelStart()
{
   servo[Ball_Reel_L] = 255;   //Send servo commands to start the ball reel
   servo[Ball_Reel_R] = 0;
}

int MotorCorrection; //Create MotorCorrection integer

void VLFforward()   //VLF forward void
{
   int MotorSpeed = 100/Sensitivity;   //Motor speed is set at 100 devided by sensitivity
   int ProportionalGain = 3; //K- value
   MotorCorrection = ProportionalGain*(HDGyro.heading - DesiredAngle); //Calculates Motor Correction to make
   motor[motorD] = MotorSpeed + MotorCorrection; //Moves and applies motor correction (You may need to adjust this depending on if the sign is correct)
   motor[motorE] = MotorSpeed + MotorCorrection; //Moves and applies motor correction
   motor[motorF] = MotorSpeed - MotorCorrection; //Moves and applies motor correction
   motor[motorG] = MotorSpeed - MotorCorrection; //Moves and applies motor correction
}

void VLFbackward()   //VLF backward void
{
   int MotorSpeed = 100/Sensitivity;   //Motor speed is set at 100 devided by sensitivity
   int ProportionalGain = 3; //K- value
   MotorCorrection = ProportionalGain*(HDGyro.heading - DesiredAngle); //Calculates Motor Correction to make
   nxtDisplayCenteredBigTextLine(4, "%5.1f",HDGyro.heading); //Displays the current Gyro Heading
   motor[motorD] = -MotorSpeed + MotorCorrection; //Moves and applies motor correction (You may need to adjust this depending on if the sign is correct)
   motor[motorE] = -MotorSpeed + MotorCorrection; //Moves and applies motor correction
   motor[motorF] = -MotorSpeed - MotorCorrection; //Moves and applies motor correction
   motor[motorG] = -MotorSpeed - MotorCorrection; //Moves and applies motor correction
}

void Brake() //Brake motors
{
   motor[motorD] = 0;
   motor[motorE] = 0;
   motor[motorF] = 0;
   motor[motorG] = 0;
}


Also, the toggling thing we were trying to do, so what we are trying to do is when the lift is up you press one button to lower servo and then press it again to raise it. Our problems was our drivers were holding the button down too long so it was activating both. Our first solution was to put a wait but that's not ideal so we switched to waiting for button to not be pressed in between. For the controller 2 fail safe we needed to stop controller task because even if we just ended the lift motor it would continue going as the encoders would not have reached their full count yet. By restarting the task we ended all the while loops waiting for encoders so it would start again from scratch. Thanks so much again! Does there look like there is any problems with the code or does it look good?

_________________
Thanks!


Tue Mar 03, 2015 10:07 pm
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
Adding on to my last post, did your team find any useful uses for sensors in teleop this year?

_________________
Thanks!


Tue Mar 03, 2015 11:34 pm
Profile
Rookie

Joined: Mon Dec 15, 2014 12:46 am
Posts: 19
Post Re: Question for MHTS
Just for your reference, this is how we did a toggle button. Initially the button was meant to switch between three different positions, but now we just need two but the functionality is still there if we need three or more positions later:
Code:
#ifndef ROBOTDEFINITIONS
#include "..\RobotDefintions 150131.c"
#define ROBOTDEFINITIONS 1
#endif

int nextServoCommand = 1;
bool bButtonPressed = false;

void autoServoBall()
{
   clearDebugStream();
   while(true)
   {
      getJoystickSettings(joystick);
      if(joy2Btn(9) == true && bButtonPressed == false)
      {
         switch((int) nextServoCommand)
         {
         case 1: servo[autoBallDispenser] = HoldSmallBall;
            nextServoCommand++;
            bButtonPressed = true;
            //writeDebugStreamLine("Small Ball");
            break;
         case 2: servo[autoBallDispenser] = HoldNoBalls;
            nextServoCommand = 1;
            bButtonPressed = true;
            //writeDebugStreamLine("No Balls");
            break;
         //case 3: servo[autoBallDispenser] = HoldBothBalls;
         //   nextServoCommand = 1;
         //   bButtonPressed = true;
         //   //writeDebugStreamLine("Both Balls");
         //   break;
         default:
            break;
         }
      }
      if(joy2Btn(9) == true != true)
      {
         bButtonPressed = false;
      }
   }
}

_________________
FTC 7104 - The Synergists


Wed Mar 04, 2015 12:16 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
Did anything change from the code I suggested? It seems the same to me, even the comment that I said I didn't quite know what should go there.
If I understand your description on the Failsafe task correctly then you probably don't need it any more because there is no longer a RobotC task for the lift.
Regarding the toggle switch issue, I still don't understand the code. According to your description, I would put the button 4 toggle code in the Controller2Task. So the buttons 1, 2, 3, and 4 will just raise the lift to various heights. You need to pick another button to toggle and operate on raising and lowering the servo independent of the lift. What I don't understand is your code in LiftGoal on the "Down" parameter? I would guess that's the encoder reading to lower the lift to but then why are the down positions different for each goal height??? I would expect the down position is the same for all goal heights.


Last edited by MHTS on Wed Mar 04, 2015 5:35 am, edited 1 time in total.



Wed Mar 04, 2015 5:00 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
akash329dsouza wrote:
Adding on to my last post, did your team find any useful uses for sensors in teleop this year?

For this year, the only sensor we used in teleop was the touch sensor as a lower limit switch for our elevator.


Wed Mar 04, 2015 5:05 am
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
So our code for the lift down parameter is that we reset the encoder when we get up just so we can have a different value when we go down, it's not easier in the long run but we just decided to do it that way. Also, we tested the teleop today and found a problem. I know what is causing the problem but don't have a ideal solution to fix it. So basically when we do the auto IR LineUp or Raise the lift the brake commands in the else(at the end of the else if commands) that brakes if nothing is being pressed brakes all moters in controller 1 void and in controller 2 void it brakes the lift. Basically what it does is the robot stutters because it keeps receiving that braking command, even in IRLineUp and others where its not supposed to. Another thing, which I don't know what is being caused by, is that when the lift is being raised for some reason we are unable to operate the Goal_Servo's and the Ball_Reel.
Thanks so much for your help guys!

_________________
Thanks!


Last edited by akash329dsouza on Thu Mar 05, 2015 1:13 pm, edited 1 time in total.



Wed Mar 04, 2015 11:07 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
akash329dsouza wrote:
So our code for the lift down parameter is that we reset the encoder when we get up just so we can have a different value when we go down, it's not easier in the long run but we just decided to do it that way. Also, we tested the teleop today and found a problem. I know what is causing the problem but don't have a ideal solution to fix it. So basically when we do the auto IR LineUp or Raise the lift the brake commands in the else(at the end of the else if commands) that brakes if nothing is being pressed brakes all moters in controller 1 void and in controller 2 void it breaks the lift. Basically what it does is the robot stutters because it keeps receiving that breaking command, even in IRLineUp and others where its not supposed to. Another thing, which I don't know what is being caused by, is that when the lift is being raised for some reason we are unable to operate the Goal_Servo's and the Ball_Reel.
Thanks so much for your help guys!

Are these problems happening in your original code or in the code I suggested with state machines? It sounded like a multi-tasking problem but it should have been fixed if you use the state machines.


Thu Mar 05, 2015 4:54 am
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
These were problems in thebcode you gave us

_________________
Thanks!


Thu Mar 05, 2015 8:31 am
Profile
Novice

Joined: Tue Dec 16, 2014 10:25 am
Posts: 81
Post Re: Question for MHTS
The first problem is causes because there is no while loop so it keeps braking even with the IRLineUp running.

_________________
Thanks!


Thu Mar 05, 2015 1:08 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1523
Post Re: Question for MHTS
akash329dsouza wrote:
The first problem is causes because there is no while loop so it keeps braking even with the IRLineUp running.

I see. So this is because the suggested code was "blindly ported" to use state machines for multi-tasking without fully understanding the interaction of your code. In your original code, it was using while-loop to block other things from happening. But now everything is multi-tasked and running "concurrently", so the tasks are interfering with each other. In theory, there should only be one task dealing with one subsystem. So this task would gather all input information (e.g. whether the robot is in IRLineUp mode, or in joystick driving mode) and decide what the drive base should do. It is not too hard to fix though. Since when you press button 2 in controller 1, you have enabled IRLineUp task and the IRLineUpEnabled Boolean is set to true, you can use this Boolean as a condition to run the block of code dealing with joystick drive. In other words, you can say if !IRLineUpEnabled then go into the block of code that reads the joystick values. Also note that the same thing needs to be taken care of for MoveForwardEnabled. My simple port was meant to show you how you can get rid of the while loops so your program is more responsive to the controller events. But now you have to deal with everything running concurrently. In theory, it could be very orderly if the code is structured differently. For example, in our library, we have a joystick module that calls you back for every button presses or releases. Then unless it's something that "fires and forgets" (e.g. servos), the button event callback code does not do any actions directly. Instead, it calls the subsystems or sets variables that the subsystem monitors (i.e. changes the state of some subsystems). It is the subsystem that completely owns that action hardware. For example, the drivebase subsystem controls the 4-wheel drive motors. Nobody else's allowed to touch those motors except for the drivebase subsystem code. If a button is pressed to do IR Line up, it will just set a variable. The drivebase subsystem will monitor this variable, if it's set then it will deal with IR line up, otherwise it will read joystick analog input for the driving. So the fix I suggested is going along with that line of thought.
It would have been nice if RobotC is actually object oriented so that subsystems can be abstracted and encapsulated so that other subsystems cannot access the others except for published interfaces. RobotC folks should consider this in the long-run. It will drastically simplifies the interaction between subsystems. Our library attempts to provide objects in the absence of RobotC native object support. But without native object support, user of the library must use discipline to not access anything internal to the modules.


Thu Mar 05, 2015 5:26 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 32 posts ]  Go to page Previous  1, 2, 3  Next

Who is online

Users browsing this forum: No registered users and 1 guest


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.