Solved need help with custom elevon mixing

Contra47

New member
hello there
beware of bad English 🤣
currently i'm building a wing ( more specifically i will use the FT spear) using my nine eagles j5 pro transmitter
(sadly i crash landed the plane...) so i'm using arduino 101 in order to control the plane, but who ever knows the j5 pro, it doesnt have mixing
so i am trying to mix the channels in the arduino, but i cant figure the correct combination in order to control the servo motors,
can anyone knows what is the "formula", or just explain what are the values of mixing elevon. ive searched google on that, tried some examples but it didnt work
perhaps i dont know enough or simply missing some crucial thing...
that is the only barrier that keeps me from getting started building the plane.

thanks for your attention

p.s i will more grateful if you know the code for the "arduino elevon mixing" using simply the values 1 to 180 😁
 

Merv

Site Moderator
Staff member
I don’t know about arduino code so I will use transmitter settings & let you convert the ideas to code. Transmitter values typically go from +100 to -100 to represent full up and full down of a control surface. A zero value represents neutral control surface position.

For ailerons, one servo should be +100 & the other should be -100. That is one side should go up when the other should go down. If the control is reversed, swap the positive and negative values. With the elevator both servos should be +100. That is, they should both go up or down. If the elevator control is reversed, make the value-100. In your coding, you should limit the maximum servo. That is don’t let the values go higher than +100 or lower than -100.
 

Contra47

New member
OK, thanks for the explanation
second question
if i transmit for example ( ele = +50 & ail = -35 )
i just do simple average math or something like vector math?
because i'm able to control aileron and elevator separately but i cant mix it properly
 

Merv

Site Moderator
Staff member
On my transmitter (Tx) the values simply added together, then limited to the maximum servo travel. In your example 50-35=15

Another possibility, instead of using 100’s limit the values to 50. That way you can’t exceed the maximum travel.

In coding, I believe one servo will use the raw aileron input and the other will take the raw value times -1.
 
Last edited:

H49

New member
Hey can you share the code?
Tell me the channel input type (ppm or own) , your transmitter and receiver name/info and which Arduino you gonna use for mixing. I will make the code for you or you can have my code for f 22 and edit it your self.
 

H49

New member
Hey can you share the code?
Hi ,

Himanshu here. I have made my own transmitter and receiver using Arduino Uno and nrf24lo1 PA modual which I'm using for my F22 build which require elevon mix. So if you have the same requirements Tell me your transmitter receiver details as well as which signal do you use (pwm,ppm) and your Arduino type I will edit my code for your needs.
 

Saqib sanadi

New member
Hey thank you sooo much for your help. I am using arduino nano and nrf24l01. I am using pwm signals can you share me your codes it would be very helpful for me i am using 3 channel 1 for throttle and the rest two to elevons.
 

H49

New member
/* here you go..... */

/*
EDITED BY H49, THE ORIGNAL RECEIVER CODE IS MADE BY ELETRONOOBS
CHECK OUT HIS YOUTUBE CHANNEL FOR THE TRANSMITTER PART
PLEASE READ EACH AND EVERY COMMENTS FOR YOUR COMFORT

**FOR NRF24LO1
GND -> GND
Vcc -> 3.3V
CE -> D9
CSN -> D10
CLK -> D13
MOSI -> D11
MISO -> D12

**ESC -> D2
**SERVO -> D5,D6

*/



#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h> //To create PWM signals we need this library

//Set the throw angle of servo,from 0 to 180 degree , this will allow to set the throws for elevator
#define servoUpRange 180
#define servoDownRange 0

//the below values are for the mixing, set it as per your requirement, this will allow to set the throws for ailerons
#define servoMaxRange 135
#define servoMidRange 67.5
#define servoMinRange 0

/*
*************DONT FORGET TO CHANGE THIS in the transmitter*******************
*/
const uint64_t pipeIn = 0xE8E8F0F0E1LL;//Remember that this code is the same as in the transmitter

RF24 radio(9, 10); //CSN = 9 and CE = 10 pins, you can set any digital pin

// The sizeof this struct should not exceed 32 bytes
struct Received_data {
byte ch1;
byte ch2;
byte ch3;
};

Received_data received_data;

Servo channel_1;

//left right servo is just for name, in case if you get reversed output just change the servo pins
Servo left; //left servo
Servo right; //right servo

