[WORKING WITH MAPLE MINI] USB Host Shield, MCP4151 DigiPots and a PS4 controller

So I just tried to post this on the project hub, added all the parts and tools, even helpful little comments on everything that I could. Then when I added the diagram, everything disappeared. So it’s going here.

The main reason I did this is so I can fly my racing drone the same way I fly a helicopter in GTA5. My FPV cam is mounted on a single axis gimbal(up/down). In the game, the left stick controls pitch and roll, the right stick controls the camera. Yaw is done with bumpers but i’m just going to use the right stick X-axis for yaw. To gain altitude, you pull the right trigger(accelerator). To go down, you pull the left trigger. To maintain altitude, you simply let go of both triggers.

With this sketch, you are able to set the mid-throttle by holding R1 R2 and L1, then pulling the throttle to the desired position and releasing R1 L1. R1 temporarily holds the mid throttle at 0 so it doesn’t jump when you release L1. If you don’t hold R2(Brake), the throttle will jump as soon as you release L1.

To set it to center(50/50), hold square and tap R1 click SHARE and OPTIONS together. This is useful for using with RC cars with brake/reverse where you need the controller to be 50/50.

I attached the diagram to wire the 6 digipots(MCP4151-103). The three rows of holes at the top are for the potentiometer connections.
Top=A=usually positive(+)
Bottom=B=usually negative(-)
Note the MCP4151 does not require any external circuitry(diodes, resistors…), just make the connections.

I wanted to power the arduino from the same battery as the controller(Frsky Taranis Q-X7), if you want to do this too, you will probably want to use a voltage regulator or boost converter just to be safe.

I will upload pictures once i figure out how to get them off of my phone.

The sketch says that you only have to pair the PS4 controller once but i have to re pair every time I power on the arduino.

I will probably be adding more features to this as i use it more and more. If you have any suggestions, please share your ideas.

Commenting out all of the serial crap saves something like 10% of the program space.

