BrickPi3 can now be stacked!


The BrickPi3 hardware was designed to be stack-able, but initially the firmware and drivers didn’t support changing the address to allow for multiple BrickPi3s. As of firmware version 1.4.0, the BrickPi3 Firmware (and updated Python drivers) allows you to change the BrickPi3 address, so BrickPi3s can be stacked!

The updated software and firmware is available now. To update the BrickPi3 firmware, only one BrickPi3 can be connected at a time. You can run the DI Update on Raspbian for Robots, or on Raspbian you can follow the BrickPi3 software installation instructions and then the BrickPi3 firmware update instructions.

Concerning the hardware configuration, you will not be able to use the acrylic case to enclose a stack of BrickPi3s (you can use the base panel to mount the RPi to Lego, but you won’t be able to use the other panels). You will need to connect a battery pack to each BrickPi3 that you want the motors to run on.

Concerning the software configuration in Python, prior to creating each BrickPi3 instance, you need to set each BrickPi3 to a unique address using the brickpi3.set_address() function. For example, brickpi3.set_address(2, “”) would set all attached BrickPi3s to address 2 (regardless of their current address), and brickpi3.set_address(3, “192A0F96514D4D5438202020FF080C23”) would set BrickPi3 with ID “192A0F96514D4D5438202020FF080C23” to address 3 (regardless of it’s current address). The default address is 1, and the new address is volatile (it will be forgotten when the BrickPi3 power is disconnected). To create a BrickPi3 instance for each BrickPi3, you can specify the address when you create it. For example, BP3_2 = brickpi3.BrickPi3(2) would create a BrickPi3 instance called BP3_2 that communicates with the BrickPi3 with address 2.

Each BrickPi3 has a unique ID that is static (can’t/won’t ever be changed). To determine the ID for each BrickPi3, connect one at a time to the RPi, and run the Python example program (ID is listed as “Serial Number”).

Check out this BrickPi3 stack Python example.

In the examples I used the ID 192A0F96514D4D5438202020FF080C23, but that is specific to one of my BrickPi3s. You will need to replace it with the ID of one of your BrickPi3s.

I have done some testing, and it seems to work well, but please contact me with any issues you find.

@JohnC @Shoban @karan @cleoqc @graykevinb @dlech @Shane.gingell @HaWe

Stackable? Daisy chaining? dev tree compatible to Jessie? [C/C++]
Is BrickPi+ and BrickPi3 stackable?
BrickPi3 and Voice Hat (Google AIY) - SPI problem

So how many BrickPi3s can be stacked? Until they flop over? :slight_smile:

A new case to allow for this new feature would be nice.


The software limit is 255, but I’m not sure what the hardware limit is. I’m guessing signal impedance would be the limiting factor.


I think stacked cases might be a DIY jobbie. But Yippie many doors just opened with robots design :slight_smile:


A case? who needs a case? just 4x 2.5" brass spaces (17mm) and you can mount them all way up to the moon!


Using an oscilloscope (actually a logic analyzer with analog support), the SPI signals are not noticeably degraded with 3 BrickPi3s stacked on a RPi3. I only have 3 BrickPi3s on my desk for testing, but it looks like it would easily work with a lot more than 3.


Another question, power supply for each BrickPi? Do you need to run a parallel power supply to each brickpi or do we just need to power 1 of them and the rest will get power through GPIO pins?


You will need to connect a battery pack to each BrickPi3 that you want the motors to run on. They will all share 5v power through the GPIO header, so the ones without battery packs will still work, they just won’t be able to run motors.

BrickPi3 runs it’s 3.3v and 9v regulators from the 5v rail, so the microcontroller and all sensors work the same even if it’s only running on 5v (from a different BrickPi3, or from USB power from the RPi).


about initializing for stacking:
given I had 3 BrickPi3 HATs, the default address would be 1 for each (IIUC).

the 1st could be used by default settings,

so now I would stack the 2nd alone on the Pi and run
BrickPi3_set_address(2, “”); // set BrickPi3 ID=2

then the 3rd, also alone,
BrickPi3_set_address(3, “”); // set BrickPi3 ID=3

Having done all that I would label them to remember the IDs.

Now I would stack them all eventually.

Will the BrickPi3 HATs then (hopefully) always remember their IDs, even when intermediately unplugged from voltage supply (e.g., by having stored the IDs in a permanent flash mememory)?


The new address is stored in RAM (volatile memory), so what you describe won’t work. Refer back to my first post for details.


sorry, I missed that, I over-read everything about Python because I don’t understand Python :wink:
how to retrieve the HAT ID/serialNumber by C?
e.g., like
char * BrickPi3_get_address(char* serialNumber);

for a revision 2.0 of the BrickPi3 an ID stored to flash would be nice to have though)


This C example prints the Serial Number for the attached BrickPi3. “ID” and “Serial Number” are the same thing.

I want to avoid making the SPI address get permanently stored. As it is, you can just specify the ID and what address you want it to be. For any project that uses multiple BrickPi3s, you just need one extra line of code (per BrickPi3) that gets run during setup. By keeping the new address volatile, as soon as it’s powered on, it’s back to the original settings, and will work with all the examples that use the default address of 1. If the new address was non-volatile, even once you cycled power, it would still not work with the example programs (unless you explicitly changed the address back to 1).


thanks for the ID code.
would it be possible to use char* instead of string?

tbh, about stored SPI addresses I don’t see your point. Actually it’s like storing i2c device addresses, in that case one is also not expected to readjust it’s addr before being able to use that device. And just like for i2c, the programmer is reliable for it’s unique occurence.
Imagine users who just want to stack the devices one by one and want to keep their setup for the next future - having identical static SPI addresses, it would be much easier to use them out of the box.
And probably nothing would work any more, if 3 or 4 stcked HATs had all been automatically reset to address 1, in case one forgot to reassign all single HATs before.
OTOH, anyone who ever wants to re-assign a different SPI address (one or the other time, randomly or because he forgot the old one) may do it whenever he wants, just one more line of code needed - i.e., actually the same kind of code one is forced to use right now at either time (which is admittedly quite cumbersome).


In the info.c example, the ID is a char array. Rather than declaring a pointer and then allocating memory at run-time, I declared a char array of a fixed length. It’s just an example program; you can do it however you see fit.

Not all changeable I2C addresses are stored in non-volatile memory, and for most devices that aren’t a microcontroller, the I2C address is set with hardware.

If someone builds a robot with 4 BrickPi3s and sets each to it’s own address (e.g. 1, 2, 3, and 4), and then they use BrickPi3 number 3 for an application where there’s only one BrickPi3, why would they want it to be address 3 rather than the default address 1? The way it’s done now, it’s only for more complex robots (requiring more than one BrickPi3) that anyone even needs to think about addresses. Once an advanced user makes note of the serial numbers for each BrickPi3 they would ever want to stack, any time they build a robot with multiple BrickPi3s, they can easily just assign the address (per serial number) at the start of the multi-BrickPi3 program.