Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

3pi turning off alone


#1

When programming my 3pi, I realized that if I put a speed greater than 120 it switches off by itself when starting the course. On battery reading, it shows that it still has 4047mV available. Will it be the battery is not supplying the current enough to start it at higher speed?

  • The batteries are new, but this error began to happen a few days ago

  • This problem only occurs if it is on the track, if I hold it this does not occur


#2

Hello.

I am sorry you are having trouble with your 3pi turning off. This sounds like a power issue. Can you try running your 3pi after recharging your batteries (if they are rechargeable) or using a fresh set of alkalines?

As for specifically why you are getting that behavior, gearmotors like those on the 3pi will draw current based on their load. The greater the load on the output shaft of the motor, the more current will be drawn (up until the stall current is reached). When current is drawn rapidly, there can be a sag in voltage, which can cause a brownout. It sounds like this is happening with your 3pi, since as it tries to run on a course, it fails, but continues to operate nominally with its motors under less load when you pick it up and hold it.

In general, 4V is a really low voltage to measure for four alkaline batteries in series, and still a low voltage to measure for four rechargeable batteries in series. Additionally, we expect the 3pi to be able to be normally run for a few hours on a single charge. So if your 3pi has been running for a few hours on this set of batteries, what you are experiencing sounds normal.

-Jon


#3

Hello.

I understood, thank you very much, that was really the problem!!

But I have another problem, I need my trail follower to keep going straight after the end of the line, in the case of small runway faults. I’ve seen that it has how to adapt the labyrinth resolver code, but I do not know how

I’ve seen the file “turn.c” which is in C:\libpololu-avr\examples\atmega328p\3pi-mazesolver, however I do not know where to put it in my line follower code, I believe it has to be before start motors, but I have already tried to import this library, or just copy it and paste it and create the file (F7), but this does not work.

And another question is how to use this with PID


#4

In general, to detect the absence of a line you can monitor the raw values of the QTR sensors, and when they all show a reading that indicates there is no line under any of them for a certain amount of time, that is a good indication that the robot is no longer on top of a line. Can you describe in more specific detail what it is you want to do after reaching the end of a line?

-Jon


#5

Hello Jon.

The track in which I will compete will have faults of up to 10 cm, so if the robot detects a fault, he has to continue straight until he finds the other part of the track

[cid:cff76072-8008-48df-8dc2-d36d6daec54e]

The programming part of the engines I used was that, but unsuccessfully:

int main()
{
unsigned int sensors[5];

initialize();

while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);

if(position < 1000)
{
set_motors(0,90);

left_led(0);
right_led(0);
}
else if(position < 3000)
{
set_motors(90,90);
left_led(1);
right_led(1);
}
else if(position == 0)
{
set_motors(70,70);
left_led(0);
right_led(0);
}
else if(position == 4000)
{
set_motors(70,70);
left_led(0);
right_led(0);
}
else
{
set_motors(90,0);
left_led(0);
right_led(0);
}
}


#6

You can just add a conditional statement to your code to check to see if all of the 3pi’s sensors are observing full reflectance (i.e. no line). Here is one way to do this:

if(sensors[0] < 100 && sensors[1] < 100 && sensors[2] < 100 && sensors[3] < 100 && sensors[4] < 100)
	set_motors(90,90);  // continue to drive forward 

-Jon


#7

Thank you very much, I will test as soon as possible and I will tell you the result

Enviado do meu smartphone Samsung Galaxy.

-------- Mensagem original --------


#8

Hello Jon,

I made it! But he has some difficulties in the 90 ° curve, sometimes he goes straight through the curve. My teacher gave me an idea to use “while”, I tried, but to no avail.

I wanted to know if I had to control speed according to the individual value of the sensors as you showed me, so that I could have a higher velocity in the straight lines when he detected according to the value, that he is well centered with the line (of course he has, but I tried to make the control for him to go straight, right and left, but testing him, he didn’t even move).


#9

If you are still using the code from your earlier post (even with the modification I suggested), it sounds like your 3pi is probably recognizing that the line is turning, but it might not be responding quickly enough before it sees that the line is missing. One way to deal with this is to incorporate a short delay (you can try delay_ms(200);) after your turns so that your 3pi has a chance to execute the turning movement fully before reconsidering its options for following the line. You can see other examples of timed movements in turn.c.

-Jon


#10

I was talking to my teacher about reading sensors he does. He does a average, right? But I believe that if I could read them individually to program them, it would be better, because it would have a better accuracy, I think. For both 90 ° and straight curves.

Before testing the program with the delay as you indicated, I would like to show you this code I did. Well, It was supposed to work, but it did not work.

