Line Tracker with Scoop - First project

Hi all.

I am in the process of trying to get my first robot to work. For the most part, I have based my robot on the protobot with a few modifications for a “scoop”. To add additional strength/torque, I have added an additional motor to the arm. I just plan on picking my some styrofoam peanuts and dropping them somewhere.

I have used the line tracker code almost ver batim that was posted here:

I made a slight mod to where all 3 light sensors see all black. This is where I would like the scoop to drop down until it hits the limit switch, move forward a bit to pick up the material, raise up, etc. Before adding my scoop function, I made sure my line tracker code worked. It works perfect! In fact, here it is on YouTube:

The problem is that when I uncomment the scoop() function, the first time it sees black, the arm drops, but the motors for the wheels begin to just crawl. I can also hear the microprocessor “working” but it just stops. Almost as if it is in an infinite loop of some sort. I am attaching my code.

Any assistance would be greatly appreciated!

Many thanks!

Sokkerpunk (yeah, I like soccer :slight_smile: ) (3.97 KB)

I made a slight mod to where all 3 light sensors see all black. This is where I would like the scoop to drop down until it hits the limit switch, move forward a bit to pick up the material, raise up, etc. Before adding my scoop function, I made sure my line tracker code worked. It works perfect! In fact, here it is on YouTube:

The problem is that when I uncomment the scoop() function, the first time it sees black, the arm drops, but the motors for the wheels begin to just crawl. I can also hear the microprocessor “working” but it just stops. Almost as if it is in an infinite loop of some sort. I am attaching my code.

Any assistance would be greatly appreciated!

Many thanks!

Sokkerpunk (yeah, I like soccer :slight_smile: )

To reiterate, the Scoop Drops, but the Robot does not move forward (at typical speed), stop , or raise the Arm??

Looking through your code, the slowest speed, besides STOPPED, would be SPIN_SPEED (55) - 20, which is equal to 35, which is then passed on to the leftSpeed (…) and rightSpeed (…), functions.
These would be the Speeds that the Motors should be at when the scoop ( ) function is called.

So, focusing on the scoop() function, it looks like the right idea, but I am concerend with the While Loop at the Top…

The MCC18 compiler follows ANSI ‘C’, and Kernighan and Ritchie on ANSI ‘C’ say this about a break. [, and instead of Stopping the Arm Motor, it just hit a Physical Limit, it would Stall Out, and cause the rest of the Motors to be effected as well.

Give that a try and see if things work a little better…

The New Code above is still a little “superfluous”, but lets see if that fixes the issue…

I have attached your Project, with the Change I proposed…breakifbreakingwhileOld Code:****New Code:**real slow](“”) (4.19 KB)

Thanks for the reply and suggestion! Good point regarding the break statement within the loop.

The problem I am having is really a bit bizarre. The robot navigates the line just fine and will drop the scoop/arm and then raise the scoop/arm. The problem is when the arm is raised and stopped, the robot itself kind of just stalls out. My objective is to pick up some stuff from one location, navigate the line, then drop it off (rinse and repeat :)). Without the scoop method, the robot will go back and forth all day. With the scoop method, as soon as it lowers and raises the arm one time, it stalls.

I have been stepping through the trackLine function to see if there is a variable I am not setting correctly when the robot completes the execution of the scoop function.

I sincerely appreciate the assistance.

I did not program up a robot, I just stepped through the Code and looked for obvious places where the program could get into an endless loop…

Ahh… So the Scoop Function does do what it suppose to… Well, Scratch the “break” idea, it obviously works.

First off, where and how exactly do you comment out the scoop() Function. Can you post a Code Snippet??

The overview is that your Robot works, because as it transitions from State to State, it has the correct data to make the correct decisions. The current state is determined by past states of the system.

When you invoke the scoop() function, some state information is lost, and therefore, the Robot is unable to continue in its operation.

That seem reasonable. But I am wondering if it might be some input, like a signal from the line Tracker… IIRC, You lower the Arm, Move Forward, Raise the Arm, but you never MOVE BACK, to the place where the Arm was lowered.

The State of the Robot (where it is on the Line) with out the scoop() Function is Different than with the scoop() Function.

For information about State Machines, see these links:
Finite State Machine
Event Driven Finite State Machine
Virtual Finite State Machine
Automata Based Programming
State Transition Table

Another good point regarding the State of the robot before it going into the scoop routine. As far as state, the only thing that is really keeping state is a variable indicating what the “last black” line was…i.e., on the right or the left.

In regards to where I comment out the scoop() function, here is where it gets called. Specifically, it is called from the trackLine() function when all 3 of the light sensors see Black.

