View Single Post
  #23  
Old 10-13-2011, 02:22 PM
jpearman's Avatar
jpearman jpearman is online now
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,345
Re: RobotC programming tips

So it was always inevitable that this thread would discuss multi-tasking at some point. RobotC’s ability to run more than one task is IMHO it’s greatest strength, there has been lot’s written describing multi-tasking in it’s different forms but when dealing with RobotC I like to think of it as the ability to run more than one independent program at a time even though these programs are contained within one executable and downloaded together. For some background reading on multi-tasking, wikipedia is not a bad place to start. http://en.wikipedia.org/wiki/Computer_multitasking.

Some will argue that most programs written for the VEX robotics system do not need to use multi-tasking. This to a certain extent is true, back when micro processors were not so powerful much embedded software used a technique where the “tasks”, in this case simply meaning different subroutines, were called one after the other in a so called “main loop”. Each subroutine would determine if it had any actions to take, perform them if necessary and then return. System functions needing immediate attention would be setup to use interrupts but great care had to be taken to make these special interrupt routines fast and efficient. Having said this some of the most complex embedded systems of the 60’s did use a primitive form of multi-tasking, one of the most famous of all was the Apollo guidance computer (AGC), which enabled NASA to land on the moon.

RobotC is, in fact, always using multi-tasking even when you have not created additional tasks yourself. It’s ability to display global variables, sensor values and other parameters is achieved using tasks that are started behind the scenes. These tasks only consume a small amount of the microcontrollers resources, perhaps 5%. We are not going to be concerned with how RobotC switches between tasks for now, perhaps a future post.

OK, so much for the history lesson.

The difficulty in creating a simple multi-tasking example is that almost everything proposed can be done without using multi-tasking, however, just to illustrate the principles involved we will create a very simple piece of code to flash two leds on and off connected to different output ports.

RobotC always needs a main task, this is the entry point for the code, it’s the equivalent of the main function in any C program. From the main task we will start a second task using the StartTask command with a single parameter, the name of the task to start. The call to start the second task is

Code:
StartTask( flashLed_1 );
Both the main and flashLed_1 tasks contain an infinite while loop, that is, a loop that never exits until the program is stopped. This loop prevents the tasks from running out of code to execute and therefore stopping. Sometimes allowing a task to finish can be useful but in general I would not recommend it, perhaps we will cover starting and stopping tasks dynamically in another post.

The contents of the while loop of each task is very similar, change the value on the output port and then wait for a preset amount of time, change the output port value back and then wait some more.

The code also includes another example of using the C preprocessor discussed in an earlier post.
Code:
#if (_TARGET == "Emulator")
This line is testing to see if the code is running on real hardware or on the PC emulator. The PC emulator can be very usefull but does not simulate real sensors, to overcome this in the example we substitute the real sensors for an array of integers by using a definition. If the code is compiled for a real cortex then
Code:
#define SENSOR      SensorValue
will be used, otherwise if running on the PC Emulator a different definition is used and an array also declared.
Code:
#define SENSOR      SensorValueSimulations
int SensorValueSimulations[kNumbOfRealSensors];

Here is the code to play with, if you try this in the PC emulator look for SensorValueSimulations[8] and SensorValueSimulations[9] changing as these represent the first two digital ports.

In part 2 on multi-tasking we will create a more complex example doing something more relevant to VEX robotics.

Code:
#pragma config(Sensor, dgtl1,  LED_1,               sensorDigitalOut)
#pragma config(Sensor, dgtl2,  LED_2,               sensorDigitalOut)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

// Detect if we are running in PC emulation and switch to
// using a simulation of the sensors as we cannot see the real leds
#if (_TARGET == "Emulator")
#define SENSOR      SensorValueSimulations
int SensorValueSimulations[kNumbOfRealSensors];
#else
#define SENSOR      SensorValue
#endif

// Flash the first LED  
task flashLed_1()
{
    while( true )
        {
        // output to 1
        SENSOR[ LED_1 ] = 1;
        wait1Msec( 500 );
        
        // output to 0
        SENSOR[ LED_1 ] = 0;
        wait1Msec( 500 );
        }
}

// Main task - flash the second LED
task main()
{
    // Start the other task
    StartTask( flashLed_1 );
    
    // Do our own thing
    while( true )
        {
        // output to 1
        SENSOR[ LED_2 ] = 1;
        wait1Msec( 250 );
        
        // output to 0
        SENSOR[ LED_2 ] = 0;
        wait1Msec( 250 );
        }
}
Reply With Quote