MBC Pathfinder 16-Way × Pybricks

Read the Pathfinder 16-Way with MicroPython in three steps

A Pybricks program always follows this order: first import the library, then create an object and give the sensor a name, and only then use that name to call functions. Work through the steps on the left and the program on the right grows with you. Drag the black line in the sensor simulator to see what the program prints.

Your hub:
1

Import the library

The first thing in the program tells Pybricks "I want to use the Pathfinder 16-Way library". Without this line the hub does not understand MBC_LINE16 later on, and you get a NameError.

Choose one library (both work exactly the same; only the import line is different):

  1. Download the library (save the file and keep its name): MBC_line16.py (only this sensor) or MBC_sensors.py (the all-in-one library). You picked MBC_line16.py.
  2. In Pybricks Code, press "Import a file" in the file panel on the left and import it into the same project.
  3. Do not rename the file, and do not put it in a subfolder.
  4. Go back to your main program and write the lines below at the very top (marked ① in the program on the right).
2

Create an object: give the sensor a name

A robot can have several sensors, so you "create an object": you tell the program which port the sensor is on and give it a name. After that, you use this name every time you read a value.

Which port is the sensor on?

Turn on multitasking?

The 3 in the program is the port number: SPIKE 1~6 = A~F. You can also write Port.C, but then you must also import from pybricks.parameters import Port.

3

Use the functions

It always looks like "line16.function_name()": the name, a dot, then the function. Click a function and the program and output change to its example.

Sensor simulator (looking forward from behind the robot): drag the black line and watch the output on the right change

The simulator is only a sketch: the maths is simplified, so a real sensor may differ by one or two steps. The number in each circle is the light value of that channel (SPIKE: 0 = black, 15 = white). Red ring = that channel counts as on the line.

Example for each function

16 functions, each with a short example you can put straight into a loop. Press "Try it" to jump to step 3. The program and output on the right change to that example.

Complete examples

Simple line following + stop at a crossroads (SPIKE, left motor A, right motor B)

        

!Only change the "Change these" part at the top. Robot wobbles left and right: make KP smaller. Robot cannot make the turn: make it bigger. Robot does not stop at the crossroads: make CROSS a little smaller (for example 10). Robot already stops at a T-junction: make it a little bigger (16 at most). Robot drives backwards: move Direction.COUNTERCLOCKWISE to the other motor.

Multitasking (advanced)

        

!When you create the object, write True as the second value. Create the object outside run_task(). Put await in front of every function.

Using it with other MBC sensors

        

!Switch to the all-in-one library: change only the import line and import MBC_sensors.py. Do not import both libraries at the same time.

Things to know

  1. Unplugging does not stop the program. If the sensor cannot be read, you get the last value it read. If it has never been read, you get None. One warning line is printed on the computer, in Chinese and English: MBC: Port C 讀不到感應器,先回傳上一次的值 / no sensor, using the last value. Plug it back in and it works again by itself. Use sensor_ok() to check if it is connected. Tick "Unplug the sensor" in the simulator to see this. If you unplug it while line following, the robot keeps driving with the last position.
  2. Reading again within 10 ms does not slow things down. The same data is read from the sensor at most once every 10 ms (the sensor itself updates every 10 ms), so calling several functions in a row is fine.
  3. The light value range depends on the hub. On SPIKE, each channel's light value is 0 to 15 (all 16 channels are sent in one go, so each channel gets only 4 bits). On EV3, ir_ch() and ir_calibration() give 1 to 9, while edge_l() and edge_r() give 0 to 100. Change your black/white threshold to match (SPIKE: below 8 is black; EV3 edge: below 50 is black).
  4. On EV3, switching to another data group takes about 0.5 seconds. Try to use one group in the same loop: pos100(), width(), edge_l(), edge_r() are one group (the most used for line following); bin_raw(), bitmap(), on_sensors(), junction(), junction_name() are one group; pos16() is a group on its own; ir_ch() and ir_calibration() are one group. Put device_id() and firmware_version() outside the loop. SPIKE does not have this problem.
  5. Direction: stand behind the robot and look forward. A line on the left gives a negative number, a line on the right gives a positive number. Channel 1 is on the far left, channel 16 on the far right.
  6. Lost line and crossroads: when the line leaves the sensor completely, pos16() gives −16 or +16 and pos100() gives −100 or +100 (depending on whether the line left on the left or on the right), so the robot turns back to that side by itself. To check "really no line", use width() == 0. At a crossroads the whole row is black. That is one single piece of line, so junction() is still 1. Use width() >= 11 instead.