Robot courier Lesson 4.1 All coursesFor teachersStudy in the app Student Arduino Uno + L298P motor shield
Topic 4 · Lesson 4.1

Finding and counting intersections

The robot notices an intersection, stops at it and does not count the same intersection twice.

2 × 45 min1–2 students per robotPractice

Lesson result

The robot travels along the line with the P-controller and stops at the required intersection. Each intersection is counted once.

You will learn

  • Describe what the sensors at the intersection show.
  • Write down the intersection condition and explain the choice of threshold.
  • Explain why one intersection can be counted many times, and correct it.
  • Stop the robot at the intersection with the given number.

Need to know

  • 3.2 P-controller: smooth and fast

Will need

Line sensor (analog, Trema) × 2

Why this lesson

In the fields of the final task, branches from intersections lead to the loads. To turn into the right place, the robot must notice intersections and know which one is in front of it. Today the robot will learn to find, count and pass intersections.

Warm up · remember
  1. What is the error of the P-controller when the line is exactly in the middle?
  2. What does the sensor show on the 0-100 scale on black?
  3. What does constrain?
1
Lesson 1 · 45 min
Crossroads through the eyes of sensors
1

What sensors see at an intersection

12 min

What should a robot do. The courier must notice the intersection, drive to it and, if necessary, stop. A separate intersection sensor is not needed: we use both line sensors and their readings together.

What we use and how it works. On a regular narrow path, the sensors are located along its edges. On a wide transverse stripe, both can see black at the same time. The program checks this combination and decides whether to continue moving. As long as the sensors remain over one lane, multiple readings refer to one intersection rather than multiple ones.

How to link a dimension to an action. First, let's check the signs on a stationary robot, then entering and exiting the lane. To count, you need to separate the detection of an intersection from driving beyond its border. Otherwise, the fast loop will count the same strip over and over again. Another wide dark area can also give such a signal: the sensors do not know the geography of the field.

Predict

The robot approaches an intersection. What will both gauges show on the 0-100 scale when it is on the cross line?

  1. Upload sketch L32_Error from lesson 3.2.
  2. Slowly move the robot with your hands along the training track through the intersection. Look at the Serial Monitor.
  3. Write down the readings in the journal: on the line in the middle, at the intersection, after the intersection.
It should work

At the intersection, both sensors show almost 0: there is a black transverse line under them.

Predict

The robot approaches an intersection. What will both gauges show on the 0-100 scale when it is on the cross line? And at the bend of the line?

  1. Upload the sketch with the scale from lesson 3.2 (L32_Error or your own template).
  2. Slowly move the robot with your hands along the path through the bend and through the intersection. Look at the Serial Monitor.
  3. Fill out the table and answer: by what criteria can an intersection be distinguished from a bend?
PositionleftLevelrightLevel
Line in the middle
On the bend
At the crossroads
After the intersection
It should work

The table is completed, the sign of the intersection is written down in words.

How many readings does the robot manage to get while driving along the transverse line?

  1. Add a repeat counter to your program from lesson 3.2 loop() and once a second print how many repetitions have passed. Record the number of repetitions per second at operating speed.
  2. Take your speed in mm/s from lesson 2.1 or measure it again.
  3. Calculate: how many repetitions will there be on a transverse line 19 mm wide?
  4. Move the robot by hand through the intersection and compare the readings with your position table.
Hint: How to count

Line time is the line width divided by the speed. Repetitions are the time multiplied by the number of repetitions per second.

It should work

The log contains repetitions per second, speed, calculation of the number of repetitions on the line and readings at the intersection.

2

Intersection condition

10 min

Let's write the rule: intersection - when both sensors see black. “Black” - the reading is less than the threshold of 30.

bool onCrossing() {
  return leftLevel < 30 && rightLevel < 30;
}

&& is read as “and”: the condition is true only if both parts are true.

Hint: Why 30 and not 0

Even on black, the reading is rarely exactly 0, and when moving the robot sees the edge of the line. A threshold of 30 reliably separates the “black” from the “edge”, but it can be adjusted according to your measurements.

It should work

You can explain why the condition does not work at a bend in the line, but does work at an intersection.

Formulate the rule yourself using your notes from the previous step: what indications occur only at an intersection and never on a straight line or a bend?

  1. Write the rule in words in a journal: what should the left sensor have and what should the right sensor have.
  2. Select the “black” threshold according to your measurements. Explain why not 0 and why not 50.
  3. Write the condition in Arduino language. You will need the "and" sign: &&.
