Jun 4, 2006

An Array of Solutions

OK, so far we’ve probably painted a pretty picture of the NXT. But some of you are likely saying “wait a minute, where’s the down side?” And there are some – after all, this is first and foremost a toy (educational or otherwise) aimed at kids, not adults with computer science and engineering degrees. So there are some things that are missing from the out-of-the-box kit. In terms of parts, this isn’t a critical problem; I (and a lot of others… you know who you are) have a lot of LEGO around the house, and it’s fully compatible. Even in terms of motors and sensors, the NXT is a more “complete” kit than the RCX (for example, the RCX with three motor ports generally came with only two motors, while the NXT comes complete with a full complement of three motors). But what about the software?

There are (from my viewpoint – again, to be honest, I’m not the target market for this) some things missing that I really wish were built in to the software. Arrays are a really good example: NXT-G has no official support for arrays, yet I find them very useful. But NXT-G is powerful enough that with a little bit of work (and a good deal of fun) I can get around this, and have my own arrays!

The method I’ve used (I’m sure there are others) uses the file system on the NXT. For each element of an array, I just create a very short on-brick file to hold that number: essentially, the array is just a series of numbered files on the NXT. What would be really nice is if you could just add this ability into NXT-G in a way even a kid could understand. Gee, yeah, that would be really nice…

Remember MyBlocks?

Here I’ve created two MyBlocks, ArrayRead (which will read a number from a specific element of the array) and... ArrayWrite (to write a number into the array). Take a look.

With these as MyBlocks, all these messy details are hidden, and almost anybody can use them as easily as the "stock" blocks from the official NXT-G pallets. For instance, to test these MyBlocks I wrote a simple program that just puts five random numbers into an array, and then reads them out to display on the screen. Notice that the code is pretty much self-documenting used this way.

While this is a reasonable way to do arrays, there's a deeper point here. Yes, there are things missing from the language. But in a lot of cases, you can write MyBlocks to patch these holes (like arrays, trig functions, etc.)... and learn (or teach!) something in the process. It this extendability of the language that I think is its greatest strength, and kudos to LEGO and NI for keeping it in. Now, when we need something implemented in the NXT-G language... we can do it ourselves.

Brian Davis


Noel Maywald said...

Great blog guys. I have read it on a daily basis since discovering it in early May.
So far in all the code examples I have not seen anything that resembles the RCX sensor stack. Does this feature still exist?

Brian Davis said...

The structure of a "sensor stack" (a sequence of blocks that execute when a particular sensor condition is met) is not explicit in NXT-G... but some of that functionality is easy to implement. Make a sequence that is simply a loop with a Wait (for some sensor condition) as the first block inside the loop. When that sensor condition is met, the blocks after that will execute. What NXT-G does *not* appear to have is the equivilent to "task priorities", but other thanthat it can do something fairly similar.

The nice thing about this is now, you can have a sequence ("stack") execute in response to lots of different conditions. Not just "the light sensor is brighter than some set value", but things like "either the light sensor is above or below this specified range, or the ultrasonic sensor detects an object closer than 20 cm".

Brian Davis

Anonymous said...

Hello Brian. Thank you for posting the array example. Could you explain the first 2 pictures a little more, please? I guess since I don't have the software I just dn't understand what each of the blocks is for. In the first picture, I understand you take a number and convert it to textstring. Then that textstring outputs to two other red blocks. This is where I am confused. What is happenign in those two red blocks?

In the second picture, you have three red blocks and I'm not understanding the comments and how this process works. Any chance you could provide some more clarification on the read/write process?

Also, is the index# generated randomly? The third picture shows an orange block that I think is a random number generator feeding into the ArrayWrite block. Is this correct? If so, if the loop happens five times isn't it possible that an array element will get overwritten if the random# repeats itself?

Thank you for taking time to go over this. I can't wait to get my MSNXT and start testing the programs.

Chris from Florida

PS: Could you cover programming one or two of the sensors and show us how to configure them or do something interesting with them? Thank you.

Brian Davis said...

Sorry about that: I'm tryint to hit a balance between demonstrating and entertaining, and it's good to know when I miss my mark. So...

