Here is a measuring wheel I made using the NXT and a mindsensors GlideWheel-AS. The NXT displays traveled distance in mm, cm, M, in, ft, or yd, and will automatically show the proper number of significant figures.
The only thing you have to modify in the code, is WHEEL_DIA (wheel diameter in mm), on line six. Note that nearly all (if not all) Lego technic tires have their size molded into the sidewall, in mm, in the format “diameter x width”; so the “RCX wheels” are “81.6 x 15”.
You can optionally modify AS_PORT and AS_ADDR as needed.
You will need the mindsensors library for the sensor, called “AngleSensor-lib.nxc”.
Here is a pong game I made for the NXT. It uses the NXTChuck to read a Wii Nunchuk, and uses the values as the user input to the game.
In the video I was using two NXTChucks and Nunchuks, in two-player game mode. If you want to play single-player, you can change just one line of the program so that it compiles for single-player mode.
You need to have the NXC NXTChuck library, available from Dexter Industries’ downloads page.
Lines 3 through 16 are constants that determine the characteristics of the game. Most of them are fairly self-explanatory. Try changing them, and don’t worry, I have listed all the original values in the program, so you can always change it back really easily. Line 16 tells the compiler to compile for 1 or for 2 controllers.
This is a scanner I made, using the new mindsensors LightSensorArray. The LSA (LightSensorArray) has 8 light sensors spaced about 6.5mm apart. I used a sideways moving scan head, so that I essentially double the scan width resolution (take a reading, move about 3.3mm sideways, and take another reading). At the end of the scan, you can upload the image (as a monochrome .bmp) to the computer, and open it using a photo viewer. The image is 16 pixels tall, and as many pixels wide as the number of rows you told the scanner to scan.
Here is a video of it scanning:
Here is the actual image it scanned while I was taking the video:
Scanned image (enlarged 6 times, and reformatted to png for uploading to the blog)
And here are a few pictures of the scanner:
Lego NXT LSA Scanner – Right
Lego NXT LSA Scanner – Left
Lego NXT LSA Scanner – Bottom
You can download the LSA library (called “LSA-lib.nxc”) from mindsensors.com.
Mindsensors is working on a new NXT sensor, called a Light Sensor Array. It’s similar in form factor to the LineLeader that they have sold previously, but it doesn’t have a PID algorithm built in. Instead, it just gives you access to the individual light sensors, and their binary states. The reason for this, is that the LineLeader was disqualified from many competitions, since it was too much of a “canned” line follower (it did all the necessary calculations on board).
I made a function that you can use to determine where a line is compared to the sensor. It returns a number from 10-80 based on where it “sees” the line. 45 is the middle, so you can compare the position to 45 to determine the offset from being centered on the line. 0 represents no line detected. Use this in conjunction with the LSA library provided by mindsensors.
float ScaleRange(float Value, float ValueMin, float ValueMax, float DesiredMin, float DesiredMax)
{
return (DesiredMax - DesiredMin) * (Value - ValueMin) / (ValueMax - ValueMin) + DesiredMin;
}
float LSA_Get_Average(byte port, byte addr, byte & Bool_LSA_Values, byte & LSA_Array_Values[], byte LSA_Threshold = 40){
Bool_LSA_Values = 0; // Reset from last state
int bit_index_i = 0; // The bit it's working on
int averaging_weight_i = 10; // The weight to add the the Weighted_Position, if the bit is 1
byte total_bits = 0; // The number of bits that are true. This is needed for the division at the end
bool set_bit; // The bit it's working on
char low_bit = 0; // The bit just below the lowest 1
char high_bit = 7; // The bit just above the highest 1
LSA_ReadRaw_Calibrated(port, addr, LSA_Array_Values); // Fill LL_Array_Values with the calibrated values of the 8 sensors
for (byte i = 0; i<8; i++){ // Build a byte with the bits set to the boolean state of the sensors
Bool_LSA_Values = Bool_LSA_Values | ((LSA_Array_Values[i]<=LSA_Threshold?1:0)<<i);
}
float Weighted_Position = 0; // The value that will contain the overall weighted avarage
float Weighted_Position_Adder = 0; // The value that will contain the average adder, based on the effected, but not true sensors
float Absolute_Average = 0;
repeat(8){
set_bit = Bool_LSA_Values >> bit_index_i & 0x01; // Seperate the bits out of the byte
Weighted_Position += set_bit * averaging_weight_i; // Add the 1's to the value
total_bits += set_bit; // If the bit was 1, add 1 to the counter (divide by the sum at the end).
averaging_weight_i+=10; // Set the variables for the next round
bit_index_i++; // ''
}
until((Bool_LSA_Values >> high_bit) & 0x01){ // Determine the bit just above the highest set bit
high_bit--;
if(high_bit==-1)break;
}
high_bit++;
until((Bool_LSA_Values >> low_bit) & 0x01){ // Determine the bit just below the lowest set bit
low_bit++;
if(low_bit==8)break;
}
low_bit--;
if (0 < high_bit && high_bit < 8 && -1 < low_bit && low_bit < 7){ // Both ends can be used
Weighted_Position_Adder = (ScaleRange(LSA_Array_Values[low_bit], LSA_Threshold, 100, 0, 100) - ScaleRange(LSA_Array_Values[high_bit], LSA_Threshold, 100, 0, 100)) / 20;
}
if(high_bit == 8 && low_bit == -1){ // According to logic, blacked out totally
return 45;
}
else{
if(high_bit==8){ // Black off the high side, but not totally blacked out
Weighted_Position_Adder = ScaleRange(LSA_Array_Values[low_bit], LSA_Threshold, 100, -2.5, 2.5);//(100/(100-Threshold)*lower/20)-5;
}
if(low_bit==-1){ // Black off the low side, but not totally blacked out
Weighted_Position_Adder = ScaleRange(LSA_Array_Values[high_bit], LSA_Threshold, 100, 5, 0);//((100/(100-Threshold)*higher/20)-5) *(-1);
}
}
if(low_bit==7&&high_bit==0){ // According to logic, whited out completely
if(LSA_Array_Values[0]<LSA_Array_Values[7]){ // More detection on the low side
Weighted_Position_Adder = ScaleRange(LSA_Array_Values[0], LSA_Threshold, 100, 10, 5);
}
else{
if (LSA_Array_Values[0]>LSA_Array_Values[7]){ // More detection on the high side
Weighted_Position_Adder = ScaleRange(LSA_Array_Values[7], LSA_Threshold, 100, 0, 5) + 82;
}
}
}
//NumOut(54, LCD_LINE5, Weighted_Position_Adder); // The average's adder calculated by the closest non-true bytes
if (Weighted_Position/total_bits+Weighted_Position_Adder){ //Not equal to 0
Absolute_Average = ScaleRange(Weighted_Position/total_bits+Weighted_Position_Adder, 5, 86, 10, 80); // Avaragetotal divided by the number of bits high, plus the adder. Then scale this from 0-82 to 0-80 so it is the same as the LL native average.
}
return Absolute_Average;
}
A while ago I removed a work-around that had been necessary, but I forgot to update the online files. It is now fixes in this V1.12 release (available here).