int main()
{
unsigned int sensors[5];

initialize();

while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if(position < 1100)
{
set_motors(-90,90);
}
else if(position < 3000)
{
set_motors(100,100);
}
else
{
set_motors(90,-90);
}
if(position < 100 || position > 3900)
while(1)
{
if(sensors[0] < 100 && sensors[1] < 100 && sensors[2] < 100 && sensors[3] < 100 && sensors[4] < 100)

set_motors(70,70);
if(sensors[0] > 3900 && sensors[1] > 3900 && sensors[2] > 3900 && sensors[3] > 3900 && sensors[4] > 3900)
set_motors(70,70);
}
}
}

The goal was to read the lines, and as soon as it detected that it would not have line “if (position <100 || position> 3900)” would run the program to go straight, until she was detected.

One thing I do not understand is why that values are placed between parentheses in if and else if, but in else no.

I’m going to the tests now! thank you.


#11

The if and else if statements have conditions that must be true for the following block of code to be executed. The block for the final else is only executed if none of the preceding conditions are met. For example, the program won’t reach the else in your latest code unless neither position < 1100 nor position < 3000 are true (basically, it is acting the same as else if (position >= 3000)). I’m not sure if this is what you were asking about, but either way, you might find it helpful to look up if statements in a C++ reference to better understand their syntax and how they work.

From a quick look at your code, the second while(1) loop seems like it shouldn’t be there (it will cause your 3pi to go straight forever as soon as it loses the line for the first time).

-Jon


#12