Predict

Someone wrote a condition via || (“or”). Where will the robot then stop by mistake?

Hint: How to write “and”

a < 30 && b < 30 is true only if both parts are true.

It should work

In the journal - a rule in words, a threshold with an explanation, a condition and an answer about ||.

Requirement 1. Function onCrossing() replies true on the transverse line and false in all other robot positions.

Check the condition on paper before writing the code. For each position, write down the readings of the left and right sensors on a scale of 0–100 and the response of the function:

PositionleftLevelrightLevelonCrossing()
Line in the middle
Line under one sensor on a steep arc of 125 mm
The line went behind both sensors
Transverse line
  1. Choose a threshold based on your measurements and justify it: what is the margin to the darkest reading outside the intersection?
  2. Find the position where your condition might be wrong. What will the robot do then?
Hint: Where to look for the error

Move the robot with your hands in a 125mm arc from Lesson 3.2: How dark does the “edge” of the line under the sensor become?

It should work

The table is filled in according to measurements, the threshold is justified by the margin, the dangerous situation and its consequences are recorded.

3

Stop at the intersection

20 min
  1. Create a sketch L41_Crossing_Stop. Transfer measurements kp and baseSpeed from the logbook.
Stop at the intersectionL41_Crossing_Stop.ino.ino
const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100; int leftLevel = 100;int rightLevel = 100; int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} // Перекрёсток: оба датчика видят чёрное.bool onCrossing() {  return leftLevel < 30 && rightLevel < 30;} // Ехать по линии, пока не найдём перекрёсток.void followLineToCrossing() {  while (true) {    readSensors();    if (onCrossing()) {      return;    }    followLineStep();  }} void setup() {  setupRobot();  followLineToCrossing();  stopMotors();} void loop() {}
  1. Find the function followLineToCrossing(). Explain to your partner how the program comes out of it.
  2. Place the robot on the line in front of the intersection and start it.
It should work

The robot drives along the line and stops at the first intersection.

How it works: How followLineToCrossing works

while (true) - always repeat. Inside: read sensors; if the intersection is return, that is, exit the function; otherwise take the P-controller step. After exit, the program continues from the line stopMotors(); in setup().

If it doesn't work
What do you seeWhat to do
A robot passes an intersectionLower baseSpeed or raise the threshold to 40
Robot stops at a bendThreshold is too high, try 20
The robot does not moveAre the measurements recorded from the log?
  1. Create a sketch L41_Crossing_Stop according to the template. Transfer measurements kp and baseSpeed from the logbook. The line functions from Lesson 3.2 are already ready.
  2. Write it yourself onCrossing() according to its rule from the previous step, followLineToCrossing() and movement in setup(). Bye onCrossing() is not written, she always answers “crossroads”, and the robot does not move.
Template: stop at the intersectionL41_Crossing_Stop_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях. const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100;int leftLevel = 100;int rightLevel = 100; // ===== Твоя часть: напиши сам ===== bool onCrossing() {  // true — только когда робот на поперечной линии; на прямой и на изгибе — false.  return true;} void followLineToCrossing() {  // Ехать по линии с П-регулятором, пока не найдёшь перекрёсток; на перекрёстке функция заканчивается.} void setup() {  setupRobot();   // Доехать по линии до первого перекрёстка и остановиться.} // ===== Готовое из уроков 3.1–3.2 — не меняй ===== int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} void loop() {}
Predict

What will the robot do if, after searching for an intersection, you forget to stop the motors?

  1. Place the robot on the line in front of the intersection and start it.
Hint: Drive while...

The function repeats the same thing - read the sensors, take a step along the line - and ends when an intersection is found. What loop repeats "always", and how do you exit the function in the middle of it?

Hint: How to exit a function

return inside a function ends it immediately. The program continues from the next line in setup().

It should work

The robot drives along the line and stops at the first intersection. The forecast is recorded.

If it doesn't work
What do you seeWhat to do
A robot passes an intersectionLower baseSpeed or raise the threshold
Robot stops at a bendThreshold too high
The robot does not moveAre the measurements included? Is it written? onCrossing()?