// DO NOT CHANGE ANY VALUE HERE
word sensorValue1 = 0; // Read raw value for up/down motion for elevons
word sensorValue2 = 0; // Read raw value for roll, left/right motion for elevons
byte leftElevator = 0;
byte rightElevator = 0;
byte roll = 0;
byte leftServo = 0;
byte rightServo = 0;
byte rollLeft = 0;
byte rollRight = 0;

int ch1_value = 0;
int ch2_value = 0;
int ch3_value = 0;

void reset_the_Data()
{
// 'safe' values to use when NO radio input is detected
received_data.ch1 = 0; //Throttle (channel 1) to 0
received_data.ch2 = 127;
received_data.ch3 = 127;

}



/**************************************************/

void setup()
{
//Attach the servo signal on pins from D2 to D8
channel_1.attach(2);
left.attach(5); // Attach servo to PWM pin 9
right.attach(6); // Attach servo to PWM pin 6

//We reset the received values
reset_the_Data();

//Once again, begin and radio configuration
radio.begin();
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.openReadingPipe(1,pipeIn);

//We start the radio comunication
radio.startListening();

}

/**************************************************/

unsigned long lastRecvTime = 0;

//We create the function that will read the data each certain time
void receive_the_data()
{
while ( radio.available() ) {
radio.read(&received_data, sizeof(Received_data));
lastRecvTime = millis(); //Here we receive the data
}
}

/**************************************************/

void loop()
{
//Receive the radio data
receive_the_data();

//////////This small if will reset the data if signal is lost for 1 sec.
/////////////////////////////////////////////////////////////////////////
unsigned long now = millis();
if ( now - lastRecvTime > 1000 ) {
// signal lost?
reset_the_Data();
//Go up and change the initial values if you want depending on
//your aplications. Put 0 for throttle in case of drones so it won't
//fly away
}


ch1_value = map(received_data.ch1,0,255,1000,2000);

sensorValue1 = received_data.ch3; //
sensorValue2 = received_data.ch2; // Read raw value from 0 TO 255

//Create the PWM signals
channel_1.writeMicroseconds(ch1_value); // THIS SIGNAL IS FOR ESC

////////////////////HERE WE DO MATH OPRATION FOR SERVO MIXING//////////////////////////////////

leftElevator = map(sensorValue1, 0, 255, servoDownRange, servoUpRange); //
roll = map(sensorValue2, 0, 255, servoMinRange, servoMaxRange); // MAPPING THE RECEIVED VALUES TO OUR PRE DEFINE VALUES
rightElevator = map(sensorValue1, 0, 255, servoUpRange, servoDownRange); //

rollLeft = constrain(roll, servoMidRange, servoMaxRange); //
rollLeft = map(rollLeft, servoMidRange, servoMaxRange, servoMinRange, servoMidRange); //IF THIS CONFUSED YOU, GO TO //https://www.arduino.cc/reference/en/language/functions/math/map/
rollRight = constrain(roll, servoMinRange, servoMidRange); //FOR MORE INFO..
rollRight = map(rollRight, servoMinRange, servoMidRange, servoMidRange, servoMinRange); //

leftServo = constrain((leftElevator-rollLeft+rollRight), servoDownRange, servoUpRange);
rightServo = constrain((rightElevator+rollRight-rollLeft), servoDownRange, servoUpRange);

//////////////////////////////// MIXING DONE///////////////////////

left.write(leftServo); //
right.write(rightServo); // WRITING THE SERVO SIGNAL



}//Loop end
 

mrjdstewart

Legendary member
OMG, soooooo glad i don't have to deal with that. it makes my head hurt just looking at it. if i had to do that for every plane i have, i never would have gotten into the hobby. :LOL:

(y) for the effort!

me :cool:
 

H49

New member
Hey thank you sooo much for your help. I am using arduino nano and nrf24l01. I am using pwm signals can you share me your codes it would be very helpful for me i am using 3 channel 1 for throttle and the rest two to elevons.


did the code work?
did you face any problem?
 

Talal zahid

New member
did the code work?
did you face any problem?
Hi, I am having some issues. I tried your code but the elevons are not working properly. there is a delay in servos moving and also when I move the roll joystick only one servo moves and similar is the case with the elevator joystick. Please help me, bro. I need your help. Thanks in Advance.
 

H49

New member
Hi, I am having some issues. I tried your code but the elevons are not working properly. there is a delay in servos moving and also when I move the roll joystick only one servo moves and similar is the case with the elevator joystick. Please help me, bro. I need your help. Thanks in Advance.