Failsafe is the last else() loop at the end of the sketch.


  • added LED color change effects as throttle increases.

  • added gyroscope raw value feedback. The gyroscope does not put out an actual angle, instead it puts out the angle it has traveled over an amount of time(I think it has to do with refresh rate) so the number goes up(to around 40000 at its fastest rate) the faster you move it and adds it(scaled down from 0-10,000 to 0-50 because you would have to pull pretty fast and hard to get it to go much higher than 10,000) to the pitch(tilt back and forth) and yaw(tilt side to side on controller yaws/turns the vehicle.

  • Failsafe goes to 128 if prehover = 128(square + L1)(LED flashes blue and yellow for 128 only) and 0 if its anything else.

  • Hold R3(click and hold right stick) to flash battery level(2 sec on, 2 sec off=don’t worry;1 sec on, 1 sec off=above 30ish%;half sec on, half sec off=watch out; 1/10 sec on, 1/10 sec off= bring it in, shut it down).

  • Added some comments.

  • I think that’s it for now. Please ask questions or at least say something so I know someone is interested.

So I have been working on the the program and thinking of more stuff that i could add to this project and discovered the trainer port on the my Taranis Q-X7. I haven’t hooked it up to the taranis because i cant find the timing specs of the Taranis trainer port but I found a ppm reader sketch and can read a clear ppm signal that follows my input.

I have also fine tuned some of the button functionality, added a servo for the arming switch and another one for a flight mode switch. Also the gyro feedback now only applies to rate mode while the accelerometer gives as similar effect to angle mode.

Every thing should be covered in the sketch.

In the file “PS4Parser.h” you will need to scroll a little past half way down and change

        float getAngle(AngleEnum a) {
                if (a == Pitch)
                        return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
                        return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;


        float getAngle(AngleEnum a) {
                if (a == Pitch)
                        return ((atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG) - 180;
                        return ((atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG) - 180;

This will make it so that the “PS4.getAngle(Pitch)” and “(Roll)” center to 0 instead of 180 when the PS4 controller is set flat on a level surface. I just thought it was more appropriate, also makes calibration calculations easier. I also just discovered that I like saying the end of that sentence out loud.

So here you go, you don’t have to make a digipot shield now, but you can if you want to. Just remember, I have not tested this in the physical world. I have also NOT tested the PPM output connected to my Taranis Q X-7, only to a ppm decoder sketch on an arduino nano just to check that the signal is changing. I haven’t had any luck finding the timing actual specs for the PPM signal. I’ll just have to play with it until it does something fun.

a_MCP4151_shiftout_PS4BT_V1.ino (25.2 KB)

a_PS4BT_Trainer_Port_V1_2.ino (24.9 KB)

USB_Host_Shield_Library_2.0.zip (388 KB)

So I duct taped the gyroscope to the accelerometer. I tried using a few different libraries but in the end they were either too big for my leonardo, too slow, or did the same thing that this library does with the accelerometer(or at least appeared to).

There is a “mix” value that you can change that says how fast the gyro will follow the accelerometer. The higher it is, the faster it will follow/correct but will be more effected by bumping and shaking.

I also moved some stuff around and added a bunch of comments and indents.

I also commented out the yaw output in angle mode because it effects the roll and pitch outputs while rolling or pitching, I left it alone in rate mode though.

For now it’s just the MCP4151 version, I will update the trainer port version at some point(probably in the next week or so).

Update: I duct taped the trainer port sketch.

a_MCP4151_PS4BT_V2_DuctTape.ino (30 KB)

a_PS4BT_Trainer_Port_V2_DuctTape.ino (29.4 KB)

I tried the “trainer port” version on my Q X-7 today with zero success. I don’t have a scope anymore so I just read the signal using a shiftIn(returns microseconds) function on a nano and printed it to serial. It is NOT accurate. The readings very a bit but all I wanted was to see the changes when I move the sticks. I got 8 readable channels out of my Q X-7 but the arduino output waivers, is way off, and sporadically outputs more channels then I tell it to(I think).

I was listening to music while I was doing this and somehow mixed up the trainer plug with my ear buds plug, DONT DO THAT!!! But I thought to myself “That F*****G HURT, I wonder what the arduino output sounds like compared to the Q X-7”. Turns out it’s way off but I can clearly hear the difference when I move the sticks on either(not eye therrr) one.

This leads me to believe my first thought when I found the trainer port, this is probably a job for the mega or (dare I say)stm32.
From the 20ish minutes of googling a few forms of “porting arduino to stm32”, I think that this is WAY over my head.

I will leave the trainer port versions up for reference. If I have any more updates, I’m only going to update the digipot version.

Here is the reader sketch I used.

a_pulseIn_trainer_port_reader.ino (558 Bytes)

I finally got it tested and working.

You will still need a Leonardo unless someone can port the usb host shield to stm32. For now, all of the work is done on Leo, then he tells an Maple Mini STM32CBT6 (or maybe C8T6, pretty sure it’s B, either way, small writing coupled with poor part number choice on STM’s part) what to do through serial1 TX on Leo to Serial2 RX on the Maple Mini.

I did find a USB Host breakout on hobbytronics that I was thinking of checking out but when I tried to order one it said it would be delayed, also it was almost twice as much as the one I used here. On the bright side, the description says that it puts everything out through serial in a nice little string beginning with “PS4” then everything(buttons, sticks, trigger, accelerometer, and gyroscope) else.

I also made a library called Laziness and used some of it so you do need it. I also included a sketch to show(at least some of) what it does and how to use it.

Connections:(I read somewhere that the power pin in the module bay of the Q-X7 is switched direct battery voltage to power all of this but I haven’t tried it yet.)

LEONARDO --------- Maple Mini ----------- Trainer Port

3.3 Volts----------------VCC

Now, from my thumbs/fingers to the motors of my drone:

thumb > PS4 Controller
PS4 Controller > USB Bluethooth dongle
dongle > USB Host shield
shield > Leonardo
Leo > Maple Mini
Maple > Q-X7 brain
Q-X7 brain > Q-X7 TX module
RX > Flight controller
FC > Electronic Speed Controllers
ESCs > Motors

0_ppm_trainer_port_leo_side.ino (30.5 KB)

0_ppm_trainer_port_maple_mini_serial.ino (4.76 KB)

0_Laziness_test.ino (3.22 KB)

Laziness.h (1.54 KB)

Laziness.cpp (2.13 KB)

keywords.txt (371 Bytes)

So i got this other USB Host breakout from Hobbytronics. It’s a LOT easier to use. Everything is done through serial or i2c. This makes it much easier to port projects over to other platforms, like the maple mini. The only drawback is it doesn’t give gyro values, only accelerometer values witch I tried and didn’t like. Also, there is no command to power down the controller so you will have to hold the PS button until it turns off. I left it in and commented it out in case I get a response from Hobbytronics saying that they have updated their firmware, in witch case I will update this again.

So here is the maple mini-hobbytronics version. It can be hooked up directly to an external FrSky XJT module or through the trainer port. The XJT also outputs S Port telemetry witch i will try to add later, maybe(I tried to add an i2c OLED for stick position readout and everything crashed after about 5 seconds).

PPM output is on pin 17.

You only the TX pin on the USB host to go to the RX pin of Serial2 on the maple mini(pin 8 ) and ground to ground. You only need the other serial wire to change settings on the USB host and mess with the LED on the controller. I didn’t do LED stuff in this one but I left it in there in case you want to mess with it.

0_ppm_XJT_HobTron_PS4_Maple.ino (28.5 KB)

ps4.h (5.17 KB)