dRehmFlight VTOL - Teensy (Arduino) Flight Controller and Stabilization

the rc project

Well-known member
I’m probably gonna sound like an idiot but this is literally the first project like this I’ve ever done, I’ve never seen a line of code.... however I’ve managed to get the hardware setup and working using the videos. But I have no idea how to get it to control a servo or an esc. I can’t find anywhere on the documents what a servo output looks like, I understand 1500 centre point but I’ve never written code. What does a 4 channel plane look like in the code? Where do I edit the code? (Declare pins?)
 

JasonK

Participation Award Recipient
I’m probably gonna sound like an idiot but this is literally the first project like this I’ve ever done, I’ve never seen a line of code.... however I’ve managed to get the hardware setup and working using the videos. But I have no idea how to get it to control a servo or an esc. I can’t find anywhere on the documents what a servo output looks like, I understand 1500 centre point but I’ve never written code. What does a 4 channel plane look like in the code? Where do I edit the code? (Declare pins?)

here is were you setup your mixer, as it stands, it is setup for a quad:
https://github.com/nickrehm/dRehmFl...BETA_1.1/dRehmFlight_Teensy_BETA_1.1.ino#L795

and here is were you set the PID settings (this requires tuning and experimentation to get just right)
https://github.com/nickrehm/dRehmFl...BETA_1.1/dRehmFlight_Teensy_BETA_1.1.ino#L141

if you wanted to do just a basic 4 channel airplane, you would want something like this in the mixer:

m1_command_scaled = thro_des;
m2_command_scaled = 0;
m3_command_scaled = 0;
m4_command_scaled = 0;
m5_command_scaled = 0;
m6_command_scaled = 0;


//0.5 is centered servo, 0 is zero throttle if connecting to ESC for conventional PWM, 1 is max throttle
s1_command_scaled = 0.5f + pitch_PID; // this might need to be a - instead of a + depending on the servo direction
s2_command_scaled = 0.5f + roll_PID; // this might need to be a - instead of a + depending on the servo direction
s3_command_scaled = 0.5f + yaw_PID; // this might need to be a - instead of a + depending on the servo direction
s4_command_scaled = 0;
s5_command_scaled = 0;
s6_command_scaled = 0;
s7_command_scaled = 0;


your stuff would be connected like this:
pin 0 - ESC (this seems odd, pin counts normally start with 1, but that is what is in the code)
pin 6 - elevator
pin 7 - ailerons
pin 8 - rudder
I will say that it looks like it has some functionality I don't see in some of the FCs that I have looked at - it currently has 7 servo outputs and 6 motor outputs configured.

FWIW: looking over more of the code... this isn't a 'plug and play' setup. If you don't have at least a bit of code experience and some understanding on how a FC running a PID loop would control an RC aircraft, this really isn't for you.

The code would really benefit by using some arrays instead of hard coding the name of each item, then some loops would be usable.
 

JasonK

Participation Award Recipient
note, I could be off on the code there, this was me just reading it really quickly and looking for the key bits, there are a handful of things that iNav/BetaFlight/Cleanflight do differently and if I was to write the code, I would have done differently, so there could be a hidden got'cha that I missed by only skimming the code.
 

JasonK

Participation Award Recipient
I am curious on how much the teensy + IMU weighs - curious how it compares to a pre-made FC.
 

the rc project

Well-known member
here is were you setup your mixer, as it stands, it is setup for a quad:
https://github.com/nickrehm/dRehmFl...BETA_1.1/dRehmFlight_Teensy_BETA_1.1.ino#L795

and here is were you set the PID settings (this requires tuning and experimentation to get just right)
https://github.com/nickrehm/dRehmFl...BETA_1.1/dRehmFlight_Teensy_BETA_1.1.ino#L141

if you wanted to do just a basic 4 channel airplane, you would want something like this in the mixer:

m1_command_scaled = thro_des;
m2_command_scaled = 0;
m3_command_scaled = 0;
m4_command_scaled = 0;
m5_command_scaled = 0;
m6_command_scaled = 0;


//0.5 is centered servo, 0 is zero throttle if connecting to ESC for conventional PWM, 1 is max throttle
s1_command_scaled = 0.5f + pitch_PID; // this might need to be a - instead of a + depending on the servo direction
s2_command_scaled = 0.5f + roll_PID; // this might need to be a - instead of a + depending on the servo direction
s3_command_scaled = 0.5f + yaw_PID; // this might need to be a - instead of a + depending on the servo direction
s4_command_scaled = 0;
s5_command_scaled = 0;
s6_command_scaled = 0;
s7_command_scaled = 0;



