ROBOTC.net Blog  

ROBOTC News

Archive for the ‘PIC’ Category

Three New, Unique VEX Creations

without comments

We’re always happy to see ‘outside-the-box’ robotics inventions, so when we were contacted by a local high school teacher  (Dana Clay from Baldwin-Whitehall School District) with a couple of youtube videos, we were more than curious to see what his class had cooked up. We were not let down. The first video shows a VEX contraption that shoots ping-pong balls through a pipe “hoop” with surprising accuracy. It even has a degree of human interaction; the light sensor can be covered/uncovered to control how far the attached arm rotates.


YouTube Direct Link 

The second video is a very cool movie of a VEX-built robot typing “I LOVE ROBOTS” on a keyboard. Robots controlling computers; now that’s an awesome idea!


YouTube Direct Link 

The final video is of a looped track with a VEX tank tread/catapult combo providing the upwards momentum to keep things rolling smoothly. This is the Ball That Never Stops, people, and it has a catapult; how can you not love it? All three were programmed in ROBOTC, of course. Enjoy!


YouTube Direct Link 

Written by John Watson

September 11th, 2012 at 5:51 pm

Announcing ROBOTC 3.5! Beta Version Available Today

with 5 comments

The ROBOTC Development team is proud to announce thatROBOTC 3.5 for the LEGO Mindstorms, VEX Cortex and PIC, Arduino, and Robot Virtual World platforms will be available on September 7th, 2012. The new ROBOTC 3.5 update will be free-of-charge for ALL existing ROBOTC 3.0 license holders. Download a Beta version (3.45) today to get a sneak peak at all of the new features and enhancements available in ROBOTC 3.5!

ROBOTC 3.5 has a number of new features and enhancements:

  • Full ANSI-C support to support pointers, recursion, and stacks with an updated compiler and updated robot firmware.
  • New and Updated Debugger Windows:
    • “Local Variables” to monitor variables in the current task or function.
      (Note: Local variables are only available when your program is suspended)
    • “Global Variables” to monitor variables available to your entire program.
    • “Call Stacks” to monitor function calls in the currently selected task.
  • Updated Documentation and Wiki (www.robotc.net/wiki) – Still in progress!
  • Support for Standard C commands – sprintf(), sscanf(), support for character arrays, unsigned variables, etc.
  • Support for the Arduino family of controllers (Uno, Mega, Mega 2560) with future support and expanded functionality for the Arduino Leonardo and Due controllers.
  • Updated Robot Virtual Worlds support to include additional sensors and motors.
  • Improved Robot Virtual Worlds performance to simulate more realistic physics and robot behaviors.
  • Support for the new MATRIX building system with the NXT.
  • Many general enhancements and bug fixes – more in-depth change log to come with the ROBOTC 3.5 official release.

Please remember that the Beta available today should not be installed across entire school sites–this is a beta version, so install at your own risk!

You can participate in the ROBOTC 3.45 Beta version by downloading a copy here. Please note that the Beta version will uninstall your existing version of ROBOTC; the Beta will use your existing licensing so there is no need to ‘Deactivate’ before installing. If you have any issues/questions with the ROBOTC Beta, please e-mail betasupport [at] robotc [dot] net for assistance and to alert us of any issues to be fixed between now and release day.

Written by Tim Friez

August 24th, 2012 at 11:24 am

Full Set of Possible Characters for VEX LCD

with 2 comments

Full credit for the work behind this post goes to ROBOTC user Matthieu V. Thanks Matthieu!

The VEX LCD is a fantastic tool, allowing you to display messages and values on the robot with very little effort. Some programmers even use a combination of the screen and input buttons to create a basic user interface on their robots – allowing them to choose between multiple autonomous routines, choose a specific sensor and display its values, and more.

What many programmers don’t know, is that there’s a wider selection of symbols that can be displayed with the LCD! Shown below is a full list of characters that can be displayed, along with their numerical equivalents, in a useful table Matthieu put together.

 

Full character look-up table:

You can download a printable PDF of the table, along with some additional notes, here.

To display any of these custom characters, you should use either the displayLCDChar(); or displayNextLCDChar(); commands as you normally would, but specify the numerical value instead of an actual character in single quotes. For example, the following code will display a right arrow on the very first position (0,0) on the LCD:

