This is my first robot. The microprocessor is a QIC board and micrrocontroller is the Microchip PIC 16F877. The code is written in PIC C, a C compiler.
The robot is to solve a maze which is black and white. The robot is to stay on the black line and I use two sensors in the front of rover called resistor1 and resistor 2. There are two sensors for turning: resistor3 and resistor4.
The problem is that my code works but it shouldn't! I will only post a sample of my code below:
OK so logically, the resistor 3 detects a left line and the rover starts turning until the counter counts down to 150. However, what actually happens is that the rover starts turning and it stops suddenly when it senses another black line. It's as if (I think) the rover broke the while loop as soon as resistor3 was less than 60.
This is contrary to my experiece in C. The compiler reads the program line by line. I mean for example If I had this:
It does process sequentially unless your doing multi-threaded stuff or possibly using interrupts - which I doubt you are.
If you have a question about a piece of code, try debugging it and removing as much code as you can from around it. Simplify it to only the problem and you might discover the real issue.
Well, I’m not using interrupts or multi-tasking. Infact I just heard of them now. It seems that turn_left() runs in the backgound until the conditions are true i.e. if(resistor3>60).
Is there such a thing is aluto multitasking where the compiler makes decisions based on the time required to execute a function?
I guess I’ll try debugging it more. It’s just annoying. I have the code and I know what it does but can’t explain why.
I think where you have said compile you meant to say execute. The c compiles once and is downloaded to the pic as machine code. If the compiler stops before its done compiling it will be because of an error or errors in the code which should be visible in the output window.
As for the unexpected behaviour. In my limited experience with c/c++ I have found most times unexpected behaviour is caused by a missing brace or brace in the wrong place. As you have not supplied a complete lisiting it is hard to tell if this is the case here.
The code looks ok from what you posted. Have you thought of doing away with the counter and just turning left until a change of state with the sensor. Which is what it sounds like its doing anyway. It’s trying to tell you this is the way I want to do do it. Heheh.
OK. I’ve gone through my code and I can barely work on it any longer due to this problem. If anyone can point out what’s wrong it would be great. Thank you.
// Use Microprocessor as a switch
//Motor1-left Motor2-right //resistor1- left resistor2-right (for correction) //resistor3- left resistor4- right (for turning)
void turn_left() { //counter runs in background (delay?) and as soon resistor1>100 it stops at which point resistor r3>33. //It starts turning when r1<100 and r3>33 and soon as r1>100 it stops. *Position of sensor 3 in front is crucial. long int counter, resistor1; // resistor 2 was ok
then I am amazed it does a left turn at all. I don’t see a call to the turn_left() function in main. You have only called turn_right() for 3 different sets of sensor readings values. Should one of those calls been turn_left() ?
Oh yes those turn_right() calls should be turn_left() calls. I think the problem was with using a counter of 150 which I originally thought was like 2 seconds but is actually only like a few milliseconds. So the program kept jumping back to main and executed this function like a 100 times when it should only execute it once.
Yup… I’m still not sure what would be the best method to make it turn. I’m thinking of making a delay to throw the rover off the black line and then make it turn until it senses a black line again.
Counters are pretty unreliable when used for determining how far a robot turns. Apart from having to trial a number of values until you get the right one. The value will change as the battery goes low. Or surface changes.
With 5 sensors you should be able to do your turns smoothly by reacting to what they read.
I don’t know how they are spread on your bot. But I’d picture a layout like this:
middle sensor3 stays over black line should read black always and if not we’ve gone off the end of the line and need to rotate 180 to get back on.
then inner left2 and right4 should read half black half white to indicate edges of straight line.
then outer left1 and right5 should always read white and if they don’t it indicates the line turns to the left or right.
just implement a switch case statement in main and have it loop through sensor readings and this.
You need to know what the sensor reads over a black surface and a white. And be consistent with those values in your case switches.
case sensor1 = white & sensor2 = white & sensor3 = black & sensor4 = white & sensor5 = white
mov_forward()
break
case sensor1 = white & sensor2 = black & sensor3 = black & sensor4 = white & sensor5 = white
mov_left()
break
case sensor1 = white & sensor2 = white & sensor3 = black & sensor4 = black & sensor5 = white
mov_right()
break
}
}
just add a couple or more cases to implement when sensor 1 or 5 indicate black to implement 90 degree turns. Being that I picture the sensors arrayed from left to right = 1 to 5. I say a couple or more cases for the final states because you do need to distinguish between just straying a bit from the line or a true turn left or right.
I hope this makes sense as its all in my head. The only line follower I’ve built was a kit. But I’m pretty sure it’s right.