your stuff would be connected like this:
pin 0 - ESC (this seems odd, pin counts normally start with 1, but that is what is in the code)
pin 6 - elevator
pin 7 - ailerons
pin 8 - rudder
I will say that it looks like it has some functionality I don't see in some of the FCs that I have looked at - it currently has 7 servo outputs and 6 motor outputs configured.

FWIW: looking over more of the code... this isn't a 'plug and play' setup. If you don't have at least a bit of code experience and some understanding on how a FC running a PID loop would control an RC aircraft, this really isn't for you.

The code would really benefit by using some arrays instead of hard coding the name of each item, then some loops would be usable.
Yep... I’ve gotta a lot of learning to do if I’m ever gonna figure this out. Probably should put it down and learn something about coding, as someone with no experience in coding(I’ve used beta flight😂) I understood none of that... please don’t take offence but it’s like reading a new language. It’s definitely a project for someone more proficient on the computer than me... probably gonna take a step back again and do some more research.
 

JasonK

Participation Award Recipient
Yep... I’ve gotta a lot of learning to do if I’m ever gonna figure this out. Probably should put it down and learn something about coding, as someone with no experience in coding(I’ve used beta flight😂) I understood none of that... please don’t take offence but it’s like reading a new language. It’s definitely a project for someone more proficient on the computer than me... probably gonna take a step back again and do some more research.
no offense taken, I 'speak' over 10 computer languages and have still ran into ones that I have trouble reading and couldn't write without some practice. And as I said, I am not 100% I got my recommendations correct, it takes time even for someone who can 'speak' the languages to figure it out.

Honestly, when you said "I never touched a line of code," my initial response was this project was not for you, as it isn't like iNav or Betaflight, were it is already all setup, your just setting up a few bits of configuration via a configuration GUI. Anything you would have done via the GUI in those, you have to write code to do for this project.
 

NickRehm

Member
JasonK is pretty much on the money with his first comment. In the controlMixer() function (scroll down toward the bottom of the code, or ctrl+f to search for it), you have all of the freedom to make what we call "mixing assignments"

This means that we basically tell the sX_command_scaled and mX_command_scaled variables how they should move in response to which axis. Here are all of the variables of interest you might want to "assign" to one of the motor or servo outputs in the control mixer:
snip.PNG


When we say "assign" all we mean is to say that the mX_command_scaled or sX_command_scaled variable is equal to any combination of these above things. For example, if we want motor 1 to have throttle control and stabilized roll control, we would make sure to include this line of code in the control mixer:

m1_command_scaled = thro_des + roll_PID; //+ or - minus depending on the direction the motor is stabilizing (this is a comment, btw, which does not affect the code)

If we want servo 1 to be centered and have unstabilized pitch and roll control (for standard elevons) we would include this line:

s1_command_scaled = 0.5 + roll_passthru + pitch_passthru;

The "amount" can be changed, simply by multiplying by a factor:

s1_command_scaled = 0.5 + 0.5*roll_passthru + pitch_passthru; //roll now has 1/2 the amount of throw as it did before

Servo not centered? Change the 0.5 to something else that centers it:

s1_command_scaled = 0.62 + 0.5*roll_passthru + pitch_passthru;

Want stabilized roll but unstabilized pitch?

s1_command_scaled = 0.62 + 0.5*roll_PID + pitch_passthru;

The code handles everything else in terms of declaring and writing out to the microcontroller pins. Assuming you did the default hardware setup, use this figure for hooking up servos/motors to the correct pins:
pins.PNG

All of this is covered in more detail starting at tutorial 9.7 in the docs. Again--the ONLY thing you have to do now that the radio and IMU is properly setup is change 3-4 lines in the controlMixer() function. I'll have a video coming out soon where I walk through the code in more detail...it might be quite a bit more than you need to understand the basics, but might help break everything down and make it less daunting

Jasonk -- the purpose of this project is to eliminate the complexities of coding to bring it to a level that anyone can understand. Hence no arrays/data structures, classes, etc. Just variables that can be accessed freely whenever/wherever in the code. Is this the 'best' solution? Efficiency wise, absolutely not. There's plenty of things I would do differently too to optimize the code for performance. But the point is to give anyone the ability to change 5-6 lines of code in the control mixer for a highly custom aircraft configuration. Once we get the rc project up and running with a fixed dynamic configuration, we can then implement a simple 'if' statement and he can flip between flight modes. Once that is understood, we can start learning about how to fade between those flight modes. IMO, all of the other flight controllers are way too restrictive for custom projects in that you are forced into their GUI/architecture with absolutely no control over the code.
Also--teensy + IMU is about 12 grams once broken out like in the above pic, so not the lightest of the lightest but good enough for most everything
 

the rc project