In ArrayRead, the MyBlock takes a number (wired in by the yellow wire) and converts it to a string (carried by orange wires), which is then combined with some other text in the next block to make a name like "array-3" or something similar. This is used as the file name (see how it's wired into the plug with a "file folder" symbol?). The first of these two File blocks closes the file (so that if it was open for some reason before, like writing to it, it will be re-opened at a known point - namely the beginning), and the second File block reads out one piece of data from the named file.

ArrayWrite works very simlarly, but closes and deletes any preexisting file by the requested name, to make sure that the number to write into the file is the very *first* piece of data in it.

Essentially I'm doing some file manipulation "behind the scenes"... but by putting it into MyBlocks, I (or a student) don't have to deal with those issues again, but can just use them as array access blocks.

> is the index# generated randomly...

Nope, there are two numbers being wired into the ArrayWrite MyBlock: the first is the index, which is being sourced from the plug coming out of the loop - the "counter". The second input to ArrayWrite is the number to write into the array, and it is wired out of the Random block.

All this is much easier when you are programming: for instance, the specifics of the block configuration appears at the bottom of the screen as you mouse over or select a block, and all the plugs have pop-up tooltips naming them (even the ones you make for your own MyBlocks). It's nearly impossible to convey the amount of information you have availible to you in any form other than a dynamic, graphical one (i.e.- the environment).

Brian Davis

byronczimmer said...

Very Very slick Brian...

What's the IO time like? Any chance of missing a sensor input during an IO read?

Brian Davis said...

Not that I know of. I've not tested the IO time on these actual MyBlocks, but from tests on individual "stock" blocks they are likely somewhat slow. The question is how this effects the execution time of other parallel sequences... and I don't know that (yet...).

Brian Davis

Sivan Toledo said...

This may wear out the flash memory quickly. Flash, which is used to store files on the NXT, has an endurance limit. After you write a certain number of times to a byte (around 100K-1M times), it becomes unusable. This is not a problem for normal downloading of files, but if you write rapidly from a program, you may wear out the flash. It would be better to search for ways to store quickly-changing data in RAM.

Brian Davis said...

I agree, there is a limit to read/write cycles on FLASH (the ARM processor specs state 10,000 write cycles), and this could become a factor. But storing such data in the limited RAM on the chip has problems as well, such as data loss if you lose power. Like I said, I'd prefer it if there was a way to run arrays without this work-around, but the thing I wanted to point out is that such workarounds exist. And even at "just" 10,000 writes (which I suspect is minimum), that means I could re-write the entire memory thiry times a day every day for a year before hitting the limit.

It's a good point to bring up, and one the members of thye MDP and LEGO have given some serious thought to. But I think this is a trade-off here, and I'm using the FLASH memory in a decidedly non-standard fashion.

Brian Davis

Anonymous said...

Arrays using a separate file for each element in the array where each file contains a string representation of a number is not a reasonable way to implement arrays in NXT-G. Try it with 10000 elements and see what happens.

Jim Kelly said...

I have yet to build a bot that might require an array of 10000. Not saying it'll never happen, but Brian's solution was still pretty cool in terms of a homemade solution.

Lighten up.


Anonymous said...

Do we have any capability for reading and writing within a certain byte position in a file? I've been bugging people to find out if it's possible to implement a D-heap with a bunch of MyBlock's. A D-heap has two operations: add something to the heap, and read the "best" (highest or lowest) value from the heap. The heap is organized so the "best" value is always at the first memory location, but after that all bets are off. (It's not really 'sorted', just loosely organized, like a competition bracket.) So reading is easy -- you read and remove that value, and then you 'percolate' the rest of the values down so the next-lowest value is now at the bottom. When you add something to the heap, though, you have to kinda 'percolate' through the heap so your new value lands in the correct spot.

While it sounds like your array method would work for D-heaps (as long as LabView supports recursion...) I think things would be much more efficient if one could read and write to different positions in the same file.

Dick Swan said...

The RobotC IDE currently supports dual-indexed arrays for those that "gotta have it".

There's also been mention of a LUA IDE coming soon. I believe the LUA language also has native support for arrays.

Both of these are 3rd party developed IDEs. RobotC is commercial software available from Carnegie-Mellon Univerisity. I believe LUA will be freeware.

YOu probably don't want to use files. Every sector write takes 3-6 msec while the NXT CPU is stalled. Deleting file, creating new file, writing one byte likely involves at least six sector writes (say 25 msec)!

Anonymous said...

In the array program, the little blocks (labeled index, etc.), i can't figure out how to find them in the mindstorms program. could you help me with this?

Related Posts Plugin for WordPress, Blogger...