task main()
{
//Create and initialize variable x
//Value stored in x must be between 16 and 255
int x = 199;

//Clear Line 0
clearLCDLine(0);

//Display the character associated with the value in x
displayLCDChar(0, 0, x);

//Wait 5 seconds before the program ends, clearing the screen
wait1Msec(5000);
}

Written by Jesse Flot

April 27th, 2012 at 1:58 pm

Posted in Cortex,General News,PIC,VEX

Tagged with

Programming with the new VEX Integrated Encoder Modules

with one comment

ROBOTC 3.06 now includes functionality to support the new VEX Integrated Encoder Modules!

The VEX Integrated Encoder Modules (IEMs) replace the plastic caps on the backs of  2-Wire Motors (269 and 393) with quadrature encoders. Unlike the existing VEX Shaft Encoders, they connect to the Cortex Microcontroller using the I2C port and provide feedback directly from the motor (with the added benefit of not hogging up your digital ports). These encoders will allow you to identify and control how fast the motors spin, how far the robot travels, and what direction it should move.

For more information and assembly instructions for the Integrated Motor Encoder for the VEX 2-wire 393 Motor, click here.

For more information and assembly instructions for the Integrated Motor Encoder for the VEX 2-wire 269 Motor, click here.

I2C Overview

As stated above, these new encoders connect to the single I2C port on the Cortex:

Unlike the DIGITAL and ANALOG ports on the Cortex, having only one I2C port does not limit you to only one I2C device. I2C ports allow multiple devices to be connected in a manner frequently referred to as daisy-chaining:

The Integrated Encoder Modules support this by having built-in sets of input and output pins. A 4-wire cable connects the Cortex to Motor 1, another 4-wire cable connects Motor 1 to Motor 2, another 4-wire cable connects Motor 2 to Motor 3, and so on. In fact, ROBOTC 3.06 will support up to 8 devices on the single I2C port!

Programming Overview

Motors and Sensors Setup

ROBOTC has undergone substantial changes to support the new encoders. Some of the most visually noticeable changes are in the Motors and Sensors Setup. On the Motors tab, the Type drop-down box allows you to choose from the different motors available in the VEX Robotics System:

This is significant because each of the new IEMs return a different number of encoder counts per revolution. Specifically, the IEM for the 2-wire 269 motor measures 240.448 counts per revolution of the motor output shaft. The 2-wire 393 motor measures 627.2 counts per revolution of the output shaft in its default high-torque configuration and  392 counts per revolution of the output shaft in its modified high-speed configuration.

Let’s take a look at a physical robot and configure it using the Motors and Sensors Setup.

  • This robot has two 269 motors with encoders.
  • The right motor is connected on MOTOR port 1. The left motor is connected on MOTOR port 10.
  •  The encoder on the right motor is the first device plugged into the I2C port.
  • The encoder on the left motor is the second device, daisy-chained off of the right motor.

We can configure this in ROBOTC by going to the Robot > Motors and Sensors Setup menu.

On the motors tab, we can enter all of the information necessary so that it matches our physical robot:

Note that:

  • “rightMotor” was configured in port1 as a VEX 269 Motor.
  • rightMotor was “Reversed” so that positive power levels will allow the robot to move forward.
  • The “Encoder” box was checked and “I2C_1″ was chosen since it is the first device plugged in to the Cortex.
  • “leftMotor” was configured in port10 as a VEX 269 Motor.
  • The “Encoder” box was checked and “I2C_2″ was chosen since it is the second device along the daisy-chain.
  • It is not necessary that the order of your motor ports correspond with the order of the I2C ports, although doing so will reduce confusion. It is necessary that your Motors and Sensors Setup perfectly match the physical setup of your robot.

Additionally, you’ll notice that there is also a new “I2C Sensors” tab in the Motors and Sensors Setup:

The additional configuration you can do here is optional. Like existing VEX Sensors, you can use this tab to name your I2C devices and monitor their values in the Sensor Debug Window. Note that these values are the raw values – not adjusted for polarity or the “Reversed” checkbox on the Motors tab.

When you’re done configuring your motors and encoders, you can press OK to apply your changes.

Function Library

In addition to the Motors and Sensors Setup, you’ll also notice new commands available in the Function Library. Most notably, we’ve included the “nMotorEncoder[]” command.

