Difference between revisions of "Tutorials/Arduino Projects/Mobile Robotics/BoeBot/Using multitasking to monitor the encoders"

From ROBOTC API Guide
Jump to: navigation, search
(The problem)
Line 5: Line 5:
 
==The problem==
 
==The problem==
  
Since there are not too many of them out there, ROBOTC lacks configuration options for non-quadrature encoders. This means that the raw SensorValue[] will only give is 1's or 0's depending on whether the light sensor reads a slit or not. What we need for our encoders to be useful, is a value that increases every time the light reading ''changes'', so we get a higher value the further the wheel has rotated.
+
Due to their limitations, ROBOTC does not contain configuration options for non-quadrature encoders. This means that the raw SensorValue[] will only give a 1 or 0 depending on whether the light sensor reads a slot or not. For our encoders to be useful, we need a value that increases every time the light reading ''changes''. We can then use that value to determine how many revolutions the robot has traveled.
  
 
==The solution==
 
==The solution==

Revision as of 15:40, 17 October 2012

ArduinoArduino Tutorials and Guided ProjectsParallax BoeBot + Arduino Shield, Mobile Robotics Platform → Tutorials/Arduino Projects/Mobile Robotics/BoeBot/Using multitasking to monitor the encoders

The problem

Due to their limitations, ROBOTC does not contain configuration options for non-quadrature encoders. This means that the raw SensorValue[] will only give a 1 or 0 depending on whether the light sensor reads a slot or not. For our encoders to be useful, we need a value that increases every time the light reading changes. We can then use that value to determine how many revolutions the robot has traveled.

The solution

To fix this problem, we are going to use one of ROBOTC's most powerful features, multitasking. This essentially lets us run a bunch of Tasks or 'mini programs', if you will, at the same time. We are going to make a task that will run in the background, counting up our encoder ticks and writing the calculated amounts in a pair of global variables (one for each encoder) which can then be read by any other function or task in the program.

Theory

Basically, what we want to do is monitor when the encoder value changes. To do this, we need to have two variables: 'state', which is the value of the sensor now, and 'lastState', which is the value of the sensor from the previous run of the loop. If state does not equal lastState, then we know the wheels have proceeded 1/16th of a revolution and we will add 1 to the global variable for that particular encoder.

The code

Here is the code without multitasking; its only job is to find the total ticks of each encoder. Be sure to read the comments so that you understand what it is doing. If you run the program and keep an eye on the 'global variables' debug window, you should find that they count up when the wheels rotate.

//used to store the count of the motor clicks
int leftEncoderCount = 0;
int rightEncoderCount = 0;
 
task main()
{
  //get the state of the encoders so that we know when they have changed
  // for example if the last state was high and the current state is low
  // or vise-versa, then we know that the encoder incremented another click.
  int lastStateLeft = SensorValue[leftEncoder];
  int lastStateRight = SensorValue[rightEncoder];
 
  while(true)
  {
 
    //get the current state of the left encoder
    int state = SensorValue[leftEncoder];
 
    //has the left encoder changed states
    if (lastStateLeft != state) {
      //if so, then increment the leftEncoderCount by 1
      leftEncoderCount++;
 
      // then store the current state as the last state so that we can keep monitoring every change
      lastStateLeft = state;
    }
 
    //do the same for the right encoder.
 
    state = SensorValue[rightEncoder];
    if (lastStateRight != state) {
      rightEncoderCount++;
      lastStateRight = state;
    }
 
    //we add a pause between updates to keep from hogging the CPU and
    // so that we debounce the encoders.
    wait1Msec(10);
  }
}

Monitoring the Encoders and Running a Program Simultaneously

So we know how to read the encoders, but modifying the code to allow us to have the robot perform other tasks would be tricky. So to solve this problem we use multitasking to have the program monitor the encoders in the background.

Breaking out of task main()

Until now, all your logic has executed, step-by-step, within task main(). Now, we are going to turn this code into a background task so that we can use task main() for our other necessary code. Since only task main() is started by default, we will use the StartTask() function to start the encoder monitoring task.

//used to store the count of the motor clicks
int leftEncoderCount = 0;
int rightEncoderCount = 0;
 
//a background task used to monitor the encoders and count the clicks
task encoderTask()
{
  //get the state of the encoders so that we know when they have changed
  // for example if the last state was high and the current state is low
  // or vise-versa, then we know that the encoder incremented another click.
  int lastStateLeft = SensorValue[leftEncoder];
  int lastStateRight = SensorValue[rightEncoder];
 
  while(true)
  {
 
    //get the current state of the left encoder
    int state = SensorValue[leftEncoder];
 
    //has the left encoder changed states
    if (lastStateLeft != state) {
      //if so, then increment the leftEncoderCount by 1
      leftEncoderCount++;
 
      // then store the current state as the last state so that we can keep monitoring every change
      lastStateLeft = state;
    }
 
    //repeat for the right encoder.
 
    state = SensorValue[rightEncoder];
    if (lastStateRight != state) {
      rightEncoderCount++;
      lastStateRight = state;
    }
 
    //we add a pause between updates to keep from hogging the CPU and
    // so that we debounce the encoders.
    wait1Msec(10);
  }
}
 
task main()
{
  StartTask(encoderTask); //Starts encoderTask running. It will keep running in the background for the duration of the program.
 
  //Do whatever. You can access leftEncoderCount and rightEncoderCount from here, and anywhere else.
}

Notepad.gif NOTE: By using multitasking you are able to use the BotBot encoders like a quadrature-encoder. Just replace "SensorValue[]" with the name of the encoder count variable.