Requirement 2. Continue with your program L32_P_Line from lesson 3.2 and save as L41_Crossing_Stop:

  • the step of the P-controller is moved to the function followLineStep(), reading sensors - in readSensors(); The P-controller works as before;
  • function followLineToCrossing() leads the robot along the line and ends as soon as onCrossing() returned true;
  • in setup() the robot reaches the first intersection and stops;
  • protection without measurements and a pause at the start remain.

Acceptance. The robot stops at an intersection five times out of five and never at an arc of its level.

Hint: Idea (1 of 3)

The “drives until...” function is an infinite loop, from which there is a conditional exit.

Hint: Plan (2 of 3)
  1. Always repeat: read sensors.
  2. Crossroads - exit the function.
  3. Otherwise, the P-controller step.
Hint: Code snippet (3 of 3)

while (true) { readSensors(); if (onCrossing()) { return; } … }

It should work

The program fulfills requirements 1–2, five out of five stops are recorded in the log.

2
Lesson 2 · 45 min
Counting intersections
4

Find the counting error

8 min
Find the mistake · The robot counted 40 intersections

The neighbors wanted to count intersections like this:

void loop() {
  readSensors();
  if (onCrossing()) {
    count = count + 1;
  }
  followLineStep();
}

The robot drove through one intersection, and count became 40. Why?

It should work

You can explain: while the robot is driving along a wide black stripe, the condition is true many times in a row, and each time the counter grows.

Find the error · Pause did not help

The neighbors noticed the double count and added a pause after the count:

void loop() {
  readSensors();
  if (onCrossing()) {
    count = count + 1;
    delay(100);
  }
  followLineStep();
}

The robot drove through one intersection, and count became 3. Why didn't the pause help? How else is it dangerous for driving along the line?

  1. Write your answer in your journal.
  2. Suggest a correction in words: What should the program do after finding an intersection before looking for the next one?
It should work

You can explain why pausing doesn't help and suggest a fix.

Find the error · Score by moment of appearance, but still 40

The neighbors decided to count only the moment when the intersection appeared:

bool was = false;

void loop() {
  readSensors();
  bool now = onCrossing();
  if (now && !was) {
    count = count + 1;
  }
  followLineStep();
}

The robot drove through one intersection, and count still became 40. Where is the error?

  1. Find the error and log the corrected code.
  2. Compare 40 with your calculation of the number of repetitions on the line from the last step. It seems?
  3. Is the score at the moment of appearance worse or better than passing the intersection, which will be in the next step?
Hint: What was stored

When the value changes in this program was?

It should work

The error was found, the correction was written in code, the number 40 was explained by calculation, a comparison of the two methods was written down.

5

Pass the intersection

10 min

To count an intersection once, you need to pass: drive straight until the sensors go black.

void passCrossing() {
  drive(FORWARD, baseSpeed, FORWARD, baseSpeed);
  do {
    readSensors();
  } while (onCrossing());
  delay(100);
}

do { … } while (условие) - do and repeat until the condition is true. A short pause at the end moves the sensors away from the edge of the transverse line.

It should work

Can you explain when the cycle ends in passCrossing().

To count an intersection once, you need to pass: drive straight until the sensors go black. Write a function passCrossing() in the log:

  1. Turn both motors forward at speed baseSpeed.
  2. Read the sensors, bye robot at a crossroads.
  3. After that, wait 100 ms.

do { … } while (условие); - do and repeat until the condition is true.

Hint: Why do and not while

Sensors must be read at least once before checking a condition.

Hint: Why the pause at the end

Immediately after black, the sensors see the edge of the transverse line. What happens if at this moment you look for the intersection again?

It should work

The function is logged. Can you explain when the cycle ends and why there is a pause.

Requirement 3. Function passCrossing() drives straight through the intersection and ends when the sensors are no longer on the cross line or at its edge.

  1. Write a function in your program.
  2. Explore the pause after leaving black: 0, 50, 100, 200 ms. For each, launch the robot through two intersections in a row (in setup() — followLineToCrossing(), passCrossing(), followLineToCrossing(), stop) and mark at which intersection he stopped.
  3. Write down what kind of pause is needed and what it depends on. What happens if you lift baseSpeed?
Pause, msWhere did you stay?What is visible
0
50
100
200
Hint: Idea (1 of 2)

Drive straight and repeat reading the sensors until the intersection condition is true.

Hint: Code snippet (2 of 2)

do { readSensors(); } while (onCrossing()); - why here do, not while?

It should work

passCrossing() is working, the pause table is filled, the conclusion about the relationship between pause and speed is recorded.

6

