Jun 12, 2007

Programming Question from our Forum


The following question was posted to our forums by Itry:

"Hi. I'm new to NXT, and trying to figure out the basics of programming. I need a light sensor to detect change in ambient light levels, and if above a certain range to activate rotation of a motor in the forward direction 4 turns & stop, and if below a certain range to activate rotation of the same motor in the reverse direction 4 turns and stop. The motor needs to complete its assigned 4 rotations before being allowed to reverse. The program needs to run continuously, forever, so that once the light level changes beyond the threshold in either direction, the motor will react. HELP?"

Well, here's a screen capture of my solution. My comments in the image should be sufficient to comprehend the program. Maybe other readers can offer up their own ideas.



20 comments:

David Levy said...

I posted my reply and image on the forum here.

Brian Davis said...

I popped up another off-the-cuff answer on the forums as well, below David's reply. None of these, BTW, is the "best" solution - the "best" one depends on what the user's goal is (smallest code? Fastest execution? Clearest written?). Mine does eliminate both a Switch and any use of a second Motor or move block, which I tend to like (easier... at least for me... to follow, and takes up less memory).

--
Brian Davis

Jim Kelly said...

Brian,

Tell me if I'm reading it wrong, but your implementation seems to only work with a single Light sensor value... say it's set to 50 in the Compare block. Then the motor spins forward if it's greater, or reverse if it's less. It doesn't look like it would work if you were testing for >60 and <20 for the two conditions.

Jim

David Levy said...

My interpretation of Brian's is that he first checks for one of two values ( will the motors move or will they not move).

He then checks for direction of movement.

The boolean result"willMove" is passed into the switch block and the direction passed in the move block direction.

Brian Davis said...

David has the essence of it. The Range block establishes if the Light sensor reading is outside a specified range (say, outside of the 20-60 range), while the Compare block just establishes which direction (above 50 would be one way, below 50 the other way, for instance). The Motor block would only execute if the value was outside of the specified range. Note that there is still at least one optimization in my code to make it run still faster... can anybody find it?

--
Brian Davis

David Levy said...

Let me guess...
You'll probably want to get rid of that last remaining switch block and connect yet another wire to the move block i.e. power=0,>0 or duration =0,4

David Levy said...

forgot to add a cheeky emoticon on that lat post ;)

Brian Davis said...

(insert BIG grin). Ain't integer math great?

Yes, you could in fact do away with the Switch all together, by using a series of Math blocks to change the Light sensor value into a zero or something-greater-than-100, but it has certain problems to watch out for as well, not the least of which being that at a power of zero, I'm not sure how if the motor is in a float-like or brake-like mode. For a "deadband" range of 20-60, for instance, you could use something like this:
x = (light sensor reading) - 40
x = x / 20
x = x * 100
The first two operations will generate a zero if the value is between 21 and 59, and something else (+/-1, +/-2, +/-3, etc.) if it is outside that range. The third line will make that result some large number (+/-100 or greater), which you can wire into the Motor block as a power (the Motor block doesn't care about the sign on the power, so there's no reason to "fix" that).

Another slightly speeded-up solution that I was thinking of is to put the Compare block inside the true case of the Switch, just ahead of the Motor block. That way if the Range evaluation isn't going to result in a movement, no time is "wasted" on evaluating the Compare block.

--
Brian Davis

Dean Hystad said...

OK, it's time to confess my ignorance in all things related to the web. Where are all these code images that everyone is talking about. All I can see are the posts, no code.

Jim Kelly said...

Brian has attached a couple of screenshots of NXT-G code in the forums... is that what you're talking about?

Jim

David Levy said...

The original question was posted on the forum . Jim's screen shot was placed on this blog topic to solicit addition interest.
If you follow the comments from the beginning, you'll see a reference for the forum entry where additional screen shots are attached.

Dean Hystad said...

I followed to the forum and scanned through to find David's post. No images.

I read the post again. Particularly the frustrating phrase "see attached images here". No images, and no obvious (to me) links.

What am I doing wrong? Please use non-technical words and pretend like your giving phone support to your grandma.

Jim Kelly said...

Hi, Dean.

Sorry you're having trouble - I'm running Internet Explorer 7 and I can see one small image below David's post/reply on June 11 at 10:06am and I see another small image (thumbnail) for Brian Davis' post on June 11 at 12:45pm.

Not sure why you can't see them... do you possibly see a link to an image instead of a thumbnail? I know some browsers can get set to display a URL/link instead of a thumbnail... unlikely, but possible in your case.

Jim

David Levy said...

Dean,

I'm guessing you weren't logged in ( accessing as guest). I just changed the permission to allow guests to view attachments. Seems like that should have been enabled by default.

Try it again.
David

Dean Hystad said...

Back to the original question.

As is normal for me I prefer a sequential solution.

Loop Forever
{
IF lightSensor < lowerThreshold
RUN MOTOR REVERSE 4 ROTATIONS

IF lightSensor > upperThreshold
RUN MOTOR FORWARD 4 ROTATIONS
}

One Loop
Two switch statements
Two move blocks

Maybe not as small as Brian's solution, but the logic is very obvious.

Brian Davis said...

Dean wrote (& I requote):

> but the logic is very obvious.

And that's a very good point. Understanding your code is an important part, and something that can sometimes get missed in the quest for the "right" way to do it. Another reason I always enjoy seeing a lot of different solutions to problems.

--
Brian Davis

David Levy said...

Dean,
So your pseudo code looks like it closely resembles Jim's screen shot ( on this blog)

If I were to express my screenshot ( on the forum) with pseudo code it would look something like:

Loop Forever
{

IF lightSensor > upperThreshold
RUN MOTOR FORWARD 4 ROTATIONS

ELSE IF lightSensor > lowerThreshold
RUN MOTOR REVERSE 4 ROTATIONS

}

One Loop
Two switch statements (nested)
Two move blocks

To me, slightly easier to read but at the expense of 2nd light sensor reading which Richard pointed out.

Dean Hystad said...

David,

By gosh, you're right. Just remove the logic blocks and change the switch statements from value to sensor and you have the same answer. I'm so excited about my new ability to see attachments on the forum that I forgot to look all the way back up at the start of this post.

Due to the horrible slowness of NXT-G V1.0 I tend to avoid nesting switches. On the beta software doing such things sometimes crashed the application on my PC. The new V1.1 is a vast improvement in that respect.

David Levy said...

tip:
You should be able to post your own attachments ( screen shots) if you register and login to the forum.

Sisiacik said...

Hallo:) I have big problem! My lego robot represents AGV (Automated Guided Vehicle) and goes from one machine to another and unloading its load. It receives 2 messages: "a" and "b". It should do 2 diffrent actions on each message. "a" message means to go, and when lego receives message "b", it should stop and unload loading. And then move again forward. Messages come from simulation program through VisualBasic. Everything is ok, but there is a problem with NXT program. I do not know how to change behaviour when message is changed. When I tried to use sequence beams, it did just one action or it did both, but second action came after few cycles (for example: "a" came, lego moved forward, then "b" came, ang again "a", "b", "a" and robot was still moving. When came third "b", lego unloaded.) I have also tried to use Switch (Receive Message) but there worked just one beam. Is there somebody who could hepl me, pls? Thank you very much and have a nice evening;) Sisi

Related Posts Plugin for WordPress, Blogger...