Pixy2 can be used in combination with different hardware platforms, which makes it such a versatile and powerful device. Among these platforms are widely used platforms like Raspberry Pi and LEGO Mindstorms EV3. If you like to program in Python or MicroPython on any of these platforms, this is your resource to find out how.
Each platform has its own characteristics. The way of communicating between Pixy2 and the platform is an important one. For instance, using Raspberry Pi communication goes via USB. If your using LEGO Mindstorms EV3 then you have to use I2C serial communication and connect Pixy2 with the cable delivered with the LEGO version of Pixy2.
In this tutorial we will describe the following platforms:
This tutorial belongs to Pixy2 and Pixy2.1. If you own the previous Pixy, go to the chapter “Pixy for LEGO Mindstorms” in the tutorial over here, written by one of our customers which explains how to use Pixy on LEGO Mindstorms EV3.
If you like to program in Python3, then ev3dev is your best choice. Ev3dev is a Debian Linux-based operating system that runs on several LEGO® Mindstorms compatible platforms including the LEGO® MINDSTORMS EV3 and the Raspberry Pi-powered BrickPi and PiStorms. Just write the image of the ev3dev operating system on a SD-card, put in in your EV3-brick and turn it on. The ev3dev website gives a clear explanation how to use it. To follow this tutorial you need a basic understanding of ev3dev.
A plus for using MicroPython on your EV3 is that it runs a lot faster. If you want to use MicroPython then PyBricks is the best solution. PyBricks is approved by the LEGO Group and you can find downloads on their LEGO Education website. If you like to use the latest version of PyBricks, you better download it from the PyBricks website. Follow the instructions on the EV3 installation page.
To make programming more easy for you, we developed a Python API to use Pixy2
on the EV3. To use this API you have to install module pixycamev3
.
The same API can be used with both Python3 and MicroPython. The
only difference is the way you install the API. When installed, using our
API with Python3 is exactly the same as with MicroPython. But first you have
to setup Pixy2.
First configure Pixy2 to communicate over I2C
. For this you can use the
PixyMon tool. You can find a full reference of PixyMon here.
Connect Pixy2 with the USB cable to your computer and run
PixyMon. In PixyMon open the configure dialog and select the Interface
tab.
If you don't see the Interface
tab, you're probably not running the
right firmware on Pixy2. Be sure to run the stock version, instead of the
LEGO version. See this page on how to install firmware
on Pixy2.
Set Data out port
to I2C
and I2C address
to 0x54
(or any other
address you like). Save your settings, close the configure dialog, close
PixyMon and detach Pixy2 from your computer.
This Python API works both with Python3 and MicroPython. There are two ways you can walk to use the API:
At the moment this method only works for Python3.
First login to your EV3 using ssh
. Run the following command
in a terminal window on your computer:
$ ssh [email protected]
where robot
is the default username in ev3dev and xxx.xxx.xxx.xxx
is the IP-address of your EV3. You will be asked for a password. The default
password is maker
. Be sure to use you're own combination of username and
password if you changed the default in ev3dev.
When logged in to EV3, you can install the API package on your EV3 with:
$ python3 -m pip install pixycamev3
This takes about four minutes on the EV3. pip
is not installed
out-of-the-box on ev3dev. You can install pip
with:
$ sudo apt install python3-pip
Beware this takes about 18 minutes on the EV3! But you can use
pip
later on to install other python packages when needed.
When package pixycamev3
is installed you're ready to program! Go
to the next paragraph Using Python API.
This method works for both Python3 and MicroPython.
In your project folder create a new folder pixycamev3
. Visit the repository
on Github.
Add the file pixy2.py to your folder pixycamev3
. The easiest way is to open
this file in Github and click on the Raw
button right above the code window.
Then select all text of the file and copy it to a new file named pixy2.py
in your pixycamev3
folder.
Your project folder structure should look like this:
project ├── pixycamev3 │ └── pixy2.py └── main.py
The file pixy2.py
works for both Python and MicroPython. When you copied
the file you're ready to program!
The main object you will need is the Pixy2
class. This object contains all
the properties and methods you need to use Pixy2. So first you have to load
this object from the pixy2
module:
class Pixy2 | |
---|---|
Parameters: | |
port | The sensor port on the EV3 to which Pixy2 is connected. |
Valid values in range 1 to 4. | |
i2c_address | The I2C address you set in the Pixy2. |
Returns: | |
Pixy2 object | |
Example: | |
from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) |
Object Pixy2
contains the following methods:
get_version() | |
---|---|
Description: | |
Get the firmware and hardware version of Pixy2. | |
Parameters: | |
None | |
Returns: | |
Pixy2Version object: | |
hardware | Hardware version (int) |
firmware | Firmware version (str) |
firmware_type | Firmware type (int) |
Example: | |
from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Get version version = pixy2.get_version() print('Hardware: ', version.hardware) print('Firmware: ', version.firmware) |
get_resolution() | |
---|---|
Description: | |
Get the current frame resolution of Pixy2. | |
Parameters: | |
None | |
Returns: | |
PixyResolution object: | |
width | Frame width (int) |
height | Frame height (int) |
Example: | |
from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Get frame resolution resolution = pixy2.get_resolution() print('Frame width: ', resolution.width) print('Frame height: ', resolution.height) |
set_lamp(upper, lower) | |
---|---|
Description: | |
Turn the leds of Pixy2 on or off. | |
Parameters: | |
upper | Upper leds: 0 = off, 1 = on |
lower | Lower led: 0 = off, 1 = on |
Returns: | |
None | |
Example: | |
from time import sleep from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Turn upper leds on for 2 seconds, then turn off pixy2.set_lamp(1, 0) sleep(2) pixy2.set_lamp(0, 0) |
set_mode(mode) | |
---|---|
Description: | |
Set mode for Pixy2 (for linetracking) | |
Parameters: | |
mode | Desired mode: |
Pixy2Mode.LINE_MODE_DEFAULT | |
Pixy2Mode.LINE_MODE_TURN_DELAYED | |
Pixy2Mode.LINE_MODE_MANUAL_SELECT_VECTOR | |
Pixy2Mode.LINE_MODE_WHITE_LINE | |
Returns: | |
None | |
Example: | |
from pixycamev3.pixy2 import Pixy2, Pixy2Mode pixy2 = Pixy2(port=1, i2c_address=0x54) mode = Pixy2Mode() pixy2.set_mode = mode.LINE_MODE_MANUAL_SELECT_VECTOR |
get_blocks(mode) | |
---|---|
Description: | |
Gets all detected blocks in the most recent frame. | |
Parameters: | |
sigmap | Sigmap of all 7 signatures for which you wish to receive block data. |
For example, if you are only interested in block data from | |
signature 1, then sigmap=1. If you are interested inbock data from | |
signatures 1 and 2, then sigmap=3 (1+2). | |
max_blocks | The maximum number of blocks you wish to receive. |
Returns: | |
nr_blocks | Number of detected blocks |
blocks | List of Block objects (length = nr_blocks): |
sig | Signature or color code number |
x_center | X location of the center of the block |
y_center | Y location of the center of the block |
width | Width of the block |
height | Height of the block |
angle | Angle of color code in degrees |
tracking_index | Tracking index of the block |
age | The number of frames the block has been tracked |
Example: | |
from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Track blocks with signature 1, request just 1 block while True: nr_blocks, blocks = pixy2.get_blocks(1, 1) # Extract data of first (and only) block if nr_blocks >= 1: sig = blocks[0].sig x = blocks[0].x_center y = blocks[0].y_center w = blocks[0].width y = blocks[0].height |
get_line_tracking_data() | |
---|---|
Description: | |
Get linetracking data (MainFeatures) in the most recent frame. | |
Parameters: | |
None | |
Returns | |
MainFeatures object: | |
error | Data error when value True |
length_of_payload | Number of bytes in payload |
number_of_vectors | Number of vectors detected |
number_of_intersections | Number of intersections detected |
number_of_barcodes | Number of barcodes detected |
vectors | List with Vector objects (length numberofvectors) |
intersections | List with Intersection objects (length numberofintersections) |
barcodes | List with Barcode objects (length numberofbarcodes) |
Vector object: | |
x0 | X location startpoint vector |
y0 | Y location startpoint vector |
x1 | X location endpoint vector |
y1 | Y location endpoint vector |
index | Index of vector in array |
flags | Internal state, used for testing/debugging |
Intersection object: | |
x | X location of intersection |
y | Y location of intersection |
nr_of_branches | Number of branches starting at this intersection |
branches | Array with Branch objects (length numberofbranches) |
Barcode object: | |
x | X location center of barcode |
y | Y location center of barcode |
flags | Internal state, used for testing/debugging |
code | Number of barcode (see Pixy2 wiki) |
Branch object: | |
index | Index in array |
angle | Angle of branch |
angle_byte1 | Byte1 of angle |
angle_byte2 | Byte2 of angle |
Example: | |
from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Detect barcodes and print their number while True: data = pixy2.get_linetracking_data() if not data.error: for i in range(0, data.number_of_barcodes) print('Barcode number: ', data.barcodes[i].code) |
set_next_turn(angle) | |
---|---|
Description: | |
Set direction for turn at the next intersection. After this intersection | |
Pixy2 will choose it's default turn again. | |
Parameters: | |
angle | Direction to choose at the next intersection (-180, 180 degrees) |
Returns: | |
None | |
Example: | |
from time import sleep from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Set next turn to 90 degrees pixy2.set_next_turn(90) |
set_default_turn(angle) | |
---|---|
Description: | |
Set default direction for all intersections. | |
Parameters: | |
angle | Default direction (-180, 180 degrees) |
Returns: | |
None | |
Example: | |
from time import sleep from pixycamev3.pixy2 import Pixy2 pixy2 = Pixy2(port=1, i2c_address=0x54) # Set default turn to 0 degrees (straight on) pixy2.set_default_turn(0) |
You'll find more practical sample code in the Github repository.
<Work in progress>