Stop at the desired intersection

17 min
  1. Create a sketch L41_Count. B TARGET indicate which intersection to stop at.
Counting intersectionsL41_Count.ino.ino
const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100; int leftLevel = 100;int rightLevel = 100; int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} // Перекрёсток: оба датчика видят чёрное.bool onCrossing() {  return leftLevel < 30 && rightLevel < 30;} // Ехать по линии, пока не найдём перекрёсток.void followLineToCrossing() {  while (true) {    readSensors();    if (onCrossing()) {      return;    }    followLineStep();  }} // Проехать перекрёсток прямо, пока датчики не съедут с чёрного.void passCrossing() {  drive(FORWARD, baseSpeed, FORWARD, baseSpeed);  do {    readSensors();  } while (onCrossing());  delay(100);} const int TARGET = 1; // на каком перекрёстке остановиться void setup() {  setupRobot();  for (int i = 1; i < TARGET; i++) {    followLineToCrossing();    passCrossing();  }  followLineToCrossing();  stopMotors();} void loop() {}
Predict

TARGET = 2. How many times will the loop be executed? for? What will the robot do at the first intersection?

  1. Check on a path with three intersections: TARGET = 1, 2, 3.
It should work

The robot stops exactly at the intersection with the number TARGET.

  1. Create a sketch L41_Count according to the template. B TARGET indicate which intersection to stop at.
  2. Write it yourself passCrossing() - according to its entry in the journal - and movement in setup(). Until your part is written, the robot does not move.
Template: counting intersectionsL41_Count_Gaps.ino.ino
// Шаблон среднего уровня. Напиши код в разделе «Твоя часть» по целям в комментариях. const int LEFT_SENSOR_PIN = A4;const int RIGHT_SENSOR_PIN = A5;const int LEFT_DIR_PIN = 7;const int LEFT_SPEED_PIN = 6;const int RIGHT_DIR_PIN = 4;const int RIGHT_SPEED_PIN = 5;const int FORWARD = HIGH;const int BACKWARD = (FORWARD == HIGH) ? LOW : HIGH; // Измерения и настройки из журнала (уроки 3.1 и 3.2).const int LEFT_WHITE = 0;const int LEFT_BLACK = 0;const int RIGHT_WHITE = 0;const int RIGHT_BLACK = 0;float kp = 0.5;int baseSpeed = 100;int leftLevel = 100;int rightLevel = 100;const int TARGET = 1; // на каком перекрёстке остановиться // ===== Твоя часть: напиши сам ===== void passCrossing() {  // Проехать перекрёсток прямо. Функция заканчивается, когда датчики уже не на поперечной линии и не на её краю.} void setup() {  setupRobot();   // Перекрёстки до TARGET — найти и проехать прямо; на перекрёстке номер TARGET остановиться.} // ===== Готовое из уроков 3.2 и 4.1 — не меняй ===== int level(int value, int white, int black) {  long result = (long)(value - black) * 100 / (white - black);  return constrain(result, 0, 100);} void readSensors() {  leftLevel = level(analogRead(LEFT_SENSOR_PIN), LEFT_WHITE, LEFT_BLACK);  rightLevel = level(analogRead(RIGHT_SENSOR_PIN), RIGHT_WHITE, RIGHT_BLACK);} void drive(int leftDir, int leftSpeed, int rightDir, int rightSpeed) {  digitalWrite(LEFT_DIR_PIN, leftDir);  digitalWrite(RIGHT_DIR_PIN, rightDir);  analogWrite(LEFT_SPEED_PIN, leftSpeed);  analogWrite(RIGHT_SPEED_PIN, rightSpeed);} void stopMotors() {  analogWrite(LEFT_SPEED_PIN, 0);  analogWrite(RIGHT_SPEED_PIN, 0);} void followLineStep() {  int error = leftLevel - rightLevel;  int correction = kp * error;  drive(FORWARD, constrain(baseSpeed + correction, 0, 255),        FORWARD, constrain(baseSpeed - correction, 0, 255));} void setupRobot() {  pinMode(LEFT_DIR_PIN, OUTPUT);  pinMode(LEFT_SPEED_PIN, OUTPUT);  pinMode(RIGHT_DIR_PIN, OUTPUT);  pinMode(RIGHT_SPEED_PIN, OUTPUT);  stopMotors();  // Без измерений робот не поедет.  if (LEFT_WHITE == LEFT_BLACK || RIGHT_WHITE == RIGHT_BLACK) {    while (true) {    }  }  delay(2000);} // Перекрёсток: оба датчика видят чёрное.bool onCrossing() {  return leftLevel < 30 && rightLevel < 30;} // Ехать по линии, пока не найдём перекрёсток.void followLineToCrossing() {  while (true) {    readSensors();    if (onCrossing()) {      return;    }    followLineStep();  }} void loop() {}
Predict

