This project has moved. For the latest updates, please go here.

Maze Solver Project - Making Turns

Jan 19, 2014 at 3:43 AM
Edited Jan 20, 2014 at 3:32 AM
Hi all,

The Lego IDE has the TANK control which allows setting a 90 degree turn etc.

The API doesn't have a specific method to make turns ( that I can see ).

I would like some help in making left and right 90 degree turns.

I did a quick experiment with setting each motor ( B, C ) to go in different directions and the robot turns
B -40 and C + 20
        await _brick.DirectCommand.TurnMotorAtPowerForTimeAsync(OutputPort.B, -40, 0, 2000, 0, false);
        await _brick.DirectCommand.TurnMotorAtPowerForTimeAsync(OutputPort.C, 20, 0, 2000, 0, false);
Any ideas on how to detect when the turn is completed ?

Thanks, Paul

Update: The API motor commands are basically these:
None of these take a parameter for degrees of turn ( Lego Move Steering Block can specify degree of turn
) thus I think there might be a way to create some new motor commands in the API

__Not sure what the difference is between TurnMotor and StepMotor ?
__
TurnMotorAtPowerAsync(OutputPort ports, int power)
TurnMotorAtSpeedAsync(OutputPort ports, int speed)

StepMotor
StepMotorAtPowerAsync(OutputPort ports, int power, uint steps, bool brake)
StepMotorAtSpeedAsync(OutputPort ports, int speed, uint steps, bool brake)

Time
TurnMotorAtPowerForTimeAsync(OutputPort ports, int power, uint milliseconds, bool brake)
TurnMotorAtSpeedForTimeAsync(OutputPort ports, int speed, uint milliseconds, bool brake)
Coordinator
Jan 23, 2014 at 4:21 PM
The desktop software uses those commands to create their tank driving scheme. Unfortunately we didn't have time to reproduce that here.

The only way to determine when a turn is completed at present is to monitor the port values using the event (or your own poller) to determine when the destination is reached.

Turn motor is continuous. Step motor will turn for a specific number of "steps"...steps are degrees in default mode I believe.
Jan 23, 2014 at 11:53 PM
Edited Jan 23, 2014 at 11:54 PM
Hi peekb,

Thank you for the help !

_The only way to determine when a turn is completed at present is to monitor the port values using the event (or your own poller) to determine when the destination is reached.

Turn motor is continuous. Step motor will turn for a specific number of "steps"...steps are degrees in default mode I believe.
_

STEPS ARE DEGREES in DEFAULT MODE
I can try this speed = 90 : StepMotorAtSpeedAsync(OutputPort ports, int speed, uint steps, bool brake)

For example, I'm checking when the Infrared Sensor Distance > 20 means then there is an open space on the Left Side of the Robot to turn left.
So, I can turn for steps = 90 ( for a 90 degree turn ) and then change the motor to go straight.

Not sure which Sensor Port values you are referring too to monitor the turn.

I might be able to check when the Distance = 20 ( a distance from the wall ) after the turn ? not sure what you mean
since the StepMotor command can STOP the robot after 90 steps.

I'll give it a try tonight and report back.

Thanks, Paul
Jan 24, 2014 at 12:09 AM
I think that he was actually referring to monitoring the values returned from the motors themselves. The motors return a value specifying the current rotational value, so you can check that value to see how far the motor has turned.
Coordinator
Jan 24, 2014 at 4:15 PM
njsokalski wrote:
I think that he was actually referring to monitoring the values returned from the motors themselves. The motors return a value specifying the current rotational value, so you can check that value to see how far the motor has turned.
Exactly what I was saying, but obviously not clearly enough. You can use the InputPort.A/B/C/D values to read the current position of the motor, either directly at will, or using the BrickChanged event.
Jan 24, 2014 at 11:23 PM
@njsokalski @peekb

Ok, thanks for the help !

_"The motors return a value specifying the current rotational value, so you can check that value to see how far the motor has turned."
_
I think that I'm missing a key concept here.

I can save the starting rotational values of each Motor B ( value x ) and C ( value y ) before the turn
and then monitor the real-time value every xxx milliseconds on the Motor Ports B and C.

So are you suggesting the following type of logic ?
Motor B = x to start and then at B = x + K1
or
Motor C = y to start and then at C = y + K2
where K1 and K2 are experientally determined values ( when the turn is complete ).

Meanwhile, I determined that I misunderstood what peekb meant by "motor steps parameter " = turn degrees.
I was thinking that 90 degrees meant the robot would complete the left turn ( ha ha ).

So, it still will require turning both the B and C motors to make the turn.
Below, I tried one case when Motor B ( inside wheel ) spins backward - negative value
and Motor B ( outside wheel ) spins forward to make the left turn.

This weekend, I will start with this simple psuedo-code to see if the robot can navigate around a large shoebox making repeated left turns.