Plz attach the wiring photos and also tell me in which pin did you attached the servo signal wire. And also look into the transmitter code and check for any error.
 

MayinjaBob

New member
Plz attach the wiring photos and also tell me in which pin did you attached the servo signal wire. And also look into the transmitter code and check for any error.
hello thanks for the code i am also using it, the first time it worked but now it's giving me the same headache.
 

NickRehm

Member
hello thanks for the code i am also using it, the first time it worked but now it's giving me the same headache.
Ditch the code in this thread....I am not sure what exactly it is doing but it is spaghetti to say the least.

Get radio values into your void loop. Figure out whatever range they are (e.g. 1000-2000 with a calibrated radio using pwm into the arduino).

The code in the void loop for elevon mixing should look something like this:
Code:
//map radio input values to 'normalized' command values for roll and pitch
float roll_command = map(ch2_pwm,1000,2000,-1000,1000)/1000.0; //map your roll pwm value from 1000-2000 range to -1.0 to 1.0 range to 'normalize' it
float pitch_command = map(ch3_pwm,1000,2000,-1000,1000)/1000.0; //map your pitch pwm value from 1000-2000 range to -1.0 to 1.0 range to 'normalize' it

//this is the mixing 'magic' for elevons...change the sign in front of the variables if anything is reversed for either servo:
float S1_command = roll_command +  pitch_command;
float S2_command = roll_command -  pitch_command;
//note you can also reduce the 'amount' of roll or pitch here by multiplying either of the variables by a float from 0.0 (no contribution) to 1.0 (full contribution)

//constrain the servo command variables to stay within -1 to 1 range
S1_command = constrain(S1_command,-1.0,1.0);
S2_command = constrain(S1_command,-1.0,1.0);