Those of you familiar with the NXT system will be very familiar with the nMotorEncoder[] command. To those who are not, it acts very similarly to the SensorValue[] command you may be more used to. The nMotorEncoder[] command gives you read-write access the value of the encoder associated with the motor specified within the brackets.

Sample Code

For example, in the sample code below, the nMotorEncoder[] command is used to clear the values of the encoders on lines 19 and 20, and then also control the distance the robot moves in the while loop on line 23. This program will cause the robot to move forward for a specified number of encoder counts (1000), while displaying encoder values to the VEX LCD.

#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, I2C_1,     rightIEM,             sensorQuadEncoderOnI2CPort,        , AutoAssign)
#pragma config(Sensor, I2C_2,     leftIEM,                 sensorQuadEncoderOnI2CPort,        , AutoAssign)
#pragma config(Motor,     port1,                        rightMotor,         tmotorVex269, openLoop, reversed, encoder, encoderPort, I2C_1, 1000)
#pragma config(Motor,     port10,                    leftMotor,         tmotorVex269, openLoop, encoder, encoderPort, I2C_2, 1000)
//*!!Code automatically generated by 'ROBOTC' configuration wizard                             !!*//

task main
{
wait1Msec(2000);

//Setup the VEX LCD for displaying encoder values
clearLCDLine(0);
clearLCDLine(1);
displayLCDString(0, 0, "R: ");
displayLCDString(1, 0, "L: ");

//Clear the encoders associated with the left and right motors
nMotorEncoder[rightMotor] = 0;
nMotorEncoder[leftMotor] = 0;

//While less than 1000 encoder counts of the right motor
while(nMotorEncoder[rightMotor] < 1000)
{
//Display the right and left motor encoder values
displayLCDNumber(0, 3, nMotorEncoder[rightMotor], 6);
displayLCDNumber(1, 3, nMotorEncoder[leftMotor], 6);
//Move forward at half power
motor[rightMotor] = 63;
motor[leftMotor]    = 63;
}
}

You can see the code running on an the robot here:

For a more detailed explanation of how this code and encoders work, you should check out the videos in the  Movement > Shaft Encoders section of the VEX Cortex Video Trainer. For more information on the nMotorEncoder[] command and how it is used in the NXT system, check out this video.

Motors Debug Window

Yet another change in ROBOTC to support the new encoders was made in the Motors debug window, found by going to Robot > Debug Windows > Motors. ROBOTC will now display the Type of motor you have connected and the Encoder value as your robot runs.

This window, unlike the Sensor Debug window, will take the motor “Reversed” setting and polarity into account; positive motor powers will always result in positive encoder values and negative motor powers will always result in negative encoder values. In other words, the Encoder column displays the same value that gets returned by the nMotorEncoder[] command.

Conclusion and Future Development

The new VEX Integrated Encoder Modules are a fantastic addition to the VEX Robotics System, which we’re thrilled to support in ROBOTC. That being the case, we have additional improvements with the encoders coming down the pipeline. With integrated encoders, we’ll be able to implement “Encoder Targets” and “PID Control” like we have available for the NXT Platform. With Encoder Targets, you’ll be able to specify a “target” encoder value for the motors to spin to, and the robot will actually slow to a stop at that value, rather than letting its momentum carry it too far. With PID, we’ll be able to use feedback from the encoders to constantly adjust the power levels of the motors so that their physical performance matches what you set in the code – all with no extra effort on your part! Again for lots of additional information on both Encoder Targets and PID Control, check out the Movement > Improved Movement section of Teaching ROBOTC for Mindstorms.

Finally, if the VEX IEM’s seem like something you’d like to have (and they should) you can purchase them for the 2-wire 393 Motors here, and the 2-wire 269 Motors here.

Written by Jesse Flot

March 7th, 2012 at 4:42 pm

Posted in General News,PIC,VEX

Michigan VEX Regionals

without comments

A few weeks ago I came to the VEX Regionals over at Monroe, Michigan which was held at  Monroe High School. This was their first year hosting the VEX competition, and Steve Ketron did a nice job organizing the event.

There were about two dozen teams, and the robots that were built by the teams were phenomenal.