program loop:
move straignt forward ( both motors at same speed )
If Infrared Sensor on Left of Robot Distance > 30 // detect opening on the left of the robot
then make the Left Turn ( see code below )
      Test the realtime Motor B and Motor C values here for completion of the turn ?
repeat.

NOTE: I will need to insert Thread.Sleep( xxx milliseconds ) in the code also.
private async void StepMotorPower_Click(object sender, RoutedEventArgs e)
{
// make Left Turn
            await _brick.DirectCommand.StepMotorAtPowerAsync(OutputPort.B, -30, 0, 100, 0, false); // spin backward at speed -30 for 100 steps
            await _brick.DirectCommand.StepMotorAtPowerAsync(OutputPort.C, 40, 0, 250, 0, false); // spin forward at speed +40 for 250 steps

            // BatchCommands for  StepMotor not supported            
            //_brick.BatchCommand.StepMotorAtPowerAsync(OutputPort.B, -30, 0, 100, 0, false);
            //_brick.BatchCommand.StepMotorAtPowerAsync(OutputPort.C, 40, 0, 240, 0, false);
            //await _brick.BatchCommand.SendCommandAsync();
 }
I will post my findings this weekend.
Please reply if you think I'm on the wrong track.

Thanks, Paul
Jan 25, 2014 at 12:54 AM
Edited Jan 25, 2014 at 12:56 AM
When we say that 1 step = 1 degree, that means the number of degrees the motor turns, not necessarily the wheel(s) or tread(s). To determine the number of steps required to make the wheel rotate 1 degree, you will need to compare the radii of the gears connecting the motor to the wheel and multiply the number of steps by their ratio to each other. Also, when calculating how far 1 step will drive the robot, you need to take into account the radii of the wheel itself. Here are some equations that may help (you will need to convert them to code, these are just the equations):

motorgearradius=40
wheelgearradius=75
wheelradius=125
distancetotravel=1000
stepsperwheeldegree=motorgearradius/wheelgearradius

And then to travel distancetotravel you would use the following to calculate the number of steps:

stepstotraveldistance=(180 x stepsperwheeldegree x distancetotravel)/(wheelradius x Pi)

The key concept here, which is important in just about any project that uses motors, gears, wheels and/or axles is the ratios of the connections between axles (whether it is gears, chains, belts, or anything else) and the circumference of wheels. Hopefully this helps (I'm not always the best at explaining things, so feel free to ask if you need me to further explain this). Good luck!
Coordinator
Jan 26, 2014 at 4:31 PM
Two quick additions:

1) Use the ClearAllChanges method to set the motors back to 0 so you don't need to track their starting positions.
2) The Step commands should be working as BatchCommands. I saw you had it commented out above. If that's not working, it's a bug, so please let me know. :)

Thanks!
Jan 27, 2014 at 5:10 AM
@peekb

Only see ClearChanges method in the API
and don't see the Motor commands under the BatchCommand class either.

I'm going to try to figure out turns without tracking the way you've mentioned since I don't understand it.
I will try various combinations of turning Motors B and C .

Do I have the wrong version of the API ( download about 10 days ago ) ?

Thanks, Paul
Coordinator
Jan 27, 2014 at 5:43 AM
Which platform are you using? Desktop/Phone/WinRT?
Jan 27, 2014 at 4:15 PM
@peekb

I'm using Desktop ( on VS 2013 for Windows on Windows 7 Profess. ).

I don't have Windows 8 ( WinRT ), is that the platform that you are using ?

Thanks, Paul
Coordinator
Jan 27, 2014 at 9:18 PM
Hm...I'm seeing ClearAllDevices and all the motor commands in my testing here with the Desktop API. Are you building the library from source or using the pre-compiled binary? If the latter, downloaded from here or via NuGet? They should all be the same, though. I'm seeing Turn/Step* commands, ClearAllDevices, etc. all under _brick.BatchCommand . Not sure why you wouldn't be, though...
Jan 28, 2014 at 4:55 AM
Hi peekb,

Well, I really don't understand how to download the latest code using a local NuGet app, so I just click on the
download link underneath ISSUES tab and I got a version with the correct code this time.

Don't know why the earlier download has an obsolete version of the Desktop project with the Code folder.

Anyway, I'm able to make the calls now.
So, I will work on the turns and report back.

BTW, I really need to get up to speed on using NuGet as the source control in VS 2012 and VS 2013.
I work alone at the office and don't have any other .Net developers to assist.

Thanks, Paul
Coordinator
Jan 28, 2014 at 4:48 PM
The latest version is found under the Downloads tab above. You want the "Library + Docs" download. That same package is available via NuGet if you get up to speed on that. Check out http://docs.nuget.org/ for more info there. Here's an intro on how to add a package:

http://docs.nuget.org/docs/start-here/Managing-NuGet-Packages-Using-The-Dialog