But how could I solve it then? In some 90 ° curves he it is lost, and does not complete them. I figured while would be the best solution. I thought of taking control of them not by an average displayed, but by the individual value of the sensors, it work if I try to set them with this code? if(sensors[0] > 3900 && sensors[1] > 3900 && sensors[2] > 3900 && sensors[3] > 3900 && sensors[4] > 3900
I tried to use the delays as indicated, but he went crazy, he walked and made random turns.

Talking to my teacher, we created a flow chart to try to solve the 90 ° curve problem, and we make up something similar with this: if he detected the curve, he would trigger the engines to do it, and while he still detected that he was In a curve, he would be checking the value of the sensors, and only when he finished the curve would he start to read to see if have fails in the track.

-------- Mensagem original --------


#13

Can you post what code you tried that added the delays, but didn’t successfully make 90 degree turns?

By the way, if(sensors[0] > 3900 && sensors[1] > 3900 && sensors[2] > 3900 && sensors[3] > 3900 && sensors[4] > 3900 is true when all QTR sensors detect very little reflectance (i.e. a line), so I do not expect that to snippet of code to help you turn.

-Jon


#14

When I did tests on the white part of the track, it gave values 0 and 4000, so I decided to put> 3900. But really, maybe it’s not so good to use this.

I made several attempts, but none worked, but the one I did for first using delay was this, I even recorded a video using this code:

https://youtu.be/cfd4MncadAE (Sometimes it makes the right turn, but sometimes it does not.)

https://i.ytimg.com/vi/cfd4MncadAE/maxresdefault.jpg https://youtu.be/cfd4MncadAE

3pi 90° fails https://youtu.be/cfd4MncadAE
youtu.be

int main()
{
unsigned int sensors[5];

initialize();

while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if(position < 1100)
{
set_motors(-60,90);
}
else if(position < 2900)
{
set_motors(100,100);
}
else
{
set_motors(90,-60);
}
if(sensors[0] < 100 && sensors[1] < 100 && sensors[2] < 100 && sensors[3] < 100 && sensors[4] < 100)
{
set_motors(70,70);
delay_ms(200);
}
}
}

In other attempts I only changed the end of the program, in the part of the white reading

if((position > 1100) || (position <2900))
while(sensors[0] < 100 && sensors[1] < 100 && sensors[2] < 100 && sensors[3] < 100 && sensors[4] < 100)
{
set_motors(70,70);
delay_ms(200);
}

#15

It looks like your 3pi successfully recognizes 90 degree turns, but sometimes notices that the line is missing (and therefore keeps driving straight) before it finishes turning onto the line. One thing you can do to test that idea is to try lowering the speed of the 3pi to see if it makes turning more reliable.

You might try creating a variable that keeps track of whether or not the 3pi is going straight, and then add it to the conditional that checks for the line to ensure that the robot only keeps going straight if it was already going straight. Like:

int main()
{
unsigned int sensors[5];
unsigned char goingStraight;

initialize();
goingStraight = 0;

while(1)
{
unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if(position < 1100)
{
set_motors(-60,90);
goingStraight = 0;
}
else if(position < 2900)
{
set_motors(100,100);
goingStraight = 1;
}
else
{
set_motors(90,-60);
goingStraight = 0;
}

if(sensors[0] < 100 && sensors[1] < 100 && sensors[2] < 100 && sensors[3] < 100 && sensors[4] < 100 && goingStraight)
{
set_motors(70,70);

#16

i can not lowering the speed, why the track I’m going to compete has a ramp, and my robot it needs to be at a speed of at least 140. And I’m also going to use bigger wheels on my robot, because with the current wheels it does not have enough height to climb.

About the code you passed me jon, I tested it, and it made sure the curves, however at the end of the black line it does a spin looking for the line. Look:

Enviado do meu smartphone Samsung Galaxy.

-------- Mensagem original --------


#17

It will be more reasonable to get your entire code working first before beginning to ramp up the speed of your robot. As for your code, I played around with the 3pi in my office and, to get things working, reordered one of the if statements and changed the QTR thresholds to 500. So, the 3pi should keep going straight when it reaches a dead end. How well the code works will depend on the amount of interference from the kinds of lights in the room your 3pi is operating in. So, if you find that this code will not work outright, you might try increasing or decreasing the QTR sensor thresholds (the 500 values).

int main()
{
	unsigned int sensors[5];
	unsigned char goingStraight;

	initialize();
	goingStraight = 0;

	while(1)
	{
		unsigned int position = read_line(sensors,IR_EMITTERS_ON);
		if(sensors[0] < 500 && sensors[1] < 500 && sensors[2] < 500 && sensors[3] < 500 && sensors[4] < 500 && goingStraight)
		{
			set_motors(70,70);
		}
		else if(position < 1100)
		{
			set_motors(-60,90);
			goingStraight = 0;
		}
		else if(position < 2900)
		{
			set_motors(100,100);
			goingStraight = 1;
		}
		else
		{
			set_motors(90,-60);
			goingStraight = 0;
		}
	}
}

By the way, this piece of code:

if(sensors[0] < 500 && sensors[1] < 500 && sensors[2] < 500 && sensors[3] < 500 && sensors[4] < 500 && goingStraight)

will only work with breaks in the line encountered during a straightaway like in your initial diagram. The course you showed in your video combines a 90 degree turn and broken line in a single intersection, which will not be trivial to code with the 3pi.

-Jon


#18

Finally it worked, thanks! I was starting to give up already …

Now I have to make some adjustments in his structure so he can climb up the ramp and get enough traction for this!

Enviado do meu smartphone Samsung Galaxy.

-------- Mensagem original --------


#19

Hello Jon, I’m here again! As still have a time for the challenge (it will occur on 06/10). I wanted to ask you if you could take a look at some of the codes I tried to modify to use in my robot. One is the code with PID and white detection and the other is without PID, but with white detection and maximum speed on the straights. I did some tests but they did not work, so I came to talk to you…
Here they are:
(without PID)

if(sensors[0] < 400 && sensors[1] < 400 && sensors[2] < 400 && sensors[3] < 400 && sensors[4] < 400 && reto)
{
set_motors(90,90);
}
                else if(position > 1500 && position < 2500)
{
set_motors(170,170);
reto = 1;
}
else if(position < 1000)
{
set_motors(-40,90);
reto = 0;
}

else if(position < 3000)
{
set_motors(120,120);
reto = 1;
}
else
{
set_motors(90,-40);
reto = 0;
}
}

(with PID)

int main()
{
unsigned int sensors[5];
unsigned char goingStraight;
unsigned int last_proportional=0;
long integral=0;

initialize();
goingStraight = 0;


while(1)
{

unsigned int position = read_line(sensors,IR_EMITTERS_ON);
if(sensors[0] < 400 && sensors[1] < 400 && sensors[2] < 400 && sensors[3] < 400 && sensors[4] < 400 && goingStraight)
{
set_motors(100,100);
}

int proportional = ((int)position) - 2000;

int derivative = proportional - last_proportional;
integral += proportional;

last_proportional = proportional;

int power_difference = proportional/10 + integral/55000 + derivative*1/1;

const int max = 80;
if(power_difference > max)
power_difference = max;
else if(power_difference < -max)
power_difference = -max;
else if(power_difference <0)
{
set_motors(max+power_difference, max);
goingStraight = 1;
}
else
{
set_motors(max, max-power_difference);
goingStraight = 0;
}
}
}

#20

Can you specifically explain what you expect your code to do, and what your 3pi is actually doing when both your regular and PID-based code is executed? Can you also post videos that clearly show the behavior of your code in each instance? Also, can you start making your code more easily readable by using triple backticks ``` before and after the code blocks? You can click the edit pencil at the bottom right of your posts containing code in this thread, which I have edited to include these backticks, for examples of how this is done. (I recommend placing a blank line before and after the code block to make the raw formatting easier to read.)

-Jon