I’ve been fortunate enough to go to several VEX competitions over the years, and this one had a very friendly and relaxed atmosphere. I’d chalk that up to the friendly teams surrounding Monroe that came, and also Steve’s planning for the competition.

Photos

I took several hundred photos AND video for the event. I will post the video as soon as I can get all of them onto youtube.

Note: If you want a photo removed, I completely understand! Just comment on this post letting me know which photo to remove and I will remove it immediately. Your comment will not show up below so it will be anonymous.

NextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnailNextGen ScrollGallery thumbnail
dsc00039
dsc_0006
dsc_0007
dsc_0067
dsc_0068
dsc_0069
dsc_0070
dsc_0072
dsc_0075
dsc_0077
dsc_0078
dsc_0079
dsc_0091
dsc_0099
dsc_0103
dsc_0105
dsc_0106
dsc_0110
dsc_0112
dsc_0114
dsc_0115
dsc_0119
dsc_0121
dsc_0127
dsc_0135
dsc_0138
dsc_0141
dsc_0147
dsc_0164
dsc_0166
dsc_0170
dsc_0171
dsc_0173
dsc_0177
dsc_0178
dsc_0182
dsc_0184
dsc_0187
dsc_0188
dsc_0230
dsc_0231
dsc_0280
dsc_0286
dsc_0290
dsc_0302
dsc_0316
dsc_0336
dsc_0354
dsc_0355
dsc_0374
dsc_0388
dsc_0390
dsc_0391
dsc_0392
dsc_0396
dsc_0406
dsc_0408
dsc_0412
dsc_0416
dsc_0425

Written by Vu Nguyen

November 22nd, 2011 at 9:29 am

3rd Party Sensors with VEX: Sharp IR Rangefinder

without comments

The VEX Robotics System includes a growing, powerful set of official sensors. That said, the electronics world is overflowing with other types of cool and useful sensors. The great news is, both the VEX PIC and the VEX Cortex microcontrollers are extremely versatile and can be used with many of these sensors. Both the VEX PIC and VEX Cortex can be used with Analog Sensors that operate between 0 and 5 volts (+/- .5 volts), and have Power, Ground, and Signal lines.

One such sensor is the Sharp GP2D12 IR Rangefinder.

The Sharp IR Rangefinder allows your robot to determine distance from the nearest object, much like the VEX Ultrasonic Rangefinder. Unlike the VEX Ultrasonic Rangefinder, which uses  sound waves to measure distance, the Sharp IR Rangefinder uses infrared light. On one side of the sensor an infrared LED shines a beam of light, which is reflected back by the closest object, and detected by the receiver on the other side of the sensor. The sensor then uses a method called triangulation to determine how far away the object was.

The basis for triangulation is that objects at different distances will reflect the infrared beam back to the receiver at different angles. The varying angles produce different voltage levels in the sensor, and in turn sensor values that can be used to calculate distance. See below:

The Sharp IR Rangefinder provides very reliable distance values ranging from 10 to 80 centimeters away. One big advantage with using the IR Rangefinder is that it’s not affected by soft for angled objects that cause the VEX Ultrasonic Rangefinder to fail.

One challenge with using the sensor is that the raw values provided do not directly correlate to useful distance values, and they’re also non-linear. This means that we must perform a calculation on the raw sensor data first. Documentation for the sensor tells us that we can calculate the distance using the following formula:

Voltage = 1 / ( Distance + 0.42 )

Which, when rearranged gives us:

Distance = (1/Voltage) – 0.42

One additional challenge is that we can’t directly access the voltage returned by the sensor in our program. What we can access is the sensor value, which is proportional to the voltage – we’ll just have to take a conversion factor into account.

Below is a sample program written for the Sharp IR Rangefinder. It contains the function “IRValue()” which will perform the necessary calculation and return the useful distance data, in centimeters. Note that the “sensorPotentiometer” type was used, since there is no “IR Rangefinder” sensor type in ROBOTC, and the Potentiometer type will return the full, unmodified analog data (unlike other sensor types like the Gyro).

#pragma config(Sensor, in5,    sharp,               sensorPotentiometer)
#pragma config(Motor,  port2,           rightMotor,    tmotorNormal, openLoop, reversed)
#pragma config(Motor,  port3,           leftMotor,     tmotorNormal, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