if ( (right == BLACK) && (left == BLACK ) ) // If all 3 are black, this is where the scoop method should execute
     scoop ( ) ;

Essentially, all I do is comment out the scoop method ( //scoop() ) so it is never called. Once it goes into the scoop method, all hay breaks loose!

Scoop method being what you assisted me with earlier.

I thought I was going about this a logical way in getting the navigation to work first and then adding scoop…apparently, I was wrong :slight_smile:

So when the Call to scoop(), is not called. the Robot behaves like the Posted Video. When it reaches the End of the Line, when all Three Sensors read Black, it then Turns Around and follows the Line back to the other end??

Well, assuming that none of you code is being corrupted by another part of the Program, you have pretty much three discreet events in the scoop() function:

  1. Lower the Arm.
  2. Moving Forward.
  3. Raise Arm
  4. (and maybe back up)

What happens if you comment out 1 or 2 of the 3?? Does the Behavior of the Robot still act like the scoop() function being called, or not…

I am putting my money on the #2, Moving Forward, So I would comment out Step #2 and see what happens…

I think it is perfectly logical, and I would have proceeded the same way…

Thanks again for the help MarkO!

As you indicated in a prior response, something is up with the state of the robot prior to going into the scoop() function. If everything is commented out of the scoop() function, i.e. just an empty function, it works. However, if any operation is executed in the scoop() function, it stops working.

I tried several different combinations…just lowering the arm and that’s it, lower and then raise arm, no arm movement but secondary wheel movement (move backwards), etc.

The only thing I can have in the scoop() method for it to work is a print statement indicating “I am here”. Anything more, and the robot is stuck with the microprocessor churning away…it is either stuck in a recursive loop somehow or I have it in a state where it has no idea what to do next.

Any other suggestions…other than going outside and yelling at a tree (yep, I have tried that one too :slight_smile: )


WOW!! Totally Weird!!

I will have to do some Heavy Thinking on this one…

So the Print Statement is fine, but all the Motor commands are a problem…

I really am assuming that the WPILIB functions [e.g. SetMotor(…)] are working correctly…

But it did occur to me that your Call Stack is the Deepest, when the Weird Behavior starts to occur…

The Typical Call Stack looks like this, “Main–>trackLine–>leftSpeed–>>SetMotor”, when it is working correctly.

But The Call Stack looks like this, “Main–>trackLine–>scoop–>leftSpeed–>>SetMotor”, when it is not working correctly.

Also, what Version of EasyC are you using and what version of the Master Code are you using.

You can see the Master Code version in the Terminal Window when the Vex Controller Powers Up.

This occurred to me too, but there just isn’t very much going on the stack - I know I’ve used more without issue.

The thing that stands out to me is the “isScooping” variable. It is initialized to 0, but is never reset anywhere else as far as I can see. It is set prior to starting the scoop operation, but if you ever again land on a spot where all three sensors see black and the wheels are stopped, I think you will get stuck.


  • Dean

“isScooping” variable is reset to 0, when Center is black, left is white, right is white.

You are correct… IF the Line Trackers read Center is black, left is black, right is black, before the Center is black, left is white, right is white. There will be no movement.

The question is, when can the variable “isScooping” be reset to “0”, before getting a Center is black, left is white, right is white.

In reply to an earler thread, I am using version easyC V2 for Vex Version The master code version I have loaded is VEX_MASTER_V7_4EASYC.

Also, the isScooping flag was something I was playing around with and have since removed as it did not alter the behavior of the robot with or without it.

I am now starting to chart this out as more of a finite state machine and see where I have gone wrong. Frustrating to get this far and not being able to scoop something!

Again, any suggestions will be greatly appreciated…and thanks so much to those who have responded as it has been very helpful. Thanks!

You guys have really got me thinking about this. Although the line tracking code I got from the forum and modified for my own navigation worked fine. However, I wonder if there is a different “pattern” that I should look for to indicate “time to scoop”. I have been thinking just the end of the line where I can form a “T” so the line trackers will see all black…but that could also happen when not at the end of the line.

I am now beginning to wonder if I should look for a different state. One that I do not have represented is where the center is white and both right and left are black. Maybe instead of a “T”, I have a two strips of black tape with a white center to indicate when it is time to scoop.

Does this sound logical? Or, will I wind up in the same place I am now? Again, the “original” line tracking code has different code when all 3 sensors were black…I just modified this as I believed it would work.

However, with the mention of the finite state machine, I need to indicate time to scoop by a pattern/state that is not already represented.

Unless there are additional suggestions, I am going to give this a quick go. Granted, it is midnight on the east coast and I have to be at work in the morning so I will post my results tomorrow night.

Thanks again!

Excellent!!! That is all Excellent!!!

WOW!!! I am beginning to suspect that it has something to do with the Call Stack…

Could you try something??? Take Everything in the scoop() function, and place it in-line where the Function Call to scoop() was. And try your Test again.
This will reduce one level on the Call Stack… And IF this is a Compiler Issue, that will side step that issue.

Do that… Another way of solving the same problem will be a Valuable Experience, plus giving you more code examples to draw from in the future.

Not a Problem…

We love to work on these sorts of problems

I have some experience with this code, and I think you will find this to be unreliable. The robot spends too much time weaving around the line to guarantee it will see black/white/black at the termination. I think you are best off sticking with black/black/black as the terminal indicator, since this is pretty much guaranteed if you put a large enough black line at the end of the path.

As for how to (re)structure the code. I’d put trackLine() back the way it was, and just have it stop both motors and return when it sees all black. This will give you a tidy function that you can call to find a line and follow it to the end.

I’d then modify scoop() to go forward until all three sensors see white (plus 100ms for good measure). This will mean the black stop line is pretty much under the center of the robot when you scoop.

When trackLine() is called, it’ll put the robot into a spin if all sensors see white (until it picks up the line). This will effectively make the robot U-turn on top of the stop line.

You can then fix up the loop in main() do something like this:

while (1) {

This structure has the added benefit of not ever being very deep on the call stack, which may be the culprit in your current situation.


  • Dean


If I may, $0.02’s worth from a hardware guy:

  1. Have you checked the function of the limit switches? I suggest you try exercising them manually and confirming both that they work (use a DVM to test for continuity or output, as appropriate, depending on the switch type) and that your controller is reading them properly. If you can print the “I am here” message and you can read the limit switches, it seems to me you should be able to have it print the status of the limit switches. That would enable you to see if the limit switches are detecting the end of arm travel. My bet is either they are, and the detection is the triggering event for the undesirable behavior, or they are not being read properly by the controller. (If the switches work when you exercise them manually, but not when the robot is moving the arm, check whether the arm is pushing firmly enough against the limit switches.)

  2. Put a voltmeter on the power input to the controller. If the voltage drops whenever you get “stuck”, that supports MarkO’s stalled-motor theory. If the limit switches aren’t stopping the arm motion, then the arm motor is likely hitting some mechanical barrier, stalling, and “sucking down” the system power supply. (Keep in mind that the current through a motor is highest when it is stalled.)

BTW, how can you “hear the microprocessor “working””? Even in my youth, my hearing was never good enough to detect the ricochet of electrons and holes through silicon. :wink:

Happy Hunting,

In regards to hearing the microprocessor…I probably should have said microcontroller since it is what is making R2D2 type sounds…you are right, I would have some pretty insane sensitive hearing should I be able to pick up the sounds of the microprocessor :slight_smile:

First, thanks a million for all the suggestions from everyone. It has made me approach my project from a much better perspective as well as force me to look closer at my code. In doing this, I uncovered a rather gross and utter lack of attention to detail on my part :frowning:

My main problem was with my scoop method in that as soon as code was executed here the robot would simply cease to operate. Well, in attempting to keep the code clean and readable, I made a mistake and used a reference to a global variable that was incorrect. I was using a different function for my “arm movement” and used a “stop motor” variable that was intended to only be used for the motors driving the wheels. Well, the variable was 0…so, it essentially was throwing the arm motors into a counter-clockwise motion immediately…thus, the reason why it stopped working!

In other words, this error should be classified as I-Dee-Ten-T…read, IDIOT! Duh!

So, I am finally in a good spot in order to fine tune the scooping/dumping, etc. If I hit any additional problems, I will add those to this thread. Once I am complete with this, I will post a video to YouTube as well as my project source in order to help out other folks.

At this point, I will revert back to my original way of dealing with this, and go outside and yell at a tree :slight_smile:


A lot of the time, you can hear the Motors starting to Turn, so they whine a little.

I looked most of it over pretty well…

Uhhh Oh!!! It was Much Worse…

Your Left and Right Arm Motors Turn Opposite Directions when accomplishing their Task, (e.g. Up or Down)… When you set them to STOP_MOTOR, you then were forcing them to Work Against each other… This would cause a Massive Power Draw, and explains the rest of the behavior of your robot…

In the Army we would say, “I spell, India Delta India Oscar Tango”… :wink:

If you setup the Control of the Arm Motors like the Left Motor and Right Motor, you can use the STOP_MOTOR Constant for control.

Don;t do that, the Tree might feel hurt… :wink: