offtopic: code help with goebish multipro

More
25 Sep 2017 16:30 - 25 Sep 2017 16:32 #64663 by Wene001
Hy together!

I have two Walkera 2401 Transmitters lying around , that i want donate to some childs in the neighborhood.
The gimbals are really good.
I have ordered a bunch of NRF24 modules and want to install it beside an arduino in the transmitters, using goebishs multipro code.
https://github.com/goebish/nrf24_multipro

i think this should work.

The problem is, that the TXs have a 8 channel PPM signal, but only the first 4 are used for the Gimbals.
No way to use a switch via ppm.

Unfortunately code is way to complex for me.

Anyone interested to help me with changing the code, so we can use some switches directly connected to the arduino?

In the meantime i will build it as 4 Channel version...

Thanks
Attachments:
Last edit: 25 Sep 2017 16:32 by Wene001.

Please Log in or Create an account to join the conversation.

More
27 Sep 2017 14:26 #64692 by Wene001
Replied by Wene001 on topic offtopic: code help with goebish multipro
Preparing the transmitter i realized that my PPM Signal is inverted.
Can anyone tell me if the goebish multipro code acceppts negative PPM Signal?

Please Log in or Create an account to join the conversation.

More
13 Oct 2017 11:47 - 13 Oct 2017 11:53 #65025 by goebish
Replied by goebish on topic offtopic: code help with goebish multipro
Yes it's compatible with both positive and negative PPM signals.

For your switches, I'll take an example to map a 2 pos switch to channel 6 (usually mapped to flip function):
- connect one end of the switch to gnd
- connect the other end to a free IO pin of the Arduino, eg D8
- open nrf24_multipro.ino
- in setup() function, add this to init the pin as a pulled up input:
pinMode(8, INPUT_PULLUP);
- add this at the end of the update_ppm() function to read the input and map it to channel 6 (AUX2):
ppm[AUX2] = digitalRead(8) == HIGH ? 2000 : 1000;
(use LOW instead of HIGH if you want to reverse the channel)
Last edit: 13 Oct 2017 11:53 by goebish.

Please Log in or Create an account to join the conversation.

More
14 Oct 2017 18:06 #65060 by Wene001
Replied by Wene001 on topic offtopic: code help with goebish multipro
Thanks...still waiting for my NRF Modules

Please Log in or Create an account to join the conversation.

More
04 Nov 2017 15:44 #65502 by Wene001
Replied by Wene001 on topic offtopic: code help with goebish multipro
Thanks for the tips.
First one is ready.