//Function uses data from the IR Rangerinder to calculate and return distance
int IRValue(tSensors sensorPort, float conversionFactor = .0000469616, float k = .42)
{
return (1.0 / (SensorValue[sensorPort] * conversionFactor)) - k;
}

task main()
{
wait1Msec(2000);
clearLCDLine(0);
clearLCDLine(1);

//While true...
while(true)
{
//If the robot is greater than 25 cm away...
if(IRValue(sharp) > 25)
{
//Move Forward
motor[rightMotor] = 30;
motor[leftMotor] = 30;
}
else
{
//Stop
motor[rightMotor] = 0;
motor[leftMotor] = 0;
}

//Display IR Sensor Data to LCD
displayLCDString(0, 0, "IR Value:");
displayLCDNumber(0, 9, IRValue(sharp), 3);
displayNextLCDString("cm");
}
}

Our Sharp IR Rangefinder was previously configured wired for an older microcontroller called the Handy Board. Like the VEX Cortex and PIC, it had wires for Power, Ground, and Signal, so we were able to use simple jumper wires to adapt it for the Cortex.

Front of the robot with Sharp IR Rangefinder:

Top of the robot, with connection from Sharp IR Rangefinder to VEX Cortex Analog Port 5:

And finally, here’s a video of the code from above running on the robot:

For more information on interpreting and using the data provided by the Sharp IR Rangefinder, check out this tutorial.

Written by Jesse Flot

November 8th, 2011 at 11:13 am

New Materials added to the VEX Cortex Video Trainer!

with one comment

Exciting news! We’ve updated the VEX Cortex Video Trainer with two new sections.

First, we’ve added a section for ROBOTC’s new Natural Language Library. You’ll find tons of print materials, ranging from guides describing each Natural Language command available for the VEX PIC and Cortex to dedicated helper guides for each of the VEX Sensors. You can find the new page in the VEX Cortex Video Trainer by going to the Fundamentals section and choosing Natural Language.

Second, there are 4 new tutorial videos that show how to use the Ultrasonic Rangefinder, complete with helper guides and programming challenges. You can find them by going to Sensing and choosing Forward until Near.

The VEX Cortex Video Trainer is available for free, online. To purchase a copy that you can install on each computer in your classroom, visit the RoboMatter store.

Written by Jesse Flot

October 12th, 2011 at 2:59 pm

New VEX Robot Building Instructions Available!

with one comment

Tired of the same old robot models? Look no further! We’re proud to present a new set of classroom-ready robot building instructions.

First up, we have the new and improved Squarebot 4.0:

Squarebot 4.0 features:

  • 1 VEX Cortex
  • 2 Shaft Encoders
  • 1 Limit Switch
  • 1 Bumper Switch
  • 1 Ambient Light Sensor
  • 1 Ultrasonic Rangefinder
  • 1 Potentiometer
  • 1 VEX LCD Screen
  • 2 Driving Motors
  • 1 Arm Motor

And second, we’ve augmented our popular Swervebot model with an arm!

The Swervebot has a more slender wheelbase and rear caster, making it more suitable for line tracking and fitting in small spaces. It also features:

  • 1 VEX Cortex
  • 2 Shaft Encoders
  • 2 Bumper Switches
  • 3 Line Tracking Sensors
  • 1 Ultrasonic Rangefinder
  • 1 Potentiometer
  • 1 VEX LCD Screen
  • 2 Driving Motors
  • 1 Arm Motor

Note that having all of the sensors isn’t required to take advantage of these great robot models. Build them using the parts that you have – or just use the instructions for your own inspiration.

These models along with many others can always be found at the Robotics Academy site.

Written by Jesse Flot

August 8th, 2011 at 1:54 pm

ROBOTC Interview with Robotics Trends

without comments

Down in Orlando, Florida a few weeks ago at the VEX World Championships, Rich Erb from Robotics Trends interviewed me about ROBOTC. We discussed ROBOTC and our future developments with Robot Virtual Worlds and Multi-Robot communications projects. Take a look!

Written by Tim Friez

May 4th, 2011 at 11:21 am

Cortex “View Mode” Program

without comments

In an earlier blog post, we introduced the VEX LCD and showed how to print custom messages and values to it. Being able to print messages and sensor values adds some awesome functionality to your robot… but why stop there, when there’s so much more potential?

