For a multirotor to fly, the thrust of each motor has to be equal, within certain tolerances. These tolerances depend on the bandwidth of the multirotor which are usually reflected in (well tuned) rate PIDs.
Let me explain:
The rate PIDs are usually tuned to reach the best impulse response which depends on the moment of inertia (radius, mass and mass distribution) and thrust inertia (prop weight, motor power, ESC, etc etc).
Unbalanced motors result in a steady-state error for the rate PID which it has to compensate for using the P and the I terms. Going too high with either term – higher than the multirotor bandwidth can allow – will cause oscillations and instability.
It might seem obvious that unbalanced motors are bad. In the end all motors – even high end ones – tend to have slight Kv differences which results in different thrust for the same PWM input. It happened to me when I last tested my quad – it kept flipping over at launch and I didn’t understand why the PIDs cannot compensate for this. All other quads work and surely they have their own unbalanced motors.
So when I got home I measured the Kv of each motor and I found that one of them is lazier – around 90% thrust compared to the others.
So I fired up the simulator and added some randomness to each motor thrust (between 80% and 120%) and yes – the quad wouldn’t fly. The rate PID was unable to compensate for the difference in thrust. Increasing a lot the P term or a bit the I term stabilized the quad.
But what if I couldn’t increase the P or I because of oscillations? What if my PID was at its limit, stability wise? Then the quad would not be able to fly with this particular combination of motors and moment of inertia.
Seems like a silly conclusion – if the motors are bad the quad will not fly – but I felt like I had some sort of epiphany that the thing responsible to compensate for bad motors is the same thing responsible for fully using the quad bandwidth – so unbalanced motors need some bandwidth margin to allow the PID to compensate for them.
I built a custom testing rig out of some plywood sticks and these kind of elastic cords:
There is just enough clearance for 7 inch props and the quad is free to rotate around one axis (Y or roll in the video). I can easily change the free axis as the cords connect to the arms with metal hooks.
The issue I’m debugging now is related to a tendency of the motors to generate different thrust for the same throttle input. I think it’s because the ESCs have different settings on them as I couldn’t find any issue with my code so far. If I send 50% throttle to all motors the quad spins a lot.
In my last post I talked about using the si4463 chip to send video, telemetry and RC data to the quadcopter. I calculated the bandwidth and it seemed that 500kbps video with 5/7 FEC coding should be possible.
I wrote the code, linked everything together and it kind of worked. The video was stable, not many packets lost but the latency was pretty bad. It got up to ~200ms from the current 100-130ms but worse than this, the video was very choppy. I managed to narrow it down to the H264 codec in the raspberry pi: the bitrate you configure in the codec is an average bitrate, per second. Each frame can vary a lot in size as long as the average is preserved (with some allowed over and undershoot). I got I-frames of 12-16KB and P-frames of 400-500 bytes (at 30 FPS). The I-frames took way longer to send than the P-frames and this resulted in a choppy video. I tried to play around with settings – like disabling CABAC and activating CBR but nothing made the bitstream uniform enough.
The final, biggest problem was actually caused by the RF4463F30 module – and it’s the same problem I had months ago when I tried to use them: they introduce a LOT of noise in the power line, enough to cause all the I2C chips on the quad to fail.
I tried all kinds of capacitors to decouple the module and reduced the noise a lot but there seem to always be some capacitive/inductive coupled noise persisting.
In the end I just gave up and went back to the RFM22B chip which just works. For video I went back to the monitor mode/injection system but did change the modulation to CCK, 5.5Mb to hopefully reduce the possibility of interference with other 2.4Ghz RC systems. CCK is spread spectrum similar to DSSS and should be able to coexist with RC systems around.
So yeah, FPV through a very constrained channel with a temperamental H264 encoder and a very temperamental transceiver module is not fun…
While testing the menu system yesterday I notice a strange problem. Sometimes pressing a button triggers not only the GPIO associated with that line, but adjacent lines as well.
My first thought was ‘wiring problem’ as everything is crammed inside the RC with 30+ jumper wires, so I started shaking and moving wires around but it didn’t seem to change much.
Then I turned to code – I thought I might have a bug – and after close introspection the code seemed correct:
- Set the column GPIO as output
- Set the column GPIO high (+3.3v)
- Read all 4 line GPIOs, see which button is pressed
- Set the column GPIO as input to turn it off
Everything seemed ok so I took out the oscilloscope and probed one of the columns.
Here’s what I got:
I probe 2 column GPIOs here and the trigger is on the green trace. The 2 problems become obvious – first of all the pin goes low too slow so by the time the next pin is high, the previous one still has ~2.3V, enough to register as high. And second – the code lops through this without any delay between pins.
On paper, the code works correctly but not so in real life where there is inductance and bandwidth limits for triggering GPIOs high/low.
The fix is trivial. I changed the loop like this:
- Set the column GPIO as output
- Set the column GPIO high
- Wait 2 microseconds for the pin to settle
- Read all 4 line GPIOs
- Set the column GPIO low <— this causes the voltage to drop way quicker than just setting the gpio as input
- Set the column GPIO as input
- Wait 2 microseconds for the pin to settle
Here’s the trace on the oscilloscope after the changes:
As you can see there is a clear, safe distance between triggering adjacent column GPIOs and (not visible in the trace) the lines are sampled right in the middle of the high interval.
This works perfectly now.
After a few more failed attempts to print the RC case with ABS I finally gave PLA a chance. Ordered some black 1.75 filament from amazon and a few days later I printed the case successfully from the first try. PLA is great, it’s easy to print, it smells like sugar when printing – as opposed to the chemical smell of ABS – and the quality is really good. However it doesn’t like to be sanded. At all! It’s like trying to sand rubber – or more accurately – sugar.
I decided to stop worrying about the finish so much and ordered some plastic primer and white matte paint. In the meantime I finished the RC PCB and made all the connections and did the first real test.
Here it is:
- 3 axis gimbal for yaw, pitch and roll. It’s a very high quality one with bearings and hall sensors instead of pots
- Motorized linear pot for the throttle. I went for motorized because when changing flight modes I want to have the throttle in the correct position to avoid stopping the motors
- 0.96″ OLED screen for status info, calibration and other things
- 8 ADC channels – 4 for the sticks, 3 for the individual LiPo cells and another one for the Gimbal Pitch pot
- a 4×4 button matrix implemented with pigpio for all the buttons and switches
- 2 rotary encoders for live editing of parameters like PIDS, menu navigation, etc
- 2x 2.4 GHZ wifi diversity for the video feed
- 5.8 GHZ wifi for the phone connection – to send the video feed through
- 433 Mhz 30 dBm link for the RC data
- 2.2Ah 3S LiPo battery for ~5h of continuous use, with charger/balancer port
The screen is connected through i2c1 at 1Mhz together with 2 ADC sensors (ADS1115).
I’m using this library to talk to the screen but noticed that a full display update takes ~20-30ms during which I cannot talk to the ADC sensors. To fix this, I changed the library and implemented partial screen updates. Now I can call screen->displayIncremental(1000) and the class will send incremental lines to the screen for 1000 microseconds (1 millisecond). The overall FPS is the same as with full updates but I get to do other things while the display is being updated. To avoid tearing I also added double buffering to the class and an explicit swap method.
The end result is a 40-45 screen updates per second but each update is split in 12-13 partial uploads with ADC readings in the middle. So I can sample the ADC at ~600Hz which is more than enough for a RC system.
The RC has 13 buttons and 2 rotary encoders requiring a total of 17 GPIO. Since I didn’t have enough I ended up grouping the 13 buttons in a matrix of 4×4 following this tutorial. This allows me to reduce the number of GPIO to 12 (8 for the matrix and 4 for the rotary encoders). I implemented the matrix reading using PIGPIO and added some debounce code to avoid detecting ghost presses/releases. Seems to work great and it’s very fast.
Most of the HW is done and it’s a mess of wires. I’m working now on some videos of potting it together, making the connections and the calibration.
The next step is to work on the phone app to receive the video feed, although I think I will give the quad a test – line of sight.
I really want to fly soon.
Here’s the case after my best attempt:
It looks… bad. The paint coat is horrible and full of scratches and the screen is too big.
But worst of all, the screen is not bright enough in direct sunlight. Not even close. I don’t have a photo but after brief testing I’d say it’s unusable.
So I’m pretty disappointing with the result – I ended up with a big, heavy RC system that is too dim to be usable for FPV.
I searched for a week for alternative capacitive touch screens, preferable in the 5-7 inches range but found nothing bright enough under 100 euros.
So after a mild diy depression I got an idea that will solve at lease 3 of the issues – cost, bright screen and the RC size: use my Galaxy Note4 phone as the screen.
The setup will look like this:
- The quad will send video through 2.4Ghz, packet injection (a.k.a. wifibroadcast method) and RC stream through 433Mhz
- The RC will receive both video and RC data and relay them to the phone using another 5.8Ghz wifi UDP connection. The phone will decompress the H264 video using OMX (or whatever is available) and display it with telemetry on top.
- The phone will also act like a touchscreen interface to control the RC/Quad
Basically this is what most commercial quads (like Mavic) are doing. I’m sure the video link is 2.4GHz due to longer range than 5.8 and better penetration and the connection with the phone is done over a 5.8, low power link.
So the next steps are:
- Redesign a smaller case that will accomodate a Raspberry Pi 3, the RC stick and fader + buttons and wifi cards
- Write a quick android application that can connect to the RC and decompress the video stream
I finished designing the case that will fit the silkopter RC system.
Here’s how it looks like:
- Raspberry Pi3
- Official Raspberry Pi 7″ touchscreen
- A 3 axis gimbal stick for the yaw/pitch/roll
- A ADS1115 ADC to sample the sticks and the throttle fader
- A motorized 10K fader for the throttle
- A brushed Pololu motor controller. Pololu modules are awesome btw
- 2 clickable rotary encoders to tune custom parameters like PIDS
- 2 switches to save/restore the custom parameters
- 7 push buttons to change flight modes, RTH and other cool things
The case is pretty big due to the screen. It’s 22.3 cm tall, 19.5 cm wide and 4.4 cm deep – so I couldn’t print it in one piece on my Prusa I3 printer. So I had to split in in a few pieces, print each one and them glue them together.
After a few failed prints, here’s the end result:
I’m painting it now with matte black paint and tomorrow I will put all the components together.
The only problem I’m having now is that I broke my touchscreen while fitting it in the case so I need to order another one.
I’m building my new quad and thought to give the H-Frame a chance. It it more spacious and perfect for FPV because the props are not in front of the camera.
My previous quad had 10mm CF arms – so for this one I thought to go for either 8 or 6mm ones. I tried both and settled for 6mm CF as it seemed to provide enough stiffness and were 20g lighter in total.
Here’s some Design Spark screenshots of the quad:
It’s very small – 33cm motor to motor diagonally – and light at ~680grams.
The improvement over my previous quad is that is has a gimbal and bigger motors and still about the same weight.
The components are:
- Multistar Elite 2306 mini-beasts. They are great, perfect bearings, very powerful and light. Around 10 grams heavier than my the previous 1804 RCTimers but they will swing the 7×2.4 prop way more efficiently and the estimated flight time increased by 5 minutes.
- Flycolor Raptor 20A ESC. Very small and powerful. I trust them more than my previous 4-in-1 RTFQ 12A ESC.
- The usual Raspberry Pi 3
- A TL-WN722N wifi card for the view link
- My custom Flight Controller on top of the RPi
- A MultiStar HV 3000mAh battery
So in the past 2 weeks I actually built it and it’s ready to fly. Here’s some photos:
Motor and ESC
Frame with motors, one ESC and the Raspberry Pi mount with vibration dampers
The ESC and the cover with cooling holes
Raspberry Pi mounted
The quad put together. The antennas are still temporary
However, it will probably never fly as the frame allows a lot of twist. It’s not rigid enough and to be honest, a bit messy. I don’t like the way it ended up and that twist really worries me.
Here’s a video of the issue:
So this was a failure. I should have known this before building the whole thing…
There are several solutions like adding more plastic between the arms to help the CF tubes, or switching to 8mm tubes. But I decided to switch to a X frame and be doe with it.
Last weekend I did some tests with a UBLOX Neo6 GPS running next to the V2 camera to see if it’s better than the V1 camera.
The GPS had a clear view of half of the sky with a building to one side so not necessarily ideal conditions. The GPS was powered from the Pi with the cable wrapped through a small ferrite bead.
Here is a picture of the setup:
Here is the graph showing the Satelite number, PDOP, Position accuracy and velocity accuracy reported by the GPS:
There is a clear jump when turning on the camera where PAcc goes from ~2 to ~3.2. With the V1 camera this jumped to 30-40.
The jamming indicator showed 15-20% regardless if the camera was off or on. With V1 the indicator jumped to 100% when turning the camera on.
The number of satellites is the same, as is the PDOP and VAcc.
The spectrum measured with the SDR was crystal clear even when the antenna was almost touching the camera ribbon cable – which btw is unshielded.
So my conclusion is that the V2 interferes with the GPS way less than the V1 and with a bit of (optional) ribbon cable shielding it should be ok for a multirotor.
I decided to start making binary releases available for everyone to download.
Here’s the first one – the GS and the brain binaries:
I’ll write a new post later today or tomorrow about the install steps and how to get it working.
Note this is not finishes for flying, it’s an experimental release of the new version of Silkopter that can be used to debug sensors and test most of the nodes.