Well-known member
JasonK is pretty much on the money with his first comment. In the controlMixer() function (scroll down toward the bottom of the code, or ctrl+f to search for it), you have all of the freedom to make what we call "mixing assignments"

This means that we basically tell the sX_command_scaled and mX_command_scaled variables how they should move in response to which axis. Here are all of the variables of interest you might want to "assign" to one of the motor or servo outputs in the control mixer:
View attachment 191540

When we say "assign" all we mean is to say that the mX_command_scaled or sX_command_scaled variable is equal to any combination of these above things. For example, if we want motor 1 to have throttle control and stabilized roll control, we would make sure to include this line of code in the control mixer:

m1_command_scaled = thro_des + roll_PID; //+ or - minus depending on the direction the motor is stabilizing (this is a comment, btw, which does not affect the code)

If we want servo 1 to be centered and have unstabilized pitch and roll control (for standard elevons) we would include this line:

s1_command_scaled = 0.5 + roll_passthru + pitch_passthru;

The "amount" can be changed, simply by multiplying by a factor:

s1_command_scaled = 0.5 + 0.5*roll_passthru + pitch_passthru; //roll now has 1/2 the amount of throw as it did before

Servo not centered? Change the 0.5 to something else that centers it:

s1_command_scaled = 0.62 + 0.5*roll_passthru + pitch_passthru;

Want stabilized roll but unstabilized pitch?

s1_command_scaled = 0.62 + 0.5*roll_PID + pitch_passthru;

The code handles everything else in terms of declaring and writing out to the microcontroller pins. Assuming you did the default hardware setup, use this figure for hooking up servos/motors to the correct pins:
View attachment 191541
All of this is covered in more detail starting at tutorial 9.7 in the docs. Again--the ONLY thing you have to do now that the radio and IMU is properly setup is change 3-4 lines in the controlMixer() function. I'll have a video coming out soon where I walk through the code in more detail...it might be quite a bit more than you need to understand the basics, but might help break everything down and make it less daunting

Jasonk -- the purpose of this project is to eliminate the complexities of coding to bring it to a level that anyone can understand. Hence no arrays/data structures, classes, etc. Just variables that can be accessed freely whenever/wherever in the code. Is this the 'best' solution? Efficiency wise, absolutely not. There's plenty of things I would do differently too to optimize the code for performance. But the point is to give anyone the ability to change 5-6 lines of code in the control mixer for a highly custom aircraft configuration. Once we get the rc project up and running with a fixed dynamic configuration, we can then implement a simple 'if' statement and he can flip between flight modes. Once that is understood, we can start learning about how to fade between those flight modes. IMO, all of the other flight controllers are way too restrictive for custom projects in that you are forced into their GUI/architecture with absolutely no control over the code.
Also--teensy + IMU is about 12 grams once broken out like in the above pic, so not the lightest of the lightest but good enough for most everything
You’re awesome! this should help put me back on track. I’m determined to try and figure out a vtol but it’s going to take a while to learn and that’s okay. Thanks for the reply it had the information i needed
 

JasonK

Participation Award Recipient
Jasonk -- the purpose of this project is to eliminate the complexities of coding to bring it to a level that anyone can understand. Hence no arrays/data structures, classes, etc. Just variables that can be accessed freely whenever/wherever in the code. Is this the 'best' solution? Efficiency wise, absolutely not.

Having helped multiple people with coding, a bunch of named variables vs an indexed array can be useful for someone just starting out, but in the end they tend to run into issues maintaining the code. honestly I don't see how this servo_command[0] is harder to understand then s1_command_scaled. Also by using loops, it would be easier to switch the ratio between servos and motors, in case you needed more or less of one of the 2. But that is just related to how I would deal with things.

Also--teensy + IMU is about 12 grams once broken out like in the above pic, so not the lightest of the lightest but good enough for most everything
that isn't to bad, the FC I am using right now is ~25-30g, but has 3 BECs on it, current/voltage sensors, and video overlay on it. Your setup has more outputs on it (and those pin headers have some mass to them.
 

NickRehm

Member
You’re awesome! this should help put me back on track. I’m determined to try and figure out a vtol but it’s going to take a while to learn and that’s okay. Thanks for the reply it had the information i needed

All you need to do is get the mixing squared away for the vehicle in hover, and then the vehicle in forward flight--and then we can get you setup to switch between the two very easily. Keep us updated on your progress
 

the rc project

Well-known member
All you need to do is get the mixing squared away for the vehicle in hover, and then the vehicle in forward flight--and then we can get you setup to switch between the two very easily. Keep us updated on your progress
I got servos to move!!!!! Lol. I’m really learning a lot! Slowly but surely, I’ve even got my dad involved (he’s a nitro and balsa guy) one day when I’ve got it figured out we want to build Somthing scale!
 