Many NXT (and even RCX!) users  are familiar with the  “View Mode” on their microcontrollers, that allows them to specify what sensors are connected to which ports, and then view those values on the screen. Without a built-in screen, VEX users haven’t had access to this functionality… that is, until now! If you have the VEX LCD, the code in this post will allow you to specify a sensor, specify which port it’s on, and then watch the sensor values update in real-time.

Step 1: Download and run the sample program on your robot (see below).

Step 2: Select the type of sensor connected to your robot. The left and right buttons cycle through the options. The middle button selects the current sensor.

Step 3: Select the port the sensor is connected to. For sensors with more than one wire, choose the FIRST port the sensor is plugged into (remember, sensors with more than two wires must be plugged in on neighboring ports on the Cortex). There is also a “Back to Sensors” option that will take you back to the sensor option menu.

Step 4: View the sensor data! Pressing the center button will exit, and return you to the sensor selection menu.

The sample code can be copied into ROBOTC, or you can download a copy here. Note: This code has not been fully optimized, but should work fine as-is.

//Global Variable Declarations
const short leftButton = 1;
const short centerButton = 2;
const short rightButton = 4;
short sensorChoice;
short portChoice;
short count;

//Task and Function Prototypes
void waitForPress();
void waitForRelease();
void clearPorts();

task sensorChooser();
task digitalPortChooser();
task analogPortChooser();
void menuTracker();

task display();
void analogSensorSetup(tSensors sensorPort);
void digitalSensorSetup(tSensors sensorPort);

//Main------------------------------------------------------------
task main()
{
 StartTask(sensorChooser);
 while(true)
 {
 wait1Msec(50);
 }
}
//----------------------------------------------------------------

//sensorChooser - allows you to choose which sensor you'd like to pick
task sensorChooser()
{
 //Junk Cleanup from previous runs
 clearLCDLine(0);
 clearLCDLine(1);
 clearPorts();
 waitForRelease();
 StopTask(display);
 StopTask(digitalPortChooser);
 StopTask(analogPortChooser);

 hogCPU();

 count = 0;
 while(true)
 {
 switch(count){
 case 0:
 //Touch
 displayLCDCenteredString(0, "Touch Sensor");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 0;
 releaseCPU();
 StartTask(digitalPortChooser);
 }
 else if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count = 6;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count++;
 }

 break;
 case 1:
 //Quadrature Encoder
 displayLCDCenteredString(0, "Quad Encoder");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 1;
 releaseCPU();
 StartTask(digitalPortChooser);
 }
 else
 menuTracker();
 break;
 case 2:
 //Ultrasonic
 displayLCDCenteredString(0, "Ultrasonic");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 2;
 releaseCPU();
 StartTask(digitalPortChooser);
 }
 else
 menuTracker();
 break;
 case 3:
 //Light
 displayLCDCenteredString(0, "Light Sensor");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 3;
 releaseCPU();
 StartTask(analogPortChooser);
 }
 else
 menuTracker();
 break;
 case 4:
 //Line Tracker
 displayLCDCenteredString(0, "Line Tracker");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 4;
 releaseCPU();
 StartTask(analogPortChooser);
 }
 else
 menuTracker();
 break;
 case 5:
 //Potentiometer
 displayLCDCenteredString(0, "Potentiometer");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 5;
 releaseCPU();
 StartTask(analogPortChooser);
 }
 else
 menuTracker();
 break;
 case 6:
 //Accelerometer
 displayLCDCenteredString(0, "Accelerometer");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 sensorChoice = 6;
 releaseCPU();
 StartTask(analogPortChooser);
 }
 else if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count--;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count = 0;
 }
 break;
 }
 }
}
//----------------------------------------------------------------