//write the command values out using the servo library (assuming you've already created/attached your servo objects in the void setup):
S1.write(map(S1_command,-1.0,1.0,0.0,180.0); //we remapped the normalized command from -1-1 to 0-180, which is what the servo library expects as an input
S2.write(map(S2_command,-1.0,1.0,0.0,180.0);

You can add variables in a similar way for throttle and rudder, and add more servo outputs as you need. For direct throttle control of an output, you'd just assign the 'throttle_command' variable you created from the radio throttle channel to the servo output variable you'd like to react to throttle input. Have fun with the mixing; you can add/subtract any combination of your throttle-roll-pitch-yaw command values to the servo command values to do things like elevons, flaps, differential thrust ,etc.[/CODE]
 
Last edited:

hirak

New member
hello sir, huge fan of you :giggle: i love your vtol f-35 jet, sir can you pls help me to write elevon mixing ob this code

// 4 Channel Transmitter | 4 Kanal Verici

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

const uint64_t pipeOut = 0xE9E8F0F0E1LL; //IMPORTANT: The same as in the receiver 0xE9E8F0F0E1LL | Bu adres alıcı ile aynı olmalı
RF24 radio(7, 8); // select CE,CSN pin | CE ve CSN pinlerin seçimi

struct Signal {
byte throttle;
byte pitch;
byte roll;
byte yaw;
};

Signal data;

void ResetData()
{
data.throttle = 127; // Motor Stop (254/2=127)| Motor Kapalı (Signal lost position | sinyal kesildiğindeki pozisyon)
data.pitch = 127; // Center | Merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
data.roll = 127; // Center | merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
data.yaw = 127; // Center | merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
}

void setup()
{
//Start everything up

radio.begin();
radio.openWritingPipe(pipeOut);
radio.stopListening(); //start the radio comunication for Transmitter | Verici olarak sinyal iletişimi başlatılıyor
ResetData();
}

// Joystick center and its borders | Joystick merkez ve sınırları

int mapJoystickValues(int val, int lower, int middle, int upper, bool reverse)
{
val = constrain(val, lower, upper);
if ( val < middle )
val = map(val, lower, middle, 0, 128);
else
val = map(val, middle, upper, 128, 255);
return ( reverse ? 255 - val : val );
}

void loop()
{
// Control Stick Calibration | Kumanda Kol Kalibrasyonları
// Setting may be required for the correct values of the control levers. | Kolların doğru değerleri için ayar gerekebilir.

data.throttle = mapJoystickValues( analogRead(A0), 524, 524, 1015, true );
data.roll = mapJoystickValues( analogRead(A1), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler
data.pitch = mapJoystickValues( analogRead(A2), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler
data.yaw = mapJoystickValues( analogRead(A3), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler

radio.write(&data, sizeof(Signal));
}
 

hirak

New member
Ditch the code in this thread....I am not sure what exactly it is doing but it is spaghetti to say the least.

Get radio values into your void loop. Figure out whatever range they are (e.g. 1000-2000 with a calibrated radio using pwm into the arduino).

The code in the void loop for elevon mixing should look something like this:
Code:
//map radio input values to 'normalized' command values for roll and pitch
float roll_command = map(ch2_pwm,1000,2000,-1000,1000)/1000.0; //map your roll pwm value from 1000-2000 range to -1.0 to 1.0 range to 'normalize' it
float pitch_command = map(ch3_pwm,1000,2000,-1000,1000)/1000.0; //map your pitch pwm value from 1000-2000 range to -1.0 to 1.0 range to 'normalize' it

//this is the mixing 'magic' for elevons...change the sign in front of the variables if anything is reversed for either servo:
float S1_command = roll_command +  pitch_command;
float S2_command = roll_command -  pitch_command;
//note you can also reduce the 'amount' of roll or pitch here by multiplying either of the variables by a float from 0.0 (no contribution) to 1.0 (full contribution)

//constrain the servo command variables to stay within -1 to 1 range
S1_command = constrain(S1_command,-1.0,1.0);
S2_command = constrain(S1_command,-1.0,1.0);

//write the command values out using the servo library (assuming you've already created/attached your servo objects in the void setup):
S1.write(map(S1_command,-1.0,1.0,0.0,180.0); //we remapped the normalized command from -1-1 to 0-180, which is what the servo library expects as an input
S2.write(map(S2_command,-1.0,1.0,0.0,180.0);

You can add variables in a similar way for throttle and rudder, and add more servo outputs as you need. For direct throttle control of an output, you'd just assign the 'throttle_command' variable you created from the radio throttle channel to the servo output variable you'd like to react to throttle input. Have fun with the mixing; you can add/subtract any combination of your throttle-roll-pitch-yaw command values to the servo command values to do things like elevons, flaps, differential thrust ,etc.[/CODE]
hello sir, huge fan of you :giggle: i love your vtol f-35 jet, sir can you pls help me to write elevon mixing ob this code

// 4 Channel Transmitter | 4 Kanal Verici

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

const uint64_t pipeOut = 0xE9E8F0F0E1LL; //IMPORTANT: The same as in the receiver 0xE9E8F0F0E1LL | Bu adres alıcı ile aynı olmalı
RF24 radio(7, 8); // select CE,CSN pin | CE ve CSN pinlerin seçimi

struct Signal {
byte throttle;
byte pitch;
byte roll;
byte yaw;
};

Signal data;

void ResetData()
{
data.throttle = 127; // Motor Stop (254/2=127)| Motor Kapalı (Signal lost position | sinyal kesildiğindeki pozisyon)
data.pitch = 127; // Center | Merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
data.roll = 127; // Center | merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
data.yaw = 127; // Center | merkez (Signal lost position | sinyal kesildiğindeki pozisyon)
}

void setup()
{
//Start everything up

radio.begin();
radio.openWritingPipe(pipeOut);
radio.stopListening(); //start the radio comunication for Transmitter | Verici olarak sinyal iletişimi başlatılıyor
ResetData();
}

// Joystick center and its borders | Joystick merkez ve sınırları

int mapJoystickValues(int val, int lower, int middle, int upper, bool reverse)
{
val = constrain(val, lower, upper);
if ( val < middle )
val = map(val, lower, middle, 0, 128);
else
val = map(val, middle, upper, 128, 255);
return ( reverse ? 255 - val : val );
}

void loop()
{
// Control Stick Calibration | Kumanda Kol Kalibrasyonları
// Setting may be required for the correct values of the control levers. | Kolların doğru değerleri için ayar gerekebilir.

data.throttle = mapJoystickValues( analogRead(A0), 524, 524, 1015, true );
data.roll = mapJoystickValues( analogRead(A1), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler
data.pitch = mapJoystickValues( analogRead(A2), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler
data.yaw = mapJoystickValues( analogRead(A3), 12, 524, 1020, true ); // "true" or "false" for servo direction | "true" veya "false" servo yönünü belirler

radio.write(&data, sizeof(Signal));
}