JasonK

Participation Award Recipient
umm. okay would this work for a 4 ch plane. with an arduino uno or pro mini?
Both of these are well under-powered for this, the teensy has a way more powerful mpu chip.

a benchmark I found on this -> and IIRC the mega is more powerful then either of the ones you mentioned.
1612637509054.png
 

NickRehm

Member
I got servos to move!!!!! Lol. I’m really learning a lot! Slowly but surely, I’ve even got my dad involved (he’s a nitro and balsa guy) one day when I’ve got it figured out we want to build Somthing scale!

Very excited to see you get something flying. A fixed wing or flying wing might be a good first project to get a better feel for the code changes in the control mixer. I would start with unstabilized control (really no need for a flight controller if this is the case, but its more an exercise in understanding the code than anything). You can get a feel for leveling the control surfaces, scaling the outputs for different control deflection, and even mixing if you design something with elevons. Then you can swap out the unstabilized variables for stabilized variables and work on tuning the controller gains. With an 'if' statement in the control mixer, you will even be able to flip between stabilized and unstabilized control while in flight--which would help in tuning the controller gains and having a safety net in that you can always flip back into unstabilized flight
 

the rc project

Well-known member
Very excited to see you get something flying. A fixed wing or flying wing might be a good first project to get a better feel for the code changes in the control mixer. I would start with unstabilized control (really no need for a flight controller if this is the case, but its more an exercise in understanding the code than anything). You can get a feel for leveling the control surfaces, scaling the outputs for different control deflection, and even mixing if you design something with elevons. Then you can swap out the unstabilized variables for stabilized variables and work on tuning the controller gains. With an 'if' statement in the control mixer, you will even be able to flip between stabilized and unstabilized control while in flight--which would help in tuning the controller gains and having a safety net in that you can always flip back into unstabilized flight
Exactly what I was thinking, I will be making a trainer aircraft to test the board before I do Somthing crazy. Having this small bit of success has me dreaming of building a Do31.... baby steps 😂
 

Attachments

  • 14708430-9FF5-47B0-9B45-19D7009046DF.jpeg
    14708430-9FF5-47B0-9B45-19D7009046DF.jpeg
    552.3 KB · Views: 0

NickRehm

Member
Here is a pretty extensive (boring) video where I walk through the code step by step to try to de-mystify what's going on inside the flight controller. I recommend watching once, then scrolling through and exploring the code to see the areas I talked about, then giving it another watch to solidify your understanding. I didn't cover everything, but its a great start to making some modifications once the radio and IMU is setup. I'll be making another video focused solely on the things you can do in the control mixer soon.

 

the rc project

Well-known member
Hey rcjetflyer, i've been learning a lot because of the teensy! right now i've got the wing of a Do31 that can hover!!!!!! still have lots of work to do till i can call it a plane but still a huge success. however i am a little stumped with how to set up the transition. In section 9.9 on the PDF it says "if(channel_6_pwm > 1500 { // hover mode". When i go directly below the controlMixer() (still in the control mixer section) the code says
"
//Example use of the linear fader for float type variables. Linearly interpolate between minimum and maximum values for Kp_pitch_rate variable based on state of channel 6:
/*
if (channel_6_pwm > 1500){ //go to max specified value in 5.5 seconds
Kp_pitch_rate = floatFaderLinear(Kp_pitch_rate, 0.1, 0.3, 5.5, 1, 2000); //parameter, minimum value, maximum value, fadeTime (seconds), state (0 min or 1 max), loop frequency
}
if (channel_6_pwm < 1500) { //go to min specified value in 2.5 seconds
Kp_pitch_rate = floatFaderLinear(Kp_pitch_rate, 0.1, 0.3, 2.5, 0, 2000); //parameter, minimum value, maximum value, fadeTime, state (0 min or 1 max), loop frequency
}
*/

my question is, am I in the wrong place or do i edit this part of the code?
(edit: i have another question... I don't quite understand floats. are they just servo trim?
once again sorry for the noob questions but here's some details of the project if it helps. I am using 4x2206 quad motors for hovering, and 2 larger motors as pushers along with rudder, aileron, and elevator. im building a Do31 like i said i was dreaming about! only this one will be powered by only props rather than edfs for a multitude of reasons. it is essentially a twin pusher with a quad copter in the wingtips.
 

Attachments

  • ED5F593F-1FF9-4FB1-8C67-CD6794B55F7C.jpeg
    ED5F593F-1FF9-4FB1-8C67-CD6794B55F7C.jpeg
    2.4 MB · Views: 0