BrickPi3 and Voice Hat (Google AIY) - SPI problem

I am using BrickPi3 with my own Raspbian image on a Raspberry Pi 3 B. By itself, it works fine, but when I try to use it with the Voice Hat (that came free with this month’s Magpi Magazine, in order to make Google Voice projects), I get the following problem:

When I run Read_Info.py: ‘No SPI Response’

When I run Test_Connected.py: ‘Communication with BrickPi3 unsuccessful’

When I run any of the examples, e.g. EV3-Gyro.py: IOError: ‘No SPI response’

I am afraid I don’t know enough about this to move forward, despite having spent the last two days trying to find a solution. I am grateful to anyone who can help.

What I would like to be able to do is use Google’s Voice User Interface (which I have working with the Voice Hat) to issue voice commands via BrickPi3 to a LEGO personal assistant.

Many thanks,
Stuart

There is probably a pin conflict. See the BrickPi3 schematics for which pins are used. Most significant are header pins 12, 19, 21, 23, and 26 (and for firmware updates also pins 18 and 22). Pins 12 (SAMD reset) and 26 (SPI select) are most important, as 19, 21, and 23 can be shared with other SPI devices, and pins 18 and 22 can be used as GPIO except when you do a BrickPi3 firmware update.


Hi Matt,
Thank you very much for such a quick reply. I appreciate it.
I have compared the schematics for BrickPi3 and the VoiceHat (see the uploaded image) and it looks like GPIO6/Pin26 might be the problem. It is SPI_CE1 for the VoiceHat.

Do you know of any way around this, please?
Many thanks!
Regards,
Stuart

You could try switching to SPI_CE0 for the BrickPi3. It will require hardware modification (connect pin 26 of BrickPi3 to RPi pin 24 instead of 26), and a simple drivers change (assuming you’re using Python or Scratch, change brickpi3.py line 21 from ‘BP_SPI.open(0, 1)’ to ‘BP_SPI.open(0, 0)’, and then re-run the install script as described in the README).

Alternatively you could try hacking the Voice Hat hardware/software to make it use pins that don’t conflict with the BrickPi3.

Thanks Matt,
That didn’t work. I think there are more pin conflicts than I first thought. However, you have given me some great ideas regarding hacks, and I know more about SPI than I did a few hours ago :slight_smile:

Thank you,
Regards,
Stuart

@Matt
Probably a little of topic here but why did Dexter choose to make BrickPi3 a SPI device instead ofa IC2 device??

yes, it’s off-topic (most probably because SPI can communicate asynchroneously and by far higher bus clock) … :wink:

I’m curious about the on-topic solution about the Voice HAT though… 8)

(and C API libs for that piece , but that’s admittedly another OT thing :wink: )

Helmut is correct; because SPI is much faster than I2C. The BrickPi3 uses an SPI bitrate that is 5 times the speed of standard I2C (500kbps vs 100kbps), and the protocol has less overhead.

… not to forget that it might be increased to another 4x faster SPI bus clock speed without issues and is supposed then still to work like a charm… :wink:
(on my Arduino Due I use a SPI clock of even 84 MHz (== full cpu clock), that’s 168x as fast as Matt’s SPI clock currently, and it still has no issues :sunglasses: )

SPI can indeed work at very high speeds, but the BrickPi3 doesn’t support running much faster than what I set the speed to. It seems to work at around 700kbps, but fails at 1mbps. I set the speed to 500kbps to be safe, and it seems very reliable. The BrickPi3 protocol does the read/writes during communication (interrupts at each byte), so by increasing the speed, the available CPU processing time gets decreased. To run a lot faster, the FW would need to use DMA to load/unload the data, and then commands would each need two transfers (a write to the BrickPi3, and then a few moments later a read from the BrickPi3). By dealing with the data in the SPI ISR using interrupts, each command can use a single SPI transfer (write and read in one transfer).

With most SPI applications the data only needs to go one way (e.g. read from flash storage, or write to a display), and the communication is handled with hardware (even if it’s using DMA to load the data and then processed by software). The BrickPi3 does data processing during the transaction (again, with the benefit being that read and write commands can be a single transaction).

tbh, I cannot understand that.
IIUC, you are using a SAMD21 core, probably somehow similar to a Arduino Zero or M0 or Adafruit Feather - they all are clocked at 48MHz, so if one chose a clock devider =1 then you could clock SPi also up to 48MHz .

more limitations would have to be considered probably for the Pi side of SPI, as it’s limited here to about 4 MHz - pls CMIIW :sunglasses:

The CPU is running at 48MHz, but if you tried clocking the SPI at much more than 500kbps, the CPU wouldn’t have enough time to process the data as it’s coming in/going out.

aah - that’s why.
ok, point for you, of course :slight_smile:

but back to the topic post -
do you think it would be feasable some time in the future (perhaps not in one one would call near) to make the BR3 pins 12,18, 22 free configurable? e.g. by software or perhaps by micro switches or jumpers?

Probably another silly question. But why is it needed a fast bit rate? Isn’t there is only a small amount of data sent between the RPi and BrickPi (I assume a few bytes for each command passed)?

Again my hardware knowledge is weak. My understanding is the advantage of SPI is speed but the disadvantage is it’s not as easy to connect several devices in parallel

Fast bit rates allow for fast communication, which means more commands per second (reads and writes). More commands per second allows for faster and more advanced robots.

Even with SPI, the BrickPi3s can still be stacked (connected in parallel). See here for details.

In most applications, the BrickPi3 is the only hardware connected to the Raspberry Pi header. If you look at the specifications for Raspberry Pi HATs, you’ll see that they are not to be stackable (only one at a time is supposed to be connected to the RPi). The BrickPi3 is not designed to follow the official HAT specs (it can be stacked with other BrickPi3s).

I think you are missing that SPI is a multi-device bus system with seperate write (MOSI) and read (MISO) lines (like UART TX and RX, but unlike i2c ) plus the option to address devices (unlike UART, but like I2C, but which can only read or only write and address only 1 device at a time, and every read needs basically an additional inital write signal for addressing the device to read, plus delays and clock-streching in between for synchronization: that is what makes i2c slow, apart from bus clock.

From a practical POV: by 100kHz i2C bus speed I was only able to read different devices at 10ms each, one after the other (edit, including data transmission control).

Now imagine you have 4 or 6 or 8 BP shields plus 2 MCP23017 (400kHz capable, but not with 100kHz devices on the same bus) plus 4 PCF8591 (just 100kHz capable which limits the whole bus speed then to 100kHz) plus a 9DOF IMU plus 1 Arduino for IO multiplexing plus an OLED, all on 1 i2c …:

hell, no!! :rolleyes:

OTOH, on SPI you can read multiple devices in a stream and write to multiple devices simultaneously, asynchroneously in an independent stream, all in real-time, and have additionally i2c available for less time-critical standard devices. And you have 2 independent address lines (actually just 2 on the Pi (CE0+CE1, theoretically even more, IIRC), and SPI devices (eg., an Arduino or a PI) can be switched from master to slave at any time by design (SS=slave select vs. CS=chip select).

Got the point?
If you don’t believe me: try it out by yourself.

Of course for a simple 2-motor line follower and just 1 BP shield that is no issue at all.

BTW: HATs are smaller by design, but many HATs are stackable too (e.g. Adafruit motor HATs) and use i2c-0 additionally for HAT EPROM by HAT specs.

So again my hardware knowledge is lacking.

To stack SPI devices require each device to have a different ss line ??? or can each device just be addressed differently like a I2C device??

Normally you can’t stack SPI devices like you can the BrickPi3, but the SAMD (BrickPi3 microcontroller) is unique in that it supports SPI address matching (the MISO line remains high impedance until address match). Traditionally you do need a different SS line for each SPI slave, as SPI doesn’t normally support addressing.

1 Like

So I2C is easier to stack when using a header but SPI is faster. To stack SPI it is easier when using jumper wires instead of header so that you can connect different SS line to each device.