I`ve implemented two switches for Ch5 Ch6, and two momentary switches(one for Bind/reset via AUX8)

I coded some switchable sort of expo to handle silverized Acro Quads with high rates.

If (compensated) telemetry voltage (Siverized Bayang) goes under 3.5 Volts the beeper gives Alarm.

It was necessary to code subtrim to get the Sticks center to perfect 1500us.

In the end a perfekt Transmitter for most of the China Toys.
Attachments:

Please Log in or Create an account to join the conversation.

More
04 Nov 2017 15:56 #65503 by goebish
Replied by goebish on topic offtopic: code help with goebish multipro
Good job :)

Please Log in or Create an account to join the conversation.

More
04 Nov 2017 16:04 - 04 Nov 2017 16:26 #65504 by Wene001
Replied by Wene001 on topic offtopic: code help with goebish multipro
Thanks Master :-)
This was my second Arduino Projekt after an Openxsensor for Frsky telemetrie.
i begin to love this little Arduinos :-)
i think i a have to learn coding.....

If anyone is interested in my poor code modifications....
/*
 ##########################################
 #####   MultiProtocol nRF24L01 Tx   ######
 ##########################################
 #        by goebish on rcgroups          #
 #                                        #
 #   Parts of this project are derived    #
 #     from existing work, thanks to:     #
 #                                        #
 #   - PhracturedBlue for DeviationTX     #
 #   - victzh for XN297 emulation layer   #
 #   - Hasi for Arduino PPM decoder       #
 #   - hexfet, midelic, closedsink ...    #
 ##########################################


 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License.
 If not, see <http://www.gnu.org/licenses/>.
 */

#include <util/atomic.h>
#include <EEPROM.h>
#include "iface_nrf24l01.h"


// ############ Wiring ################
#define PPM_pin   2  // PPM in
//SPI Comm.pins with nRF24L01
#define MOSI_pin  3  // MOSI - D3
#define SCK_pin   4  // SCK  - D4
#define CE_pin    5  // CE   - D5
#define MISO_pin  A0 // MISO - A0
#define CS_pin    A1 // CS   - A1

#define ledPin    13 // LED  - D13

// SPI outputs
#define MOSI_on PORTD |= _BV(3)  // PD3
#define MOSI_off PORTD &= ~_BV(3)// PD3
#define SCK_on PORTD |= _BV(4)   // PD4
#define SCK_off PORTD &= ~_BV(4) // PD4
#define CE_on PORTD |= _BV(5)    // PD5
#define CE_off PORTD &= ~_BV(5)  // PD5
#define CS_on PORTC |= _BV(1)    // PC1
#define CS_off PORTC &= ~_BV(1)  // PC1
// SPI input
#define  MISO_on (PINC & _BV(0)) // PC0

#define RF_POWER TX_POWER_80mW 

// tune ppm input for "special" transmitters
#define SPEKTRUM // 1100-1900, Elevator reversed

// PPM stream settings
#define CHANNELS 12 // number of channels in ppm stream, 12 ideally
enum chan_order{
    ELEVATOR,
    AILERON,
    THROTTLE,
    RUDDER,
    AUX1,  // (CH5)  led light, or 3 pos. rate on CX-10, H7, or inverted flight on H101
    AUX2,  // (CH6)  flip control
    AUX3,  // (CH7)  still camera (snapshot)
    AUX4,  // (CH8)  video camera
    AUX5,  // (CH9)  headless
    AUX6,  // (CH10) calibrate Y (V2x2), pitch trim (H7), RTH (Bayang, H20), 360deg flip mode (H8-3D, H22)
    AUX7,  // (CH11) calibrate X (V2x2), roll trim (H7)
    AUX8,  // (CH12) Reset / Rebind
};

#define PPM_MIN 1000
#define PPM_SAFE_THROTTLE 1050 
#define PPM_MID 1500
#define PPM_MAX 2000
#define PPM_MIN_COMMAND 1300
#define PPM_MAX_COMMAND 1700
#define GET_FLAG(ch, mask) (ppm[ch] > PPM_MAX_COMMAND ? mask : 0)
#define GET_FLAG_INV(ch, mask) (ppm[ch] < PPM_MIN_COMMAND ? mask : 0)

// supported protocols
enum {
    PROTO_V2X2 = 0,     // WLToys V2x2, JXD JD38x, JD39x, JJRC H6C, Yizhan Tarantula X6 ...
    PROTO_CG023,        // EAchine CG023, CG032, 3D X4
    PROTO_CX10_BLUE,    // Cheerson CX-10 blue board, newer red board, CX-10A, CX-10C, Floureon FX-10, CX-Stars (todo: add DM007 variant)
    PROTO_CX10_GREEN,   // Cheerson CX-10 green board
    PROTO_H7,           // EAchine H7, MoonTop M99xx
    PROTO_BAYANG,       // EAchine H8(C) mini, H10, BayangToys X6, X7, X9, JJRC JJ850, Floureon H101
    PROTO_SYMAX5C1,     // Syma X5C-1 (not older X5C), X11, X11C, X12
    PROTO_YD829,        // YD-829, YD-829C, YD-822 ...
    PROTO_H8_3D,        // EAchine H8 mini 3D, JJRC H20, H22
    PROTO_MJX,          // MJX X600 (can be changed to Weilihua WLH08, X800 or H26D)
    PROTO_SYMAXOLD,     // Syma X5C, X2
    PROTO_HISKY,        // HiSky RXs, HFP80, HCP80/100, FBL70/80/90/100, FF120, HMX120, WLToys v933/944/955 ...
    PROTO_KN,           // KN (WLToys variant) V930/931/939/966/977/988
    PROTO_YD717,        // Cheerson CX-10 red (older version)/CX11/CX205/CX30, JXD389/390/391/393, SH6057/6043/6044/6046/6047, FY326Q7, WLToys v252 Pro/v343, XinXun X28/X30/X33/X39/X40
    PROTO_FQ777124,     // FQ777-124 pocket drone
    PROTO_E010,         // EAchine E010, NiHui NH-010, JJRC H36 mini
    PROTO_BAYANG_SILVERWARE, // Bayang for Silverware with frsky telemetry
    PROTO_END
};

// EEPROM locationss
enum{
    ee_PROTOCOL_ID = 0,
    ee_TXID0,
    ee_TXID1,
    ee_TXID2,
    ee_TXID3
};

struct {
    uint16_t volt1;
    uint16_t rssi;
    uint8_t updated;
    uint32_t lastUpdate;
} telemetry_data;

uint8_t transmitterID[4];
uint8_t current_protocol;
static volatile bool ppm_ok = false;
uint8_t packet[32];
static bool reset=true;
volatile uint16_t Servo_data[12];
static uint16_t ppm[12] = {PPM_MIN,PPM_MIN,PPM_MIN,PPM_MIN,PPM_MID,PPM_MID,
                           PPM_MID,PPM_MID,PPM_MID,PPM_MID,PPM_MID,PPM_MID,};


const int buzzer = 9; //buzzer to arduino pin 9
unsigned long previousMillis = 0;        // will store last time BEEPER was updated
const long interval = 2000;           // interval at which to beep (milliseconds)
const long beep = 200;  // Beepdauer
const long freq = 1000; // Tonhöhe - Frequenz

void setup()
{
//    Serial.begin(9600);      // open the serial port at 9600 bps:
    randomSeed((analogRead(A4) & 0x1F) | (analogRead(A5) << 5));
    pinMode(6, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    pinMode(8, INPUT_PULLUP);
    pinMode(10, INPUT_PULLUP);
    pinMode(buzzer, OUTPUT);        //Buzzer
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW); //start LED off
    pinMode(PPM_pin, INPUT);
    pinMode(MOSI_pin, OUTPUT);
    pinMode(SCK_pin, OUTPUT);
    pinMode(CS_pin, OUTPUT);
    pinMode(CE_pin, OUTPUT);
    pinMode(MISO_pin, INPUT);
    frskyInit();
    
    // PPM ISR setup
    attachInterrupt(digitalPinToInterrupt(PPM_pin), ISR_ppm, CHANGE);
    TCCR1A = 0;  //reset timer1
    TCCR1B = 0;
    TCCR1B |= (1 << CS11);  //set timer1 to increment every 1 us @ 8MHz, 0.5 us @16MHz

    set_txid(false);
}

void loop()
{
    uint32_t timeout=0;
    // reset / rebind
    if(reset || ppm[AUX8] > PPM_MAX_COMMAND) {
        reset = false;
        telemetry_data.volt1 = 400;
        selectProtocol();
        NRF24L01_Reset();
        NRF24L01_Initialize();
        init_protocol();
    }
    if(telemetry_data.volt1 < 345) {
        Alarm();
    }
    
    telemetry_data.updated = 0;
    // process protocol
    switch(current_protocol) {
        case PROTO_CG023:
        case PROTO_YD829:
            timeout = process_CG023();
            break;
        case PROTO_V2X2:
            timeout = process_V2x2();
            break;
        case PROTO_CX10_GREEN:
        case PROTO_CX10_BLUE:
            timeout = process_CX10();
            break;
        case PROTO_H7:
            timeout = process_H7();
            break;
        case PROTO_BAYANG:
        case PROTO_BAYANG_SILVERWARE:
            timeout = process_Bayang();
            break;
        case PROTO_SYMAX5C1:
        case PROTO_SYMAXOLD:
            timeout = process_SymaX();
            break;
        case PROTO_H8_3D:
            timeout = process_H8_3D();
            break;
        case PROTO_MJX:
        case PROTO_E010:
            timeout = process_MJX();
            break;
        case PROTO_HISKY:
            timeout = process_HiSky();
            break;
        case PROTO_KN:
            timeout = process_KN();
            break;
        case PROTO_YD717:
            timeout = process_YD717();
            break;
        case PROTO_FQ777124:
            timeout = process_FQ777124();
            break;
    }
    // updates ppm values out of ISR
    update_ppm();
    
    while(micros() < timeout) {
        if(telemetry_data.updated) {
            frskyUpdate();
        }            
    }
    telemetry_data.updated = 0;
}

void set_txid(bool renew)
{
    uint8_t i;
    for(i=0; i<4; i++)
        transmitterID[i] = EEPROM.read(ee_TXID0+i);
    if(renew || (transmitterID[0]==0xFF && transmitterID[1]==0x0FF)) {
        for(i=0; i<4; i++) {
            transmitterID[i] = random() & 0xFF;
            EEPROM.update(ee_TXID0+i, transmitterID[i]); 
        }            
    }
}

void selectProtocol()
{
    // wait for multiple complete ppm frames
    ppm_ok = false;
    uint8_t count = 10;
    while(count) {
        while(!ppm_ok) {} // wait
        update_ppm();
        if(ppm[AUX8] < PPM_MAX_COMMAND) // reset chan released
            count--;
        ppm_ok = false;
    }
    
    // startup stick commands (protocol selection / renew transmitter ID)
    
    if(ppm[RUDDER] < PPM_MIN_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND) // rudder left + aileron left
        current_protocol = PROTO_BAYANG_SILVERWARE; // Bayang protocol for Silverware with frsky telemetry
        
    else if(ppm[RUDDER] < PPM_MIN_COMMAND)   // Rudder left
        set_txid(true);                      // Renew Transmitter ID
    
    // Rudder right + Aileron right + Elevator down
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] > PPM_MAX_COMMAND && ppm[ELEVATOR] < PPM_MIN_COMMAND)
        current_protocol = PROTO_E010; // EAchine E010, NiHui NH-010, JJRC H36 mini
    
    // Rudder right + Aileron right + Elevator up
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] > PPM_MAX_COMMAND && ppm[ELEVATOR] > PPM_MAX_COMMAND)
        current_protocol = PROTO_FQ777124; // FQ-777-124

    // Rudder right + Aileron left + Elevator up
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND && ppm[ELEVATOR] > PPM_MAX_COMMAND)
        current_protocol = PROTO_YD717; // Cheerson CX-10 red (older version)/CX11/CX205/CX30, JXD389/390/391/393, SH6057/6043/6044/6046/6047, FY326Q7, WLToys v252 Pro/v343, XinXun X28/X30/X33/X39/X40
    
    // Rudder right + Aileron left + Elevator down
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND && ppm[ELEVATOR] < PPM_MIN_COMMAND)
        current_protocol = PROTO_KN; // KN (WLToys variant) V930/931/939/966/977/988
    
    // Rudder right + Elevator down
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[ELEVATOR] < PPM_MIN_COMMAND)
        current_protocol = PROTO_HISKY; // HiSky RXs, HFP80, HCP80/100, FBL70/80/90/100, FF120, HMX120, WLToys v933/944/955 ...
    
    // Rudder right + Elevator up
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[ELEVATOR] > PPM_MAX_COMMAND)
        current_protocol = PROTO_SYMAXOLD; // Syma X5C, X2 ...
    
    // Rudder right + Aileron right
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] > PPM_MAX_COMMAND)
        current_protocol = PROTO_MJX; // MJX X600, other sub protocols can be set in code
    
    // Rudder right + Aileron left
    else if(ppm[RUDDER] > PPM_MAX_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND)
        current_protocol = PROTO_H8_3D; // H8 mini 3D, H20 ...
    
    // Elevator down + Aileron right
    else if(ppm[ELEVATOR] < PPM_MIN_COMMAND && ppm[AILERON] > PPM_MAX_COMMAND)
        current_protocol = PROTO_YD829; // YD-829, YD-829C, YD-822 ...
    
    // Elevator down + Aileron left
    else if(ppm[ELEVATOR] < PPM_MIN_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND)
        current_protocol = PROTO_SYMAX5C1; // Syma X5C-1, X11, X11C, X12
    
    // Elevator up + Aileron right
    else if(ppm[ELEVATOR] > PPM_MAX_COMMAND && ppm[AILERON] > PPM_MAX_COMMAND)
        current_protocol = PROTO_BAYANG;    // EAchine H8(C) mini, BayangToys X6/X7/X9, JJRC JJ850 ...
    
    // Elevator up + Aileron left
    else if(ppm[ELEVATOR] > PPM_MAX_COMMAND && ppm[AILERON] < PPM_MIN_COMMAND) 
        current_protocol = PROTO_H7;        // EAchine H7, MT99xx
    
    // Elevator up  
    else if(ppm[ELEVATOR] > PPM_MAX_COMMAND)
        current_protocol = PROTO_V2X2;       // WLToys V202/252/272, JXD 385/388, JJRC H6C ...
        
    // Elevator down
    else if(ppm[ELEVATOR] < PPM_MIN_COMMAND) 
        current_protocol = PROTO_CG023;      // EAchine CG023/CG031/3D X4, (todo :ATTOP YD-836/YD-836C) ...
    
    // Aileron right
    else if(ppm[AILERON] > PPM_MAX_COMMAND)  
        current_protocol = PROTO_CX10_BLUE;  // Cheerson CX10(blue pcb, newer red pcb)/CX10-A/CX11/CX12 ... 
    
    // Aileron left
    else if(ppm[AILERON] < PPM_MIN_COMMAND)  
        current_protocol = PROTO_CX10_GREEN;  // Cheerson CX10(green pcb)... 
    
    // read last used protocol from eeprom
    else 
        current_protocol = constrain(EEPROM.read(ee_PROTOCOL_ID),0,PROTO_END-1);      
    // update eeprom 
    EEPROM.update(ee_PROTOCOL_ID, current_protocol);
    // wait for safe throttle
    while(ppm[THROTTLE] > PPM_SAFE_THROTTLE) {
        delay(100);
        update_ppm();
    }
}

void init_protocol()
{
    switch(current_protocol) {
        case PROTO_CG023:
        case PROTO_YD829:
            CG023_init();
            CG023_bind();
            break;
        case PROTO_V2X2:
            V2x2_init();
            V2x2_bind();
            break;
        case PROTO_CX10_GREEN:
        case PROTO_CX10_BLUE:
            CX10_init();
            CX10_bind();
            break;
        case PROTO_H7:
            H7_init();
            H7_bind();
            break;
        case PROTO_BAYANG:
        case PROTO_BAYANG_SILVERWARE:
            Bayang_init();
            Bayang_bind();
            break;
        case PROTO_SYMAX5C1:
        case PROTO_SYMAXOLD:
            Symax_init();
            break;
        case PROTO_H8_3D:
            H8_3D_init();
            H8_3D_bind();
            break;
        case PROTO_MJX:
        case PROTO_E010:
            MJX_init();
            MJX_bind();
            break;
        case PROTO_HISKY:
            HiSky_init();
            break;
        case PROTO_KN:
            kn_start_tx(true); // autobind
            break;
        case PROTO_YD717:
            YD717_init();
            break;
        case PROTO_FQ777124:
            FQ777124_init();
            FQ777124_bind();
            break;
    }
}

// update ppm values out of ISR    
void update_ppm()
{
    for(uint8_t ch=0; ch<CHANNELS; ch++) {
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
            ppm[ch] = Servo_data[ch];
        }
        
    }
    ppm[ELEVATOR] = ppm[ELEVATOR]-23; //Subtrim Elevator
    ppm[AILERON] = ppm[AILERON]+38; //Subtrim Aileron
    ppm[RUDDER] = ppm[RUDDER]-10; //Subtrim Rudder

/*      
      Serial.print(" ELEVATOR "); 
      Serial.print(ppm[ELEVATOR]); 
      Serial.print(" AILERON "); 
      Serial.print(ppm[AILERON]); 
      Serial.print(" THROTTLE "); 
      Serial.print(ppm[THROTTLE]); 
      Serial.print(" RUDDER "); 
      Serial.println(ppm[RUDDER]); 
    
      Serial.print(" telemetry_data.volt1 "); 
      Serial.println(telemetry_data.volt1);  
*/
        
#ifdef SPEKTRUM
    for(uint8_t ch=0; ch<CHANNELS; ch++) {
        
        ppm[ch] = constrain(map(ppm[ch],1130,1870,PPM_MIN,PPM_MAX),PPM_MIN,PPM_MAX);
        if(digitalRead(6) == LOW) {
          if(ch == ELEVATOR || ch == AILERON || ch == RUDDER) {
            if(ppm[ch] < 1250) 
               ppm[ch] = ppm[ch]/2+ppm[ch]-500;
              
            else if(ppm[ch] > 1750) 
               ppm[ch] = ppm[ch]/2+ppm[ch]-1000;
            
            else 
               ppm[ch] = ppm[ch]/2+750;
                   }
      } 
   }
    
#endif

    ppm[AUX1] = digitalRead(6) == HIGH ? 2000 : 1000;
    ppm[AUX2] = digitalRead(8) == LOW ? 2000 : 1000;
    ppm[AUX3] = digitalRead(10) == LOW ? 2000 : 1000;
    ppm[AUX5] = digitalRead(6) == LOW ? 2000 : 1000;
    ppm[AUX8] = digitalRead(7) == LOW ? 2000 : 1000;  
}

void ISR_ppm()
{
    #if F_CPU == 16000000
        #define PPM_SCALE 1L
    #elif F_CPU == 8000000
        #define PPM_SCALE 0L
    #else
        #error // 8 or 16MHz only !
    #endif
    static unsigned int pulse;
    static unsigned long counterPPM;
    static byte chan;
    counterPPM = TCNT1;
    TCNT1 = 0;
    ppm_ok=false;
    if(counterPPM < 510 << PPM_SCALE) {  //must be a pulse if less than 510us
        pulse = counterPPM;
    }
    else if(counterPPM > 1910 << PPM_SCALE) {  //sync pulses over 1910us
        chan = 0;
    }
    else{  //servo values between 510us and 2420us will end up here
        if(chan < CHANNELS) {
            Servo_data[chan]= constrain((counterPPM + pulse) >> PPM_SCALE, PPM_MIN, PPM_MAX);
            if(chan==3)
                ppm_ok = true; // 4 first channels Ok
        }
        chan++;
    }
}

void Alarm() 
{
 
  unsigned long currentMillis = millis();

  
  if (currentMillis - previousMillis >= interval-beep) {
    tone(buzzer, freq);
  }
    
    if (currentMillis - previousMillis >= interval) {
    // save the last time you beeped
    previousMillis = currentMillis;
    noTone(buzzer);

  }
}
Last edit: 04 Nov 2017 16:26 by Wene001.

Please Log in or Create an account to join the conversation.

Time to create page: 0.099 seconds
Powered by Kunena Forum