robotC motor, SensorValue, and vexRT arrays' weird behaivor

Hello! I ran into an interesting find today in the motor, SensorValue, and vexRT arrays in robotC. When running this code:


int k=0;
task main()
{
	clearDebugStream();
	writeDebugStreamLine("c1 %d",Ch1);			//0
	writeDebugStreamLine("c2 %d",Ch2);			//1
	writeDebugStreamLine("c3 %d",Ch3);			//2
	writeDebugStreamLine("c4 %d",Ch4);			//3
	        	        	        	        	        	        //4?
	        	        	        	        	        	        //5?
	writeDebugStreamLine("c1x %d",Ch1Xmtr2); 	//6
	writeDebugStreamLine("c2x %d",Ch2Xmtr2);	        //7
	writeDebugStreamLine("c3x %d",Ch3Xmtr2);	        //8
	writeDebugStreamLine("c4x %d",Ch4Xmtr2);	        //9
	        	        	        	        	        	        //10?
	        	        	        	        	        	        //11?
	        	        	        	        	        	        //12?
	        	        	        	        	        	        //13?
	writeDebugStreamLine("5d %d",Btn5D);		        //14
	writeDebugStreamLine("5u %d",Btn5U);		        //15
	writeDebugStreamLine("6d %d",Btn6D);		        //16
	writeDebugStreamLine("6u %d",Btn6U);		        //17
	writeDebugStreamLine("8d %d",Btn8D);		        //18
	writeDebugStreamLine("8l %d",Btn8L);		        //19
	writeDebugStreamLine("8u %d",Btn8U);		        //20
	writeDebugStreamLine("8r %d",Btn8R);		        //21
	writeDebugStreamLine("7d %d",Btn7D);		        //22
	writeDebugStreamLine("7l %d",Btn7L);		        //23
	writeDebugStreamLine("7u %d",Btn7U);		        //24
	writeDebugStreamLine("7r %d",Btn7R);		        //25
	writeDebugStreamLine("5dx %d",Btn5DXmtr2);	//26
	writeDebugStreamLine("5ux %d",Btn5UXmtr2);	//27
	writeDebugStreamLine("6dx %d",Btn6DXmtr2);	//28
	writeDebugStreamLine("6ux %d",Btn6UXmtr2);	//29
	writeDebugStreamLine("8dx %d",Btn8DXmtr2);	//30
	writeDebugStreamLine("8lx %d",Btn8LXmtr2);	//31
	writeDebugStreamLine("8ux %d",Btn8UXmtr2);	//32
	writeDebugStreamLine("8rx %d",Btn8RXmtr2);	//33
	writeDebugStreamLine("7dx %d",Btn7DXmtr2);	//34
	writeDebugStreamLine("7lx %d",Btn7LXmtr2);	//35
	writeDebugStreamLine("7ux %d",Btn7UXmtr2);	//36
	writeDebugStreamLine("7rx %d",Btn7RXmtr2);	//37
	writeDebugStreamLine("ax %d",AccelX);			//38
	writeDebugStreamLine("ay %d",AccelY);			//39
	writeDebugStreamLine("az %d",AccelZ);			//40
	writeDebugStreamLine("ax2 %d",AccelXXmtr2);	//41
	writeDebugStreamLine("ay2 %d",AccelYXmtr2);	//42
	writeDebugStreamLine("az2 %d",AccelZXmtr2);	//43
	while(k<36)
	{
		writeDebugStream("%d",k);
		writeDebugStreamLine("motor: %d",motor[k]);
		k++;
		wait1Msec(1);
	}
	k=0;
	while(k<5000)
	{
		writeDebugStream("%d",k);
		writeDebugStreamLine("SensorValue: %d",SensorValue[k]);
		k++;
		wait1Msec(1);
	}
	k=0;
	while(k<5000)
	{
		writeDebugStream("%d",k);
		writeDebugStreamLine("vexRT: %d",vexRT[k]);
		k++;
		wait1Msec(1);
	}
	while(true)
		wait1Msec(50);
}

it gets this result:


c1 0
c2 1
c3 2
c4 3
c1x 6
c2x 7
c3x 8
c4x 9
5d 14
5u 15
6d 16
6u 17
8d 18
8l 19
8u 20
8r 21
7d 22
7l 23
7u 24
7r 25
5dx 26
5ux 27
6dx 28
6ux 29
8dx 30
8lx 31
8ux 32
8rx 33
7dx 34
7lx 35
7ux 36
7rx 37
ax 38
ay 39
az 40
ax2 41
ay2 42
az2 43
0motor: 0
1motor: 0
2motor: 0
3motor: 0
4motor: 0
5motor: 0
6motor: 0
7motor: 0
8motor: 0
9motor: 0
10motor: 0
11motor: 0
12motor: 0
13motor: 0
14motor: 0
15motor: 0
16motor: 0
17motor: 0
18motor: 0
19motor: 0
20motor: 0
21motor: 0
22motor: 0
23motor: 0
24motor: 0
25motor: 0
26motor: 0
27motor: 0
28motor: 0
29motor: 0
30motor: 0
31motor: 0
32motor: 0
33motor: 0
34motor: 0
35motor: 0
	        //and then 5000 lines of <>SensorValue: 0 and 5000 lines of <>vexRT: 0

  1. Why is there skips in the vexRT constants between Ch4 and Ch1Xmtr2 and between Ch4Xmtr2 and Btn5D, are there buttons I don’t know about?
  2. Why is the motor array THIRTY SIX numbers long? Shouldn’t it only be 10 because there is only 10 ports? (trying 36 gets the normal array bounds error)
  3. Why is the SensorValue array and vexRT arrays’ length not limited to at least double digits? (normal array bounds error is weirdly missing)

VexRT Enumerated Type constants:
Go ahead and take a look at the RobotC intrinsics file:

#elif defined(VEX) | defined(VEX2)
	//Channels
		Ch1               = 0,    // Channel 1
		Ch2               = 1,    // Channel 2
		Ch3               = 2,    // Channel 3
		Ch4               = 3,    // Channel 4
		Ch5               = 4,    // Channel 5
		Ch6               = 5,    // Channel 6

	// Second receiver / transmitter can also be (optionall) connected
		Ch1Xmtr2          = 6,
		Ch2Xmtr2          = 7,
		Ch3Xmtr2          = 8,
		Ch4Xmtr2          = 9,
		Ch5Xmtr2          = 10,
		Ch6Xmtr2          = 11,
#endif

Looks like Ch5 and Ch6 are in-fact a thing within RobotC designated for VEX and VEX2 Systems. What this is used for, it is difficult to tell - could just be some space for future expansion (without having to push out the 2nd controller values, which could potentially break someones code or something internally). You could take a look at the stream of data between the cortex and controller using something like PixelToast (a cheap aerial) used, then decode the data and check for any references to a fifth or sixth (or 10/11th) channel; though I doubt you would find one.

However, the 13/14 ports are completely missing… But that again can be relegated to simple future expansion, or a logical divider between two different sets of information (think analog and digital inputs).

Motor Array Size:
Now the thing you have to realize about RobotC, is that it has a crazy amount of platforms to support, theirs Vex VexIQ, NXT and EV3 (Lego), RiPi, Arduino etc… And a lot of those platforms share the same keywords for completing certain tasks as VEX. In the case of the motor] keyword ‘thingy’ (someone a little less ignorant of intrinsics and opcodes could tell you the correct terminology), it also has to provide support to EV3 and NXT; which can been seen in this past from robotc_intrinsics.

	// The old definitions are temporarily maintained here as well until the new implementation is confirmed
  // to be working well!

  #if defined(NXT) || defined(EV3)

		typedef enum
		{
		  motorA					= 0,
		  motorB					= 1,
		  motorC					= 2,
		  motorD					= 3,
			//
			// HiTechnic Motor Controllers.
			//    - Each controller supports two motors
			//    = Up to four controllers per sensor port.
			//
			//motorD					=  3,
		  //motorE,

#if defined(NXT)
			mtr_S1_C1_1     =  3,
#elif defined(EV3)
			mtr_S1_C1_1     =  4,
#endif
			mtr_S1_C1_2,
		 	mtr_S1_C2_1,
		  mtr_S1_C2_2,
		  mtr_S1_C3_1,
		  mtr_S1_C3_2,
		  mtr_S1_C4_1,
		  mtr_S1_C4_2,

		  mtr_S2_C1_1,
		  mtr_S2_C1_2,
		 	mtr_S2_C2_1,
		  mtr_S2_C2_2,
		  mtr_S2_C3_1,
		  mtr_S2_C3_2,
		  mtr_S2_C4_1,
		  mtr_S2_C4_2,

		  mtr_S3_C1_1,
		  mtr_S3_C1_2,
		 	mtr_S3_C2_1,
		  mtr_S3_C2_2,
		  mtr_S3_C3_1,
		  mtr_S3_C3_2,
		  mtr_S3_C4_1,
		  mtr_S3_C4_2,

		  mtr_S4_C1_1,
		  mtr_S4_C1_2,
		 	mtr_S4_C2_1,
		  mtr_S4_C2_2,
		  mtr_S4_C3_1,
		  mtr_S4_C3_2,
		  mtr_S4_C4_1,
		  mtr_S4_C4_2,
		} tMotor;

Of familiarity, is the fact that there are exactly 36 definitions here!

(In case your wondering how the type ties into the actual property motor], check out this line which defines the intrinsic ‘motor’:


intrinsic word property(motor, propertyMotorPower, kNumbOfTotalMotors, tMotor);

Input Length Limits?
This is for a combination of the above two reasons; for multi-device support and because, well, why bother? it would just impact your ability to add more platforms or make changes to platforms later. I mean an example is the Arduino mega with some ungodly amount of ports (98 analog and digital ports). What if there was to be 2 extra ports added, you would have to change that limit for all your users and then people would be asking, “well why was it limited to a length of 2 digits anyway?”.

I mean, the reality is that these are enumerable definitions and so it makes little sense to stop you from being able to enumerate through higher numbers as it will just return a constant 0. It’s not like a crazy large array where it is taking up masses of precious space on your cortex. To note, the reason vexRT] is capped is possibly because you are actually inputting something instead of just reading the result of running an input through a function.

Anyway, that’s my two cents. I don’t work for Robomatter nor do I have hundreds of years working with embedded systems, so take what I say with a large block of ice.

vexRT was setup to handle 6 channels of analog control even though we only have 4.

because we support platforms other than VEX, specifically, certain lego platforms can have many more than 10 motors.

Well, first they aren’t really arrays, they are what we call intrinsic functions. vexRT maps to a call to getProperty, when all the analog channels, buttons and a second controller are considered there are 44 different values that can be retrieved.

Thanks @EvolvingJon and @jpearman! That clears everything up… except that I can’t reference two responses that answers my question ;p (sorry @EvolvingJon but I owe @jpearman for the smart motor library and a thousand other similar things)

Ahahah, its alright, without @jpearman I think we would all be lost!
… and I mean, really really lost.

When someone has over 1000 more posts than the one guy who makes the rules and has complete control over the game, you can tell he’s important to the community.