Kirjoittaja Aihe: Joystick radioon?  (Luettu 7683 kertaa)

Poissa ChiKung

  • Pro torppari
  • ****
Joystick radioon?
« : 26 Elokuu, 2011, 14:51:59 »
Kaikkea sitä näkee kun vanhaksi elää.



Mitenhän lie, tuleekohan tuollaiset yleistymään FPV-käytössä ja onkohan tuosta Force Feedbackista mitään käytännön hyötyä?

Onko kukaan askarrellut ilotikkua radioon, vaikkapa arduinolla analogisesta ppm:ksi?
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa Turmoil

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #1 : 26 Elokuu, 2011, 15:09:33 »
Kyllähän tuo näyttää älyttömän hienolta systeemiltä :). Ei tietenkään kopterien kanssa toimisi (ainakaan hyvin) mutta siltikin. Varsinkin tuo kameran liikuttelu on hienon näköinen ominaisuus. Voiko näitä siis ostaa jostain vai onko tuo vain jonkun itse rakentelema viritys?

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #2 : 26 Elokuu, 2011, 15:34:23 »
Kyllähän tuo näyttää älyttömän hienolta systeemiltä :). Ei tietenkään kopterien kanssa toimisi (ainakaan hyvin) mutta siltikin. Varsinkin tuo kameran liikuttelu on hienon näköinen ominaisuus. Voiko näitä siis ostaa jostain vai onko tuo vain jonkun itse rakentelema viritys?
Kyllähän tuota on myynnissä varsin suolaiseen hintaan, jos tuon force feedbackin haluaa toimimaan. Ilman tuota on valmiita koodeja saatavilla ainakin arduinoon. Tuo ei tosin toimi USB-hostina, eli pitää puukottaa tikusta suoraan potikat ADC:lle.

En näe mitään syytä miksei toimisi kopterissakin. Peräähän pyöritellään tikkua kiertämällä. Niin ja "päätä" pyöritellään tuosta tikun päältä... Tuli väsäiltyä yksi kamerateline niin ajattelin jos joku foorumilainen olisi vastaavaa tikkuhässäkkää kokeillut.

Edit. Onkohan missään valmista koodia johonkin USB-hostina toimivaan kontrolleriin?
« Viimeksi muokattu: 26 Elokuu, 2011, 15:38:36 kirjoittanut ChiKung »
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa Trnquill

  • Seniori torppari
  • *****
Vs: Joystick radioon?
« Vastaus #3 : 26 Elokuu, 2011, 15:50:09 »

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #4 : 10 Marraskuu, 2011, 09:02:35 »
Tuollanen koodi löytyy valmiina: http://www.ianjohnston.com/content/index.php?option=com_content&view=article&id=30:project-rc-ppm-trainer-port-joystick

Pitäisi löytää sopiva tikku projektiin. Työkaverilta saan jonkun vanhan, mutta en vielä tiedä onko riittävästi akseleita. Hattunäppäimen haluaisin lisätä tuohon, vieläpä sopivalla rate limitterillä jos pelkkä on-off-on -nappi. Saisi kameratelineen kääntelyn hattuun. Pitäisi päästä kohtalaisen helpolla ja halvemmalla kuin HK:n valmiissa paketissa.

Ps. Mitenhän tuo trainerportti käytännössä toimii? Saanko kuitenkin radiosta esim. miksaukset käyttöön?
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #5 : 11 Marraskuu, 2011, 09:57:43 »
no ni. Saitekin tikkuhan se on. Akseleita tarpeeksi, hattunäppäin ja kaasuvipu. Pitääpä kokeilla kuinka toimii tuossa. Jos onnistuu niin dokumentoin tänne.
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #6 : 20 Marraskuu, 2011, 14:41:20 »
Pikkuhiljaa kasautuu tuokin. Signaalit ovat ok, mutta askarruttaa tuon kytkeminen radioon. Millaista signaalia tuo Spektrum syö?

Tuollaista pitäisi olla kaiketi sisään:


ja kanavat:

    Throttle
    Ailerons
    Vertical stabilizer
    Rudder
    Aux2 or Gear
    Aux2 or Gear
    Usually a mix
    Unused on the DX7


... mutta mitenhän signaalitasot? Vai pitääkö olla open collector -anto? Onko tuolla jonkunlainen suojaus (dc-block + transienttilimitteri), eli uskaltaako tökätä arduinon annon suoraan trainer porttiin?
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #7 : 19 Joulukuu, 2011, 18:32:51 »
Trainer portti antaa pihalle DC-erotetun signaalin. Laitoin erotuskonkat ja niiden jälkeen TVS:n ja vielä megasen vastuksen maihin. Hyvin sai toimimaan. Siis tuon itse trainer portin. Muuten käyttömukavuus olikin nolla, eli radiosta pitää painaa koko ajan sitä trainer-nappulaa jos aikoo saada homman toimimaan. Toisena vaihtoehtona joku hieno viritys, jossa tatit ovat keskellä, jolloin ei tarvitse painaa nappia, mutta trainee voi käyttää vain neljää kanavaa...