TARGET = 3. How many times must the robot drive straight through the intersection?

  1. Check on a path with three intersections: TARGET = 1, 2, 3.
Hint: Repeat as many times as necessary

Loop for from Lesson 1.1 repeats commands a specified number of times. How many intersections do you need to go through before stopping at?

It should work

The robot stops exactly at the intersection with the number TARGET.

Requirement 4. Function goToCrossing(n) leads the robot along the line, passes straight through intersections to n-th and stops at n-m. Save the program as L41_Count.

Acceptance. A path with three intersections, n = 1, 2, 3, three runs each.

nLaunch 1Run 2Launch 3
1
2
3
Predict

What should the function do when n = 0? Decide for yourself, write it down and check that the program does exactly that.

Hint: Plan (1 of 2)

n - 1 times: find an intersection and drive through it. Then find the last one and stop.

Hint: Code snippet (2 of 2)

for (int i = 1; i < n; i++) { … } - how many times the loop will be executed when n = 1?

It should work

Nine runs without an error in the table, behavior when n = 0 selected and verified.

7

Quests by level

10 min
Main · First intersection

Drive along the line to the first intersection and stop at it.

Middle level · Third intersection

Stop at the third intersection, after going straight through the first two. In the middle field of the final task, the robot passes through intersections without turning.

Advanced · Non-stop

Make the robot pass all intersections without stopping and not lose the line after them. Hint: in loop() - if there is an intersection, passCrossing(), otherwise the P-controller step.

Test yourself

Test yourself

Select answers to prepare. They are not stored or evaluated on the site. Take the knowledge test in the course syllabus or discuss the answers with your instructor.

● Basic

1.By what criteria does the program recognize an intersection?
2.What will the expression leftLevel < 30 && rightLevel < 30 return if leftLevel = 10, rightLevel = 80?
3.Why does the intersection counter increase many times at one intersection?
4.What does return do inside followLineToCrossing()?
5.TARGET = 3. How many intersections will the robot pass straight to the stop?

★ Intermediate level

1.The crossings counter starts at 0 and increases at each intersection. At what value should you stop at the third intersection?
2.The intersection condition is written using “or”: leftLevel < 30 || rightLevel < 30. Where will the robot stop?
3.Why is the “black” threshold 30 and not 0?
4.In the template, onCrossing() returns true for now. What does the robot do after starting?
5.Why is there a do ... while loop in passCrossing(), and not while?

★★ Advanced level

1.What should the passCrossing() function do?
2.What helps you not to lose your line immediately after an intersection? Choose all the correct answers.
3.Without a pause after leaving the cross line, the robot sometimes stops immediately after the intersection. Why?
4.Called goToCrossing(2). At what intersection will the robot stop?
void goToCrossing(int n) {  for (int i = 0; i < n; i++) {    followLineToCrossing();    passCrossing();  }  followLineToCrossing();  stopMotors();}
5.On a steep arc, the robot sometimes stops, as if at an intersection. What to check first?

Answer questions at your level. Correct answers needed: Beginner - 4 out of 5; Average - 4 out of 5; Advanced - 4 out of 5. Answers will be checked by the teacher or course program.

Summary

The robot finds intersections and counts them without repetitions. The next step is to turn in the right direction at the intersection and follow the route.

How to confirm the result

For each experiment, save the conditions, program version, observation and conclusion. When comparing attempts, change one reason at a time; unsuccessful attempts also remain in the log. Marking a result refers to actions that have already been completed; there is no need to repeat them for the sake of marking. If the result is not obtained, write down the discrepancy and the next hypothesis to be tested. A model, measurements of a real robot, and an explanation are different types of evidence.

Lesson vocabulary

intersectionThe place where a line is crossed by another line. Both sensors see black at the same time.
thresholdNumber for comparison: a reading less than 30 on a scale of 0–100 is considered black.
while loopRepeats commands as long as the condition is true.
returnImmediately terminates the function and returns the program to where the function was called.