//digitalPortChooser - allows you to choose which port you'd like to pick
task digitalPortChooser()
{
 StopTask(sensorChooser);
 hogCPU();

 count = 1;  //Chooses the starting point

 while(true)
 {
 switch(count){
 case 0:
 //Back Option
 displayLCDCenteredString(0, "Back to Sensors");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 releaseCPU();
 StartTask(sensorChooser);
 }
 else if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count = 12;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count++;
 }
 break;
 case 1:
 //Digital 1
 displayLCDCenteredString(0, "DIGITAL 1");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 1;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 2:
 //Digital 2
 displayLCDCenteredString(0, "DIGITAL 2");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 2;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 3:
 //Digital 3
 displayLCDCenteredString(0, "DIGITAL 3");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 3;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 4:
 //Digital 4
 displayLCDCenteredString(0, "DIGITAL 4");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 4;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 5:
 //Digital 5
 displayLCDCenteredString(0, "DIGITAL 5");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 5;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 6:
 //Digital 6
 displayLCDCenteredString(0, "DIGITAL 6");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 6;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 7:
 //Digital 7
 displayLCDCenteredString(0, "DIGITAL 7");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 7;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 8:
 //Digital 8
 displayLCDCenteredString(0, "DIGITAL 8");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 8;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 9:
 //Digital 9
 displayLCDCenteredString(0, "DIGITAL 9");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 9;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 10:
 //Digital 10
 displayLCDCenteredString(0, "DIGITAL 10");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 10;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 11:
 //Digital 11
 displayLCDCenteredString(0, "DIGITAL 11");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 11;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 12:
 //Digital 12
 displayLCDCenteredString(0, "DIGITAL 12");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 12;
 releaseCPU();
 StartTask(display);
 }
 else if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count--;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count = 0;
 }
 break;
 }
 }
}
//----------------------------------------------------------------

//analogPortChooser - allows you to choose which port you'd like to pick
task analogPortChooser()
{
 StopTask(sensorChooser);
 hogCPU();

 count = 1;//Chooses the starting point

 while(true)
 {
 switch(count){
 case 0:
 //Back Option
 displayLCDCenteredString(0, "Back to Sensors");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 releaseCPU();
 StartTask(sensorChooser);
 }
 else if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count = 8;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count++;
 }
 break;
 case 1:
 //Analog 1
 displayLCDCenteredString(0, "ANALOG 1");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 13;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 2:
 //Analog 2
 displayLCDCenteredString(0, "ANALOG 2");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 14;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 3:
 //Analog 3
 displayLCDCenteredString(0, "ANALOG 3");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 15;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 4:
 //Analog 4
 displayLCDCenteredString(0, "ANALOG 4");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 16;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 5:
 //Analog 5
 displayLCDCenteredString(0, "ANALOG 5");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 17;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 6:
 //Analog 6
 displayLCDCenteredString(0, "ANALOG 6");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 18;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 7:
 //Analog 7
 displayLCDCenteredString(0, "ANALOG 7");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 19;
 releaseCPU();
 StartTask(display);
 }
 else
 menuTracker();
 break;
 case 8:
 //Analog 8
 displayLCDCenteredString(0, "ANALOG 8");
 displayLCDCenteredString(1, "<     Enter    >");
 waitForPress();

 if(nLCDButtons == centerButton)
 {
 waitForRelease();
 portChoice = 20;
 releaseCPU();
 StartTask(display);
 }
 if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count--;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count = 0;
 }
 break;
 }
 }
}
//----------------------------------------------------------------

//Clear Ports-----------------------------------------------------
void clearPorts()
{
 hogCPU();
 SensorType[in1] = sensorNone;
 SensorType[in2] = sensorNone;
 SensorType[in3] = sensorNone;
 SensorType[in4] = sensorNone;
 SensorType[in5] = sensorNone;
 SensorType[in6] = sensorNone;
 SensorType[in7] = sensorNone;
 SensorType[in8] = sensorNone;

 SensorType[dgtl1] = sensorNone;
 SensorType[dgtl2] = sensorNone;
 SensorType[dgtl3] = sensorNone;
 SensorType[dgtl4] = sensorNone;
 SensorType[dgtl5] = sensorNone;
 SensorType[dgtl6] = sensorNone;
 SensorType[dgtl7] = sensorNone;
 SensorType[dgtl8] = sensorNone;
 SensorType[dgtl9] = sensorNone;
 SensorType[dgtl10] = sensorNone;
 SensorType[dgtl11] = sensorNone;
 SensorType[dgtl12] = sensorNone;
 releaseCPU();
}
//----------------------------------------------------------------

//Wait for Press--------------------------------------------------
void waitForPress()
{
 while(nLCDButtons == 0);
 {
 wait1Msec(5);
 }
}
//----------------------------------------------------------------

//Wait for Release------------------------------------------------
void waitForRelease()
{
 while(nLCDButtons != 0);
 {
 wait1Msec(5);
 }
}
//----------------------------------------------------------------

//Function to increment and decriment count - small savings on space
void menuTracker()
{
 if(nLCDButtons == leftButton)
 {
 waitForRelease();
 count--;
 }
 else if(nLCDButtons == rightButton)
 {
 waitForRelease();
 count++;
 }
}
//----------------------------------------------------------------

//Display---------------------------------------------------------
task display()
{
 StopTask(analogPortChooser);
 StopTask(digitalPortChooser);
 hogCPU();

 switch(portChoice){
 case 1:
 //Digital Port 1
 digitalSensorSetup(dgtl1);
 break;
 case 2:
 //Digital Port 2
 digitalSensorSetup(dgtl2);
 break;
 case 3:
 //Digital Port 3
 digitalSensorSetup(dgtl3);
 break;
 case 4:
 //Digital Port 4
 digitalSensorSetup(dgtl4);
 break;
 case 5:
 //Digital Port 5
 digitalSensorSetup(dgtl5);
 break;
 case 6:
 //Digital Port 6
 digitalSensorSetup(dgtl6);
 break;
 case 7:
 //Digital Port 7
 digitalSensorSetup(dgtl7);
 break;
 case 8:
 //Digital Port 8
 digitalSensorSetup(dgtl8);
 break;
 case 9:
 //Digital Port 9
 digitalSensorSetup(dgtl9);
 break;
 case 10:
 //Digital Port 10
 digitalSensorSetup(dgtl10);
 break;
 case 11:
 //Digital Port 11
 digitalSensorSetup(dgtl11);
 break;
 case 12:
 //Digital Port 12
 digitalSensorSetup(dgtl12);
 break;
 case 13:
 //Analog Port 1
 analogSensorSetup(in1);
 break;
 case 14:
 //Analog Port 2
 analogSensorSetup(in2);
 break;
 case 15:
 //Analog Port 3
 analogSensorSetup(in3);
 break;
 case 16:
 //Analog Port 4
 analogSensorSetup(in4);
 break;
 case 17:
 //Analog Port 5
 analogSensorSetup(in5);
 break;
 case 18:
 //Analog Port 6
 analogSensorSetup(in6);
 break;
 case 19:
 //Analog Port 7
 analogSensorSetup(in7);
 break;
 case 20:
 //Analog Port 8
 analogSensorSetup(in8);
 break;
 }
 releaseCPU();
 StartTask(sensorChooser);
}
//----------------------------------------------------------------

//Creates the analog sensor to be displayed
void analogSensorSetup(tSensors sensorPort)
{
 switch(sensorChoice){
 case 3:
 SensorType[sensorPort] = sensorLineFollower; //Change to sensorReflection
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Light:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 4);
 wait1Msec(100);
 }
 break;
 case 4:
 SensorType[sensorPort] = sensorLineFollower;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Line Tracker:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 4);
 wait1Msec(100);
 }
 break;
 case 5:
 SensorType[sensorPort] = sensorPotentiometer;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Potentiometer:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 4);
 wait1Msec(100);
 }
 break;
 case 6:
 SensorType[sensorPort] = sensorAccelerometer;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Accelerometer:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 4);
 wait1Msec(100);
 }
 break;
 }
}
//----------------------------------------------------------------

//Creates the digital sensor to be displayed----------------------
void digitalSensorSetup(tSensors sensorPort)
{
 switch(sensorChoice){
 case 0:
 SensorType[sensorPort] = sensorTouch;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Touch:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 1);
 wait1Msec(100);
 }
 break;
 case 1:
 SensorType[sensorPort] = sensorQuadEncoder;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Quad Encoder:");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 6);
 wait1Msec(100);
 }
 break;
 case 2:
 SensorType[sensorPort] = sensorSONAR_cm;
 clearLCDLine(0);
 displayLCDPos(0,0);
 displayNextLCDString("Ultrasonic (cm):");
 while(nLCDButtons != 2)
 {
 clearLCDLine(1);
 displayLCDPos(1,0);
 displayNextLCDNumber(SensorValue[sensorPort], 4);
 wait1Msec(100);
 }
 break;
 }
}
//----------------------------------------------------------------

Written by Jesse Flot

March 16th, 2011 at 11:48 am