Arvelinkin että joku ongelma tuossa tulisi. Ratkaisu oli onneksi helppo. Tilailin FrSky:n 2,4 gigasen RF-modulin. Huomasin vasta tilattuani futaban että fiksumpi olisi ollut tilata diy-moduuli, joita niitäkin on saatavilla. No kuitenkin tuosta arduinosta hilavastuksen läpi fetille, jolla open-collector signaali futteen käypäselle modulille. Hienosti lähti homma toimimaan ja FrSky lupailee tuolle vakiona 1,5 km kantamaa.
« Viimeksi muokattu: 20 Joulukuu, 2011, 07:42:14 kirjoittanut ChiKung »
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa okallio

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #8 : 20 Joulukuu, 2011, 10:03:28 »
Ootko suoraan käyttäny tuota ianjohnstonin koodia vai onko tarttenu puukottaa? Oon suunnitellu tommosta saman tyylistä 2.4G moduli/Arduino-komboa head trackerin kaveriksi kun loppuu 9C/Spektrum-setistä kanavat kesken. Samaan sitten kameran triggerit sun muut.

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #9 : 20 Joulukuu, 2011, 15:35:35 »
Käytin sitä sen ensimmäisen version koodia pohjana. Eli tuossa ei ole mitään näyttöjä tai summereita. Samoten poistelin ylimääräisiä skaalauksia ja multi raten siitä. Lisäyksinä sitten läjä nappeja digipinneihin.. Ei enää riittänyt napit laipoille asti, niin sen tein on-off-on -kytkimestä ja vastusjaosta niin sai kolme asentoa. Niin ja signaalit on invertoitu, kun käytän fettiä open-collectorina.

Vielä vähän hiomista tuossa koodissa. Esim. trimmit pitää vielä muuttaa reunaherkiksi, nyt vaan lisäävät tai poistavat trimmistä aina kun nappi on pohjassa, eli käytännössä paukauttavat trimmit jompaan kumpaan laitaan. Samoten pulssit pitää vielä laittaa oikean mittaisiksi, nyt eivät ole tuota 1500 us keskellä. Jotain tuohon suuntaan kuitenkin. Pinninumeroinnit yms. menevät toki uusiksi, mutta ei ole monimutkainen tuo koodi.

Koodia: [Valitse]
/*Analogue Inputs pins:

  Pin 0 = Elevator potentiometer
  Pin 1 = Aeleron potentiometer
  Pin 2 = Rudder potentiometer 
  Pin 3 = Throttle potentiometer
  Pin 4 = Aux potentiometer
  Pin 5 =

Digital Input pins:
  Pin 2 =
  Pin 3 = Trim right
  Pin 4 = Trim left
  Pin 5 = Hat up
  Pin 6 = Trigger
  Pin 7 = Hat down
  Pin 8 = Thumb Middle
  Pin 9 = Hat left
  Pin 10 = Thumb Right       
  Pin 11 = Hat right
  Pin 12 = Thumb Left
  Pin 13 =   

PPM Spektrum:

1    Throttle
2    Ailerons
3    Vertical stabilizer
4    Rudder
5    Aux2 or Gear
6    Aux2 or Gear
7    Usually a mix
 
 
*/



int AI_Pin_AEL = 4;    // Ana In - Aeleron potentiometer (Ana In Ch.0 playing up?)
int AI_Pin_ELE = 1;    // Ana In - Elevator potentiometer
int AI_Pin_THR = 3;    // Ana In - Throttle potentiometer
int AI_Pin_RUD = 2;    // Ana In - Rudder potentiometer
int AI_Pin_FLAP = 5;    // Ana In - three state FLAP input with voltage divider


int AI_Raw_AEL;        // Ana In raw var - 0->1023
int AI_Raw_ELE;        // Ana In raw var - 0->1023
int AI_Raw_THR;        // Ana In raw var - 0->1023
int AI_Raw_RUD;        // Ana In raw var - 0->1023
int AI_Raw_FLAP;        // Ana In raw var - 0->1023


int AI_AEL;           // Ana In var - 0->1023 compensated
int AI_ELE;           // Ana In var - 0->1023 compensated
int AI_THR;           // Ana In var - 0->1023 compensated
int AI_RUD;           // Ana In var - 0->1023 compensated
int AI_FLAP;           // Ana In var - 0->1023 compensated


int Aeleron_uS = 1100;     // Ana In Ch.0 uS var - Aeleron
int Elevator_uS = 1100;    // Ana In Ch.1 uS var - Elevator
int Throttle_uS = 1100;    // Ana In Ch.2 uS var - Throttle
int Rudder_uS = 1100;      // Ana In Ch.3 uS var - Rudder
int Flap_uS = 1120;      // Ana In Ch.3 uS var - Rudder


 
 // omat lisäykset:

int Hat_horizontal_uS = 1120;
int Hat_vertical_uS = 1120;
int Hat_horizontal_lowpass = 1120;
int Hat_vertical_lowpass = 1120;


int Trim_Aeleron = 50; // Thumb left/right
int Trim_Elevator = 50; // trigger / center
int Trim_Rudder = 50; // left / right



int Fixed_uS = 400;       // PPM frame fixed LOW phase
int pulseMin = 600;       // pulse minimum width minus start in uS
int pulseMax = 1600;      // pulse maximum width in uS

int outPinPPM = 2;        // digital pin 10
int inPinD3 = 3;          // Trim right
int inPinD4 = 4;          // Trim left
int inPinD5 = 5;          // Hat up
int inPinD6 = 6;          // Trigger
int inPinD7 = 7;          // Hat down
int inPinD8 = 8;          // Thumb middle
int inPinD9 = 9;          // Hat left
int inPinD10 = 10;        // Thumb right
int inPinD11 = 11;        // Hat right
int inPinD12 = 12;        // Thumb left
int outPinTEST = 13;      // digital pin 8


ISR(TIMER1_COMPA_vect) {
ppmoutput(); // Jump to ppmoutput subroutine
}

void setup() {

//  Serial.begin(9600) ; // Test

pinMode(outPinPPM, OUTPUT);   // sets the digital pin as output

pinMode(inPinD3, INPUT);      // sets the digital pin as input
digitalWrite(inPinD3, HIGH);  // turn on pull-up resistor

pinMode(inPinD4, INPUT);      // sets the digital pin as input
digitalWrite(inPinD4, HIGH);  // turn on pull-up resistor

pinMode(inPinD5, INPUT);      // sets the digital pin as input
digitalWrite(inPinD5, HIGH);  // turn on pull-up resistor

pinMode(inPinD6, INPUT);      // sets the digital pin as input
digitalWrite(inPinD6, HIGH);  // turn on pull-up resistor

pinMode(inPinD7, INPUT);      // sets the digital pin as input
digitalWrite(inPinD7, HIGH);  // turn on pull-up resistor

pinMode(inPinD8, INPUT);      // sets the digital pin as input
digitalWrite(inPinD8, HIGH);  // turn on pull-up resistor

pinMode(inPinD9, INPUT);      // sets the digital pin as input
digitalWrite(inPinD9, HIGH);  // turn on pull-up resistor

pinMode(inPinD10, INPUT);      // sets the digital pin as input
digitalWrite(inPinD10, HIGH);  // turn on pull-up resistor

pinMode(inPinD11, INPUT);     // sets the digital pin as input
digitalWrite(inPinD11, HIGH); // turn on pull-up resistor

pinMode(inPinD12, INPUT);      // sets the digital pin as input
digitalWrite(inPinD12, HIGH);  // turn on pull-up resistor


// Setup timer
TCCR1A = B00110001; // Compare register B used in mode '3'
TCCR1B = B00010010; // WGM13 and CS11 set to 1
TCCR1C = B00000000; // All set to 0
TIMSK1 = B00000010; // Interrupt on compare B
TIFR1  = B00000010; // Interrupt on compare B
OCR1A = 22000; // 22mS PPM output refresh
OCR1B = 1000;
}


void ppmoutput() { // PPM output sub

/*
1    Throttle
2    Ailerons
3    Vertical stabilizer
4    Rudder
5    Aux2 or Gear
6    Aux2 or Gear
7    Usually a mix
*/

// test pulse - used to trigger scope
// digitalWrite(outPinTEST, LOW);
// delayMicroseconds(100);    // Hold
// digitalWrite(outPinTEST, HIGH);

// Channel 1
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Throttle_uS);  // Hold for Aeleron_uS microseconds

// Channel 2
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Aeleron_uS); // Hold for Elevator_uS microseconds

// Channel 3
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Elevator_uS); // Hold for Throttle_uS microseconds

// Channel 4
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Rudder_uS);   // Hold for Rudder_uS microseconds

// Channel 5 - Hat vertical
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Hat_vertical_uS);     // Hold for hat vert microseconds

// Channel 6 - Hat horizontal
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Hat_horizontal_uS);       // Hold for hat hor microseconds

// Channel 6 - Flap
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Flap_uS);       // Hold for flap microseconds

// Synchro pulse
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);  // Start Synchro pulse

}


void loop() { // Main loop

// Read analogue ports
AI_Raw_AEL = analogRead(AI_Pin_AEL);
AI_Raw_ELE = analogRead(AI_Pin_ELE);
AI_Raw_THR = analogRead(AI_Pin_THR);
AI_Raw_RUD = analogRead(AI_Pin_RUD);
AI_Raw_FLAP = analogRead(AI_Pin_FLAP);


// Compensate for discrepancy in pot inputs including centering offset.
// Also use this to invert inputs if necessary (swap x1 & y1)
// y=mx+c, x to y scales to x1 to y1

AI_AEL = map(AI_Raw_AEL, 0, 1023, 1300, 0) - 50; // Invert Aeleron pot and slight centre offset
AI_ELE = map(AI_Raw_ELE, 0, 1023, 1300, 0) - 50; // Invert Elevator pot and slight centre offset
AI_THR = map(AI_Raw_THR, 0, 1023, 1300, 0) + 0;  // Throttle
AI_RUD = map(AI_Raw_RUD, 0, 1023, 200, 1400) - 100;  // Rudder

// Map flaps:
if (AI_Raw_FLAP <= 200){ AI_FLAP = 1120;}     // Min
if (AI_Raw_FLAP >= 800){ AI_FLAP = 600;}     // Max
if (AI_Raw_FLAP > 200 && AI_Raw_FLAP < 800){ AI_FLAP = 850;}

// flap rate reducer
if (AI_FLAP > Flap_uS) {Flap_uS += 5;}
if (AI_FLAP < Flap_uS) {Flap_uS -= 5;}
if (Flap_uS > AI_FLAP - 10 && Flap_uS < AI_FLAP + 10) {Flap_uS = AI_FLAP;}



// Map analogue inputs to PPM rates for each of the channels
Aeleron_uS = (AI_AEL) + pulseMin + Trim_Aeleron - 50 - 60;
Elevator_uS = (AI_ELE) + pulseMin + Trim_Elevator - 50 - 60;
Throttle_uS = (AI_THR) + pulseMin - 150;
Rudder_uS = (AI_RUD) + pulseMin + Trim_Rudder - 50 - 60;

// Check limits
if (Aeleron_uS <= 600) Aeleron_uS = 600;     // Min
if (Aeleron_uS >= 1600) Aeleron_uS = 1600;   // Max
if (Elevator_uS <= 600) Elevator_uS = 600;   // Min
if (Elevator_uS >= 1600) Elevator_uS = 1600; // Max
if (Throttle_uS <= 600) Throttle_uS = 600;   // Min
if (Throttle_uS >= 1600) Throttle_uS = 1600; // Max
if (Rudder_uS <= 600) Rudder_uS = 600;       // Min
if (Rudder_uS >= 1600) Rudder_uS = 1600;     // Max
if (Flap_uS <= 600) Flap_uS = 600;       // Min
if (Flap_uS >= 1120) Flap_uS = 1120;     // Max


if (Hat_horizontal_lowpass <= 600) Hat_horizontal_lowpass = 600;               // Min
if (Hat_horizontal_lowpass >= 1600) Hat_horizontal_lowpass = 1600;             // Max
if (Hat_vertical_lowpass <= 600) Hat_vertical_lowpass = 600;               // Min
if (Hat_vertical_lowpass >= 1600) Hat_vertical_lowpass = 1600;             // Max

if (Trim_Aeleron <= 0) Trim_Aeleron = 0;               // Min
if (Trim_Aeleron >= 100) Trim_Aeleron = 100;             // Max
if (Trim_Elevator <= 0) Trim_Elevator = 0;               // Min
if (Trim_Elevator >= 100) Trim_Elevator = 100;             // Max
if (Trim_Rudder <= 0) Trim_Rudder = 0;               // Min
if (Trim_Rudder >= 100) Trim_Rudder = 100;             // Max


if (digitalRead(inPinD10) == 0) { // Trim_Aeleron
Trim_Aeleron += 2;}
if (digitalRead(inPinD12) == 0) {
Trim_Aeleron -= 2;}

if (digitalRead(inPinD6) == 0) { // Trim_Elevator
Trim_Elevator += 2;}
if (digitalRead(inPinD8) == 0) {
Trim_Elevator -= 2;}

if (digitalRead(inPinD3) == 0) { // Trim_Rudder
Trim_Rudder += 2;}
if (digitalRead(inPinD4) == 0) {
Trim_Rudder -= -2;}



if (digitalRead(inPinD5) == 0) { Hat_vertical_uS = 1600; }  // Hat vertical UP
if (digitalRead(inPinD7) == 0) { Hat_vertical_uS = 600; } // Hat vertical Down
if (digitalRead(inPinD5) == 1 && digitalRead(inPinD7) == 1) { Hat_vertical_uS = 1120; } // Hat vertical center


if ( Hat_vertical_lowpass < Hat_vertical_uS) { Hat_vertical_lowpass += 1; }
if ( Hat_vertical_lowpass > Hat_vertical_uS) { Hat_vertical_lowpass -= 1; }
if (Hat_vertical_lowpass > Hat_vertical_uS - 5 && Hat_vertical_lowpass < Hat_vertical_uS + 5)
{ Hat_vertical_lowpass = Hat_vertical_uS; }


if (digitalRead(inPinD9) == 0) { Hat_horizontal_uS = 1600; }  // Hat horizontal LEFT
if (digitalRead(inPinD11) == 0) { Hat_horizontal_uS = 600; } // Hat horizontal RIGHT
if (digitalRead(inPinD9) == 1 && digitalRead(inPinD11) == 1) { Hat_horizontal_uS = 1120; } // Hat horizontal center


if ( Hat_horizontal_lowpass < Hat_horizontal_uS) { Hat_horizontal_lowpass += 1; }
if ( Hat_horizontal_lowpass > Hat_horizontal_uS) { Hat_horizontal_lowpass -= 1; }
if (Hat_horizontal_lowpass > Hat_horizontal_uS - 5 && Hat_horizontal_lowpass < Hat_horizontal_uS + 5)
{ Hat_horizontal_lowpass = Hat_horizontal_uS; }

/*

Serial.print(Throttle_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Aeleron_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Elevator_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Rudder_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Hat_vertical_lowpass + Fixed_uS);
Serial.print("\t");
Serial.print(Hat_horizontal_lowpass + Fixed_uS);
Serial.print("\t");
Serial.println(Flap_uS + Fixed_uS);
*/

}
« Viimeksi muokattu: 20 Joulukuu, 2011, 15:43:16 kirjoittanut ChiKung »
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #10 : 05 Helmikuu, 2012, 12:16:21 »
Tuli askarreltua hieman lisää. Lisäsin helpomman tavan kalibrointiin ja expon. Joystickin kanssa ihan hyvä lisä tuo expo, meinaan keskitys ei ole ihan samaa tasoa lötköllä tikulla kuin radiossa.
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa jesi

  • Seniori torppari
  • *****
Vs: Joystick radioon?
« Vastaus #11 : 05 Helmikuu, 2012, 12:38:28 »
eiks hk myy joitan ilotikkua?
/ Jere Siirilä
DJI Spark | Eachine QX95 & FrSky Taranis | Cheerson CX-Stars

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #12 : 05 Helmikuu, 2012, 12:47:26 »
Taitaa myydä. Mutta kun itse tekee, saa sellaisen kuin tulee. ;D

En tarvitse erillistä radiota, kun kaikki samassa paketissa. Samoten kaikki tarvittavat tunaukset saa itse tehtyä, esim. tuo kameratelineen kääntely ja hidastus, laippojen hidastukset jne.


Tällä hetkellä sekava koodi näyttää tuolta:
Koodia: [Valitse]
/*Analogue Inputs pins:

 Pin 0 = Elevator potentiometer  --> PPM Ch.2
 Pin 1 = Aeleron potentiometer   --> PPM Ch.1
 Pin 2 = Rudder potentiometer    --> PPM Ch.4
 Pin 3 = Throttle potentiometer  --> PPM Ch.3
 Pin 4 = Aux potentiometer       --> PPM Ch.6
 Pin 5 =

Digital Input pins:
 Pin 2 =
 Pin 3 = Trim right
 Pin 4 = Trim left
 Pin 5 = Hat up
 Pin 6 = Trigger
 Pin 7 = Hat down
 Pin 8 = Thumb Middle
 Pin 9 = Hat left
 Pin 10 = Thumb Right
 Pin 11 = Hat right
 Pin 12 = Thumb Left
 Pin 13 =

PPM Spektrum:

1    Throttle
2    Ailerons
3    Vertical stabilizer
4    Rudder
5    Aux2 or Gear
6    Aux2 or Gear
7    Usually a mix


*/



int AI_Pin_AEL = 4;    // Ana In - Aeleron potentiometer (Ana In Ch.0 playing up?)
int AI_Pin_ELE = 1;    // Ana In - Elevator potentiometer
int AI_Pin_THR = 3;    // Ana In - Throttle potentiometer
int AI_Pin_RUD = 2;    // Ana In - Rudder potentiometer
int AI_Pin_FLAP = 5;    // Ana In - three state FLAP input with voltage divider


int AI_Raw_AEL;        // Ana In raw var - 0->1023
int AI_Raw_ELE;        // Ana In raw var - 0->1023
int AI_Raw_THR;        // Ana In raw var - 0->1023
int AI_Raw_RUD;        // Ana In raw var - 0->1023
int AI_Raw_FLAP;        // Ana In raw var - 0->1023


int AI_AEL;           // Ana In var - 0->1023 compensated
int AI_ELE;           // Ana In var - 0->1023 compensated
int AI_THR;           // Ana In var - 0->1023 compensated
int AI_RUD;           // Ana In var - 0->1023 compensated
int AI_FLAP;           // Ana In var - 0->1023 compensated


int Aeleron_uS = 1200;     // Ana In Ch.0 uS var - Aeleron
int Elevator_uS = 1200;    // Ana In Ch.1 uS var - Elevator
int Throttle_uS = 1200;    // Ana In Ch.2 uS var - Throttle
int Rudder_uS = 1200;      // Ana In Ch.3 uS var - Rudder
int Flap_uS = 1200;      // Ana In Ch.3 uS var - Rudder

int Expo = 50; // Expo

// Joystick calibration. raw adc values

 int AEL_Min = 190 ;
 int AEL_Center = 550 ;
 int AEL_Max = 905;

 int ELE_Min = 237 ;
 int ELE_Center = 600 ;
 int ELE_Max = 907;

 int RUD_Min = 210 ;
 int RUD_Center = 525 ;
 int RUD_Max = 890;

 int THR_Min = 180 ;
 int THR_Max = 850 ;


int Hat_horizontal_uS = 1200;
int Hat_vertical_uS = 1200;
int Hat_horizontal_RAW = 1200;
int Hat_vertical_RAW = 1200;


int Trim_Aeleron = 0; // Thumb left/right
int Trim_Elevator = 0; // trigger / center
int Trim_Rudder = 0; // left / right



int Fixed_uS = 300;       // PPM frame fixed LOW phase
// int pulseMin = 700;       // pulse minimum width minus start in uS
// int pulseMax = 1700;      // pulse maximum width in uS

int outPinPPM = 2;        // digital pin 10
int inPinD3 = 3;          // Trim right
int inPinD4 = 4;          // Trim left
int inPinD5 = 5;          // Hat up
int inPinD6 = 6;          // Trigger
int inPinD7 = 7;          // Hat down
int inPinD8 = 8;          // Thumb middle
int inPinD9 = 9;          // Hat left
int inPinD10 = 10;        // Thumb right
int inPinD11 = 11;        // Hat right
int inPinD12 = 12;        // Thumb left
int outPinTEST = 13;      // digital pin 8


ISR(TIMER1_COMPA_vect) {
ppmoutput(); // Jump to ppmoutput subroutine
}

void setup() {

// Serial.begin(9600) ; // Test

pinMode(outPinPPM, OUTPUT);   // sets the digital pin as output

pinMode(inPinD3, INPUT);      // sets the digital pin as input
digitalWrite(inPinD3, HIGH);  // turn on pull-up resistor

pinMode(inPinD4, INPUT);      // sets the digital pin as input
digitalWrite(inPinD4, HIGH);  // turn on pull-up resistor

pinMode(inPinD5, INPUT);      // sets the digital pin as input
digitalWrite(inPinD5, HIGH);  // turn on pull-up resistor

pinMode(inPinD6, INPUT);      // sets the digital pin as input
digitalWrite(inPinD6, HIGH);  // turn on pull-up resistor

pinMode(inPinD7, INPUT);      // sets the digital pin as input
digitalWrite(inPinD7, HIGH);  // turn on pull-up resistor

pinMode(inPinD8, INPUT);      // sets the digital pin as input
digitalWrite(inPinD8, HIGH);  // turn on pull-up resistor

pinMode(inPinD9, INPUT);      // sets the digital pin as input
digitalWrite(inPinD9, HIGH);  // turn on pull-up resistor

pinMode(inPinD10, INPUT);      // sets the digital pin as input
digitalWrite(inPinD10, HIGH);  // turn on pull-up resistor

pinMode(inPinD11, INPUT);     // sets the digital pin as input
digitalWrite(inPinD11, HIGH); // turn on pull-up resistor

pinMode(inPinD12, INPUT);      // sets the digital pin as input
digitalWrite(inPinD12, HIGH);  // turn on pull-up resistor


// Setup timer
TCCR1A = B00110001; // Compare register B used in mode '3'
TCCR1B = B00010010; // WGM13 and CS11 set to 1
TCCR1C = B00000000; // All set to 0
TIMSK1 = B00000010; // Interrupt on compare B
TIFR1  = B00000010; // Interrupt on compare B
OCR1A = 22000; // 22mS PPM output refresh
OCR1B = 1000;
}


void ppmoutput() { // PPM output sub

// test pulse - used to trigger scope
// digitalWrite(outPinTEST, LOW);
// delayMicroseconds(100);    // Hold
// digitalWrite(outPinTEST, HIGH);

// Channel 1
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Throttle_uS);  // Hold for Aeleron_uS microseconds

// Channel 2
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Aeleron_uS); // Hold for Elevator_uS microseconds

// Channel 3
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Elevator_uS); // Hold for Throttle_uS microseconds

// Channel 4
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Rudder_uS);   // Hold for Rudder_uS microseconds

// Channel 5 - Hat vertical
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Hat_vertical_uS);     // Hold for hat vert microseconds

// Channel 6 - Hat horizontal
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Hat_horizontal_uS);       // Hold for hat hor microseconds

// Channel 7 - Flap
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(Flap_uS);       // Hold for flap microseconds

// Ch 8 - NA
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(1200);       // Hold

// Synchro pulse
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);    // Hold
digitalWrite(outPinPPM, HIGH);  // Start Synchro pulse


// flap rate reducer
if (AI_FLAP > Flap_uS + Fixed_uS) {Flap_uS += 5;}
if (AI_FLAP < Flap_uS + Fixed_uS) {Flap_uS -= 5;}
if (Flap_uS + Fixed_uS > AI_FLAP - 10 && Flap_uS + Fixed_uS < AI_FLAP + 10) {Flap_uS = AI_FLAP - Fixed_uS;}

if (digitalRead(inPinD10) == 0) { // Trim_Aeleron
Trim_Aeleron += 2;}
if (digitalRead(inPinD12) == 0) {
Trim_Aeleron -= 2;}

if (digitalRead(inPinD6) == 0) { // Trim_Elevator
Trim_Elevator += 2;}
if (digitalRead(inPinD8) == 0) {
Trim_Elevator -= 2;}

if (digitalRead(inPinD3) == 0) { // Trim_Rudder
Trim_Rudder += 2;}
if (digitalRead(inPinD4) == 0) {
Trim_Rudder -= -2;}


if ( Hat_vertical_RAW > (Hat_vertical_uS + Fixed_uS )) { Hat_vertical_uS += 40; }
if ( Hat_vertical_RAW < (Hat_vertical_uS + Fixed_uS )) { Hat_vertical_uS -= 40; }
if (Hat_vertical_RAW > (Hat_vertical_uS + Fixed_uS - 60 ) && Hat_vertical_RAW < (Hat_vertical_uS + Fixed_uS + 60 )) { Hat_vertical_uS = Hat_vertical_RAW - Fixed_uS;}

if ( Hat_horizontal_RAW > (Hat_horizontal_uS + Fixed_uS )) { Hat_horizontal_uS += 40; }
if ( Hat_horizontal_RAW < (Hat_horizontal_uS + Fixed_uS )) { Hat_horizontal_uS -= 40; }
if (Hat_horizontal_RAW > (Hat_horizontal_uS + Fixed_uS -60 ) &&
Hat_horizontal_RAW < (Hat_horizontal_uS + Fixed_uS + 60 ))
{ Hat_horizontal_uS = Hat_horizontal_RAW - Fixed_uS;}


}


void loop() { // Main loop

// Read analogue ports
AI_Raw_AEL = analogRead(AI_Pin_AEL);
AI_Raw_ELE = analogRead(AI_Pin_ELE);
AI_Raw_THR = analogRead(AI_Pin_THR);
AI_Raw_RUD = analogRead(AI_Pin_RUD);
AI_Raw_FLAP = analogRead(AI_Pin_FLAP);

// Joystick calibration

// Constrain raw inputs:

if (AI_Raw_AEL >= AEL_Max) AI_Raw_AEL = AEL_Max; // Max
if (AI_Raw_AEL <= AEL_Min) AI_Raw_AEL = AEL_Min;   // Min

if (AI_Raw_ELE >= ELE_Max) AI_Raw_ELE = ELE_Max; // Max
if (AI_Raw_ELE <= ELE_Min) AI_Raw_ELE = ELE_Min;   // Min

if (AI_Raw_THR >= THR_Max) AI_Raw_THR = THR_Max; // Max
if (AI_Raw_THR <= THR_Min) AI_Raw_THR = THR_Min;   // Min

if (AI_Raw_RUD >= RUD_Max) AI_Raw_RUD = RUD_Max; // Max
if (AI_Raw_RUD <= RUD_Min) AI_Raw_RUD = RUD_Min;   // Min

// Calibrate / map inputs and add collective Expo

// AEL

// =-(B10^2*$C$7)/50000+B10*(100-$C$7)/100

if (AI_Raw_AEL < AEL_Center ){
AI_AEL = map(AI_Raw_AEL, AEL_Min, AEL_Center, 500, 0) ; // min
AI_AEL = (( pow(AI_AEL, 2) * Expo)/(50000) + ( AI_AEL * (100 - Expo)/100) ) ; // Expo
}
if (AI_Raw_AEL >= AEL_Center ){
AI_AEL = map(AI_Raw_AEL, AEL_Center, AEL_Max, 0, -500); // max
AI_AEL = (-(pow(AI_AEL, 2) * Expo)/(50000) + ( AI_AEL * (100 - Expo))/100 ) ; // Expo
}

// ELE

if (AI_Raw_ELE < ELE_Center ){
AI_ELE = map(AI_Raw_ELE, ELE_Min, ELE_Center, 500, 0) ; // min
AI_ELE = (pow(AI_ELE, 2) * Expo)/(50000) + ( AI_ELE * (100 - Expo)/100) ; // Expo
}
if (AI_Raw_ELE >= ELE_Center ){
AI_ELE = map(AI_Raw_ELE, ELE_Center, ELE_Max, 0, -500); // max
AI_ELE = (-pow(AI_ELE, 2) * Expo)/(50000) + ( AI_ELE * (100 - Expo))/(100) ; // Expo
}

// RUD

if (AI_Raw_RUD < RUD_Center ){
AI_RUD = map(AI_Raw_RUD, RUD_Min, RUD_Center, 500, 0) ; // min
AI_RUD = (pow(AI_RUD, 2) * Expo)/(50000) + ( AI_RUD * (100 - Expo)/100) ; // Expo
}
if (AI_Raw_RUD >= RUD_Center ){
AI_RUD = map(AI_Raw_RUD, RUD_Center, RUD_Max, 0, -500); // max
AI_RUD = (- pow(AI_RUD, 2) * Expo)/(50000) + ( AI_RUD * (100 - Expo))/(100) ; // Expo
}

// THR

AI_THR = map(AI_Raw_THR, THR_Min, THR_Max, 500, -500);

// Map flaps:
if (AI_Raw_FLAP <= 200){ AI_FLAP = 1500;}     // Min
if (AI_Raw_FLAP >= 800){ AI_FLAP = 1000;}     // Max
if (AI_Raw_FLAP > 200 && AI_Raw_FLAP < 800){ AI_FLAP = 1250;}


// Map analogue inputs to PPM rates for each of the channels

Aeleron_uS = (AI_AEL) + Trim_Aeleron + 1500 - Fixed_uS;
Elevator_uS = (AI_ELE) + Trim_Elevator + 1500 - Fixed_uS;
Throttle_uS = (AI_THR) + 1500 - Fixed_uS;
Rudder_uS = (AI_RUD) + Trim_Rudder + 1500 - Fixed_uS;

if (Aeleron_uS <= 1000 - Fixed_uS) Aeleron_uS = 1000 - Fixed_uS;     // Min
if (Aeleron_uS >= 2000 - Fixed_uS) Aeleron_uS = 2000 - Fixed_uS;       // Max

if (Elevator_uS <= 1000 - Fixed_uS) Elevator_uS = 1000 - Fixed_uS;   // Min
if (Elevator_uS >= 2000 - Fixed_uS) Elevator_uS = 2000 - Fixed_uS;     // Max

if (Throttle_uS <= 1000 - Fixed_uS) Throttle_uS = 1000 - Fixed_uS;   // Min
if (Throttle_uS >= 2000 - Fixed_uS) Throttle_uS = 2000 - Fixed_uS; // Max

if (Rudder_uS <= 1000 - Fixed_uS) Rudder_uS = 1000 - Fixed_uS;       // Min
if (Rudder_uS >= 2000 - Fixed_uS) Rudder_uS = 2000 - Fixed_uS;     // Max

if (Flap_uS <= 1000 - Fixed_uS) Flap_uS = 1000 - Fixed_uS;       // Min
if (Flap_uS >= 1500 - Fixed_uS) Flap_uS = 1500 - Fixed_uS;     // Max



if (Hat_horizontal_uS <= 900 - Fixed_uS) Hat_horizontal_uS = 900 - Fixed_uS;
if (Hat_horizontal_uS >= 2100 - Fixed_uS) Hat_horizontal_uS = 2100 - Fixed_uS;
int lowpass = Hat_horizontal_uS;
lowpass = lowpass - 1500 + Fixed_uS;
lowpass = abs(lowpass)/4 + 1500 - Fixed_uS;

if (Hat_vertical_uS >= lowpass + 300 ){ Hat_vertical_uS = lowpass + 300; }      // Min
if (Hat_vertical_uS <= 1000 - Fixed_uS) Hat_vertical_uS = 1000 - Fixed_uS;             // Max

if (Trim_Aeleron <= -100) Trim_Aeleron = -100;               // Min
if (Trim_Aeleron >= 100) Trim_Aeleron = 100;             // Max
if (Trim_Elevator <= -100) Trim_Elevator = -100;               // Min
if (Trim_Elevator >= 100) Trim_Elevator = 100;             // Max
if (Trim_Rudder <= -100) Trim_Rudder = -100;               // Min
if (Trim_Rudder >= 100) Trim_Rudder = 100;             // Max


if (digitalRead(inPinD5) == 0) { Hat_vertical_RAW = 2000; }  // Hat vertical UP
if (digitalRead(inPinD7) == 0) { Hat_vertical_RAW = 1000; } // Hat vertical Down
if (digitalRead(inPinD5) == 1 && digitalRead(inPinD7) == 1) {Hat_vertical_RAW = 1500; } // Hat vertical center


if (digitalRead(inPinD9) == 0) { Hat_horizontal_RAW = 2100; }  // Hat horizontal LEFT
if (digitalRead(inPinD11) == 0) { Hat_horizontal_RAW = 900; } // Hat horizontal RIGHT
if (digitalRead(inPinD9) == 1 && digitalRead(inPinD11) == 1) {Hat_horizontal_RAW = 1500; } // Hat horizontal center

/*
Serial.print(AI_Raw_THR);
Serial.print("\t");
Serial.print(AI_Raw_AEL);
Serial.print("\t");
Serial.print(AI_Raw_ELE);
Serial.print("\t");
Serial.println(AI_Raw_RUD);
*/

/*

Serial.print(AI_THR);
Serial.print("\t");
Serial.print(AI_AEL);
Serial.print("\t");
Serial.print(AI_ELE);
Serial.print("\t");
Serial.println(AI_RUD);

*/



// Serial.print(lowpass);
// Serial.print("\t");

/*
Serial.print(Throttle_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Aeleron_uS + Fixed_uS);
Serial.print("\t");

Serial.print(Elevator_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Rudder_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Hat_vertical_uS + Fixed_uS);
Serial.print("\t");
Serial.print(Hat_horizontal_uS + Fixed_uS);
Serial.print("\t");
Serial.println(Flap_uS + Fixed_uS);
*/

}
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #13 : 21 Helmikuu, 2012, 21:48:39 »
Mun näkemys pulpettiradiosta: Kansakoulun pulpetti -radio.
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

Poissa zxiicci

  • TLR-Insraktori
  • Seniori torppari
  • *****
  • Lajin helppous viehättää!
Vs: Joystick radioon?
« Vastaus #14 : 21 Helmikuu, 2012, 23:13:34 »
No jo on mylly! Tossa on jo asennetta!  8)

Poissa ChiKung

  • Pro torppari
  • ****
Vs: Joystick radioon?
« Vastaus #15 : 22 Helmikuu, 2012, 08:45:53 »
Pitäähän sitä pleikkari olla.

Joystickin alla olevassa rasiassa on powerit (5 ja 12 V), häiriönsuodot ja diversiteettikytkin. Tuo pieni näyttö on eBaysta noin euron maksanut paneeliasennettava jännitemittari, eli ei arduinoon liittyvä.

Painopiste on hieman liian edessä, niin henkselit painaa niskaa pidemmän päälle. Pitänee fiksata seuraavaan versioon. Näppärä tosin noinkin ja voi pitää kätevästi vaikka sylissä jos haluaa istua. Vielä vähän säätöä, kun toisessa vastarissa olikin RSSI väärin päin. Samoten 12 voltin poweri tahtoo lämmetä kun kytkee kaikki sen perään. Laitan toisen vastaavan syöttämään pelkkää näyttöä niin jakaantuu kuorma.
T-Rex 450 SE Superframe, CX450 V2 AE, DX7

 

Vastaavat aiheet

  Aihe / Aloittaja Vastauksia Uusin viesti
6 Vastauksia
2824 Lukukerrat
Uusin viesti 29 Elokuu, 2008, 22:46:14
kirjoittanut kaardian
4 Vastauksia
2423 Lukukerrat
Uusin viesti 28 Maaliskuu, 2010, 15:46:37
kirjoittanut jimbo82
11 Vastauksia
5625 Lukukerrat
Uusin viesti 28 Joulukuu, 2010, 17:11:54
kirjoittanut Tohtori R
0 Vastauksia
1766 Lukukerrat
Uusin viesti 22 Maaliskuu, 2016, 14:24:32
kirjoittanut ropeli