BrickPi3 Error with PS4 controller

I have a BrickPi3. I have been using a PS4 controller with it: pyPS4controller. It works fine, but because it is strictly event-based (onPress, onRelease) it has limitations.

I found pygame and adapted it to something closer to what I need. However, I am getting a conflict…

When I import and run pygame, the trace output works as planned.
When I also import and run brickpi3, I get the following error:

Traceback (most recent call last):
File “usr/local/lib/python3.5/dist-packages/brickpi3-0.0.0-py3.5.egg/brickpi3.py”, line 295, in init
manufacturer = self.get_manufacturer()
File “usr/local/lib/python3.5/dist-packages/brickpi3-0.0.0-py3.5.egg/brickpi3.py”, line 411, in get_manufacturer
raise IOError(“No SPI response”)
OSError: No SPI response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/home/pi/Desktop/PiWarsAtHome/2024/PS4EventsBot.py”, line 3, in
BP = brickpi3.BrickPi3()
File “/usr/local/lib/python3.5/dist-packages/prickpi3-0.0.0-py3.5.egg/brickpi3”, line 298, in init
except IOError():
TypeError: catching classes that do not inherit from BaseException is not allowed

I have tried to hack the brickpi code to eliminate the manufacturer call, but other than that I’m at a loss. Hope you can help.

1 Like

Did you enable SPI in raspi-config?

If you didn’t do that, you will get errors like this.

1 Like

Hi Jim, I think that did it!

After years of working with Lego Mindstorms this is my first step into raspberry pi robotics, there’s a lot of “tinkering” that I don’t know anything about, and terminal always makes me a bit nervous. This was very easy to follow and worked immediately. Thanks very much.

2 Likes

Whoops, spoke too soon.

Now here’s what happens… No longer get the big error, which is good, but… I can get the brickpi motor to work at the start of the program, but as soon as I initialize pygame, the brickpi stops working.

A bit of further testing:
I import brickpi3 and pygame

If I do this:

BP = brickpi.BrickPi3()
BP.set_motor_power(BP.PORT_D, 30)
time.sleep(1)
pygame.init()
… the motor runs for 1 second, then pygame starts working (I have pygame test code below)

However, if I do them in the opposite order:

pygame.init()
BP = brickpi.BrickPi3()
… then it crashes, same crash as previous.

Any suggestions of what to do next?

1 Like

The reason it crashes is because you need to “load” (instantiate) the class libraries, (BPxxx) before you try to use them.

I don’t know enough about the BrickPi libraries to have a competent opinion, but if I remember correctly there is a similar “side effect” with the GoPiGo motors where “set_motor_power” also starts the motor moving.

Solutions I’ve used:

  • If I want to set, (initialize), the baseline motor power to use later, I "set motor power " and immediately follow it with a “motor stop” command.

  • If I am setting the motors power and plan to use it immediately, I either use that as the “start” command, or follow it immediately with the command I want to execute.

If you do something like either of these, you might want to comment your code to indicate that “set_motor_power” immediately starts the motors moving.

Sorry Jim, I’ve just posted what I thought was the relevant stuff in here…

I’ve got code working in one program when I’m only working with pygame. No problems.
I’ve got code working in another program when I’m only working with BrickPi3. No problems.
I’m at a basic testing stage in a third program where I’m combining the two.

I had an extremely basic set up so that when the program starts, the first thing it does is run a motor, just to see if it’s working. If I can make that happen, it’s a win, after which I’ll create the real program (with documentation :smiley: ).

But where I am now…

  • if I run BP set motor power first, it runs until I initialize pygame, then never works again.
  • if I run pygame first, then BP, it crashes with the SPI/manufacturer error.
    (i have SPI enabled)

Just to make sure I understand you correctly, what code am I missing to explicitly instantiate the class libraries? The other two programs work as they are, did I just get lucky?

Thanks

No need to be sorry, we’re all friends here. :wink:

The line BP = brickpi.BrickPi3() instantiates the BrickPi3 library class and creates a working instance named “BP” that you can use.

The line BP.set_motor_power(BP.PORT_D, 30) “calls” (uses) a method of the class instance “BP” to actually do something - setting a motor parameter and possibly cause it to start moving.[1]

Are you using a BrickPi-3?  It makes a difference.  The current GoPiGo libraries are specific to the GoPiGo-3 and older versions possibly won’t work with them.  (AFAIK)

Note:
The name of the class instance can be anything you want.  (i.e. “vanilla_milkshake” or “my_stupid_robot” instead of “BP”)

AFAIK, based on your description, it appeaórs that “pygame” uses the class instance (somehow, I don’t see you passing the instance named to pygame, which puzzles me), and “BP=xxx” creates the instance that has something pygame uses.

The Dexter Industries website, (which should still have a “BrickPi” section), should have documentation for the various software features and classes used by the BrickPi.

If you can’t find it, I recommend shooting off an email to “support@modrobotics.com” and ask them about BrickPi documentation, then come back and tell us about it.[2]

You should also read up on “pygame” and see how it works and what it needs when you run it.

====================

  1. Additional note:
    I am NOT an expert in using (or defining) classes.  I am attempting to explain this in the way I best understand it.
     
    Likewise:
    Neither I, nor @cyclicalobsessive or @KeithW, have a BrickPi, and we have never used the software.  However, since the principles are essentially the same for all the Dexter Industries libraries, we will still try to give you whatever help we can.

  2. [Sound bite:  Mission Impossible theme music]
    “Kevin:  Your mission, (should you decide to accept it), is to do the necessary fundamental research into the BrickPi libraries, experiment with them, and create articles here describing what you’ve learned and done.  IOW, to “boldly go where no BrickPi has gone before”! :wink:
     
    (This message will self-destruct in 15 seconds. . .)”

1 Like

There may also be a dependency on i2c as well. Just for the heck of it, you might want to check raspi-config and make sure that’s turned on.

SSH and VNC are also useful features to enable.

Thanks Jim, your dedication to this issue is admirable. I am proud to call you… “friend”.

(BTW I’m Canadian, where"sorry" is just a word to indicate that a sentence is on its way :smiley: )

Okay, I’m with you on the instatiation… and I think I’m doing it right.
What I left out of my shared code…

pygame.init
j = pygame.joystick.Joystick #initialise new joystick object
j.init
Pygame documentation here - pygame.joystick — pygame v2.6.0 documentation

As for Dexter - when you install BrickPi3 (it’s deffo a 3), it comes with all the readme stuff, class libraries, etc. It’s been a long time since I first installed it - probably pre-2020. A little cagey about randomly updating everything for fear of turning something that kinda works into something that doesn’t work at all! (especially since the recurring proposed solution is to wipe and install Legacy!)

I have enabled SPI, I2C, SSH and VNC :smiley: When I said “i think that did it”, it was because the program ran without errors and I got overexcited. The conflict was still there, the motor still didn’t work, but it just stopped throwing the error into the console.

More context of initial problem:
I’ve had the BrickPi working for years on its own, with pyPS4controller. The problem with pyPS4 is that it’s event-based, so can’t check status of things continuously - it can do “onTrianglePress” “onTriangleRelease” functions on a listener, which is pretty good, but I got greedy and wanted something a little more real time.

I found PyGame, which does real time nicely - I’m able to continually check status of all actions and stick positions in a “while True” loop, which means (for example) I can check gyro readings while driving and make small adjustments, rather than “onUpPress > power=30)” I wrote a custom tester for pygame which works beautifully on its own.

But then I chucked BrickPi3 into the mix and ran into this unexpected SPI/manufacturer problem. The “get_manufacturer” error sounds stupid and insignificant, and I’ve tried hacking into the BrickPi code to get rid of it, but no joy, there must be more going on back there than they’re letting on.

I’ll keep trying. I promise if/when I get it working I’ll post tales of my bold exploration into parts unknown on here.

1 Like

“Ahh feel yer pain!”

I have (had?) a project where I drove a robot around using a web browser, a GoPiGo with a camera, and a joystick as the controller via a web page.

One of the big problems was that the browser “Gamepad” API’s didn’t have events.  Rather you were supposed to poll the joystick every request_animation_frame() cycle which is tied to Vsync.

One of the things that the gamepad API’s provide is a counter that increments whenever there’s any activity.  I wrote a routine that checked the counter every cycle and - only if there was a change in the counter - did I then grab a new joystick frame of data and sent it to the robot.

I don’t know if you’re doing this via a web page or what, but maybe something like this might help?

1 Like

Jim! I have good news and bad news.

The good news: I got it working!
The bad news: I don’t know how. It just does today. Welcome to coding.

All I can do for this channel is give you a status update:

  • OS and BrickPi: still the ones that came with the initial BrickPi3 setup. Pretty sure I updated nothing and I overwrote nothing.
  • pygame: same. The one that was on there yesterday is the same today, no updates.
  • Errors: ok this was weird. When I turned everything on this evening, I got a different error from all the errors I had before. I’m afraid I didn’t take note of it, but it was about 10 lines long and ended with:

BP-SPI.open(0,1)
Something something Errno 2 something not found.

New error means progress.

Because it was SPI, I did what any self respecting programmer would do: I went back into raspi-config and enabled SPI again. Then for good measure I enabled I2C, SSH, VNC, and just about everything else on offer in the Interface options menu.

I went back to Thonny and tried it again… and it worked.

Now, I can tell you with conviction that SPI and all those other things were enabled yesterday. Remember all this started with a completely different error, and the first/tenth/hundredth thing I did was enable SPI and continued to get that other error.

But today I guess is a magical day.

Once it worked, I stopped the program, saved it, shut down the pi and walked away. If it doesn’t work tomorrow, I at least ended the day with the knowledge that success was once achieved and can be again.

Once I’ve got working pygame/brickpi code I’ll happily share it, but it comes with the caveat that I can walk you to the edge of the canyon and pick you up on the other side, but you’re on your own for the bit in the middle.

Thanks very much for your patience! I owe you one!

2 Likes

Next steps:

Try again and see what’s reproducible.

Since I don’t believe in magic, I usually try a different installation - as in “do it again with a different SD card and see what happens” - and try to get to the point where I can reproduce either success or a particular failure mode repeatably, before I believe it. . .

Yup!  “Welcome to coding” is right!

1 Like