DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

  • klaus
  • klaus's Avatar Offline Autor
  • Platinum Mitglied
  • Platinum Mitglied
  • Beiträge: 372
  • Dank erhalten: 226

klaus antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 28 März 2013 16:20 #19
Ich Versteh nur BAHNHOF :( :lol: :oops:

Jedenfalls ist es nicht schlimm, wenn ich den Widerstand nicht eingebaut habe, oder?
"Meine und Thorn's" Webseite:
[img

Modellfliegen in Südtirol
von klaus

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • dibub
  • dibub's Avatar Offline
  • Elite Mitglied
  • Elite Mitglied
  • Beiträge: 222
  • Dank erhalten: 33

dibub antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 28 März 2013 17:27 #20
Hallo Klaus,


Wenn Du die erwähnte Zeile im Code drin hast, ist der Widerstand überflüssig, sonst kann es Probleme machen. Es hängt davon ab, was Du in den Arduino geflashed hast, es gibt leider mehrere PPMtoDSM Versionen im Netz.

Sorry wegen des BAHNHOFs, ich hatte schon früher Dinge mit Ardunios und Microcontrollern realisiert, ist nicht immer einfach zu erklären, ich versuch es noch mal.

Offene Eingänge des Microcontrollers (wenn der Bind-Taster nicht gedrückt ist, und kein Widersatnd da ist) können in beide Richtungen (low oder high bzw Masse oder Vss) driften, und sind dann 'unberechenbar'.
Das wäre so, als ob dann zufällig irgendwann der Bind-Taster gedrückt wird.
Daher muss man es entweder extern mit einem Widerstand machen oder halt in der Software. Hoffe es ist etwas klarer ...

Gruß

Dirk
von dibub

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • klaus
  • klaus's Avatar Offline Autor
  • Platinum Mitglied
  • Platinum Mitglied
  • Beiträge: 372
  • Dank erhalten: 226

klaus antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 28 März 2013 17:59 #21
Hallo DIrk,

ja danke, jetzt versteh ich es in groben "Zügen" :cheer:

Ja dass es mehrere Versionen des PPMtoDSM gibt hab ich mittlerweile auch schon herasugefunden. Letzendlich hat bei mir nur die PPMtoDSM.pde (vom 13.07.2011 12:44 Uhr) zum Erfolg geführt.

Die erwähnte Zeile kommt darin nicht vor. Also sollte ich sie etnweder einfügen (WO GENAU?) oder den Widerstand einbauen, richtig?


Der derzeitige Code darin lautet wie folgt:
Code:
/* PPM to DSM v1.07 - June 2011 Sends DSM2 signal using low power MLP4DSM Spektrum TX module Based on the code by daniel_arg, modifications by AS aka c2po. 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 along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "WProgram.h" #include <avr/interrupt.h> #define DE_BUG // Change this to #define DEBUG if needed typedef enum { NULL_ST = -1, NOT_SYNCHED, ACQUIRING, READY, FAILSAFE } State_t; #define TICKS_PER_uS 1 // number of timer ticks per 1 microsecond with prescaler = 8 and CPU 8MHz #define MAX_CHANNELS 8 // maximum number of channels we can store, don't increase this above 8 #define MIN_IN_PULSE ( 750 * TICKS_PER_uS) // valid pulse must be at least 750us #define MAX_IN_PULSE (2250 * TICKS_PER_uS) // valid pulse must be less than 2250us #define SYNC_GAP_LEN (5000 * TICKS_PER_uS) // we assume a space at least 5000us is sync #define VALID_FRAMES 10 // must have this many consecutive valid frames to transition to the ready state. #define DSM2_CHANNELS 6 // Max number of DSM2 Channels transmitted #define BINDING_PIN 4 // Pin used to bind #define BINDING_LED 5 // Pin used for Binding in process LED #define PPM_OK_LED 6 // Pin used for PPM Ok signal LED #define RF_OK_PIN 7 // Pin used for RF Ok signal #define GREEN_LED 13 // Pin used for board LED #define FLASH_LED 250 // LED flash interval in ms static int Pulses[ MAX_CHANNELS + 1]; // array holding channel pulses width value in microseconds static int Failsafe[MAX_CHANNELS + 1]; // array holding channel fail safe values static byte ChannelNum; // number of channels detected so far in the frame (first channel is 1) static byte ChannelCnt; // the total number of channels detected in a complete frame static State_t State; // this will be one of the following states: Null, Not_Synched, Acquiring, Ready, Failsafe static byte stateCount; // counts the number of times this state has been repeated static byte DSM2_Header[2]; static byte DSM2_Channel[DSM2_CHANNELS*2] = {0x00,0xAA,0x05,0xFF,0x09,0xFF,0x0D,0xFF,0x13,0x54,0x14,0xAA}; static byte DSM2_Sent = 0; static byte ChanIndex[] = {1,2,3,4,5,6}; //PPM to DSM2 Channel Mapping Table static byte count; static int pulse; /* ---------- ---------- ---------- Sync ---------- ---------- ---------- */ static void processSync() { // sync pulse was detected so reset the channel to first and update the system state Pulses[0] = ICR1 / TICKS_PER_uS; // save the sync pulse duration for debugging if(State == READY) { if( ChannelNum != ChannelCnt) // if the number of channels is unstable, go into failsafe State = FAILSAFE; } else { if(State == NOT_SYNCHED) { State = ACQUIRING; // this is the first sync pulse, we need one more to fill the channel data array stateCount = 0; } else { if( State == ACQUIRING) { if(++stateCount > VALID_FRAMES) { State = READY; // this is the second sync and all channel data is ok so flag that channel data is valid ChannelCnt = ChannelNum; // save the number of channels detected } } else if( State == FAILSAFE) { if(ChannelNum == ChannelCnt) // did we get good pulses on all channels? State = READY; } } } ChannelNum = 0; // reset the channel counter } /* ---------- ---------- ---------- Interrupt ---------- ---------- ---------- */ ISR(TIMER1_OVF_vect) { if(State == READY) { State = FAILSAFE; // use fail safe values if signal lost ChannelNum = 0; // reset the channel count } } ISR(TIMER1_CAPT_vect) { // we want to measure the time to the end of the pulse TCNT1 = 0; // reset the counter if(ICR1 >= SYNC_GAP_LEN) // is the space between pulses big enough to be the SYNC processSync(); else if(ChannelNum < MAX_CHANNELS) { // check if its a valid channel pulse and save it if((ICR1 >= MIN_IN_PULSE) && (ICR1 <= MAX_IN_PULSE)) // check for valid channel data Pulses[++ChannelNum] = ICR1 / TICKS_PER_uS; // store pulse length as microseconds else if(State == READY) { State = FAILSAFE; // use fail safe values if input data invalid ChannelNum = 0; // reset the channel count } } } /* ---------- ---------- ---------- Class ---------- ---------- ---------- */ class PPM_Decode { public: PPM_Decode() { // Constructor // empty } void begin() { pinMode(8, INPUT); // Timer1 interrupt handler uses pin 8 as input, do not change it ChannelNum = 0; State = NOT_SYNCHED; TCCR1A = 0x00; // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 // PWM11=0, PWM10=0 => PWM Operation disabled // TCCR1B = (1<<ICES1) | (1<<CS11); // capture using rising edge, prescaler = 8 TCCR1B = (1<<CS11); // capture using falling edge, prescaler = 8 // 8MHz clock with prescaler 8 means TCNT1 increments every 1 uS TIMSK1 = _BV(ICIE1)|_BV (TOIE1); // enable input capture and overflow interrupts for timer 1 for(byte ch = 1; ch <= MAX_CHANNELS; ch++) { Failsafe[ch] = Pulses[ch] = 1500; // set midpoint as default values for pulses and failsafe } Failsafe[3] = Pulses[3] = 1100; // set channel 3 failsafe pulse width to min throttle } State_t getState() { return State; } byte getChannelCnt() { return ChannelCnt; } void setFailsafe(byte ch, int value) { // pulse width to use if invalid data, value of 0 uses last valid data if((ch > 0) && (ch <= MAX_CHANNELS)) Failsafe[ch] = value; } void setFailsafe() { // setFailsafe with no arguments sets failsafe for all channels to their current values if(State == READY) // useful to capture current tx settings as failsafe values for(byte ch = 1; ch <= MAX_CHANNELS; ch++) Failsafe[ch] = Pulses[ch]; } int getChannelData(uint8_t channel) { // this is the access function for channel data int result = 0; // default value if(channel <= MAX_CHANNELS) { if((State == FAILSAFE) && (Failsafe[channel] > 0 )) result = Failsafe[channel]; // return the channels failsafe value if set and State is Failsafe else if((State == READY) || (State == FAILSAFE)) { cli(); // disable interrupts result = Pulses[channel]; // return the last valid pulse width for this channel sei(); // enable interrupts } } return result; } }; PPM_Decode Receiver = PPM_Decode(); void setup() { delay(100); #ifdef DEBUG Serial.begin(115200); // print values on the screen #else Serial.begin(125000); // closest speed for DSM2 module, otherwise it won't work #endif Receiver.begin(); pinMode(BINDING_PIN, INPUT); pinMode(BINDING_LED, OUTPUT); pinMode(PPM_OK_LED, OUTPUT); pinMode(RF_OK_PIN, OUTPUT); pinMode(GREEN_LED, OUTPUT); delay(100); DSM2_Header[0] = 0x80; DSM2_Header[1] = 0; digitalWrite(BINDING_LED, HIGH); // turn on the binding LED while(digitalRead(BINDING_PIN) == LOW) { // if bind button pressed at the power up if(millis()%FLASH_LED > FLASH_LED/2) digitalWrite(BINDING_LED, HIGH); // flash binding LED else digitalWrite(BINDING_LED, LOW); sendDSM2(); delay(20); } digitalWrite(BINDING_LED,LOW); // turn off the binding LED DSM2_Header[0] = 0; count = 50; while(Receiver.getState() != READY && count-- > 0) // wait 5 sec or until PPM data is stable and ready delay(100); } void loop() { if(millis()%(FLASH_LED*4) < FLASH_LED/16) digitalWrite(GREEN_LED, HIGH); // flash the board LED - we are alive else digitalWrite(GREEN_LED, LOW); if(Receiver.getState() == READY) { // if PPM is ready if(millis()%(FLASH_LED*4) < FLASH_LED/16) digitalWrite(PPM_OK_LED, HIGH); // flash the PPM OK LED else digitalWrite(PPM_OK_LED, LOW); digitalWrite(BINDING_LED, LOW); // turn off binding LED digitalWrite(RF_OK_PIN, LOW); // turn on RF OK LED in the radio } else { digitalWrite(BINDING_LED, HIGH); // turn on binding LED digitalWrite(PPM_OK_LED, LOW); // turn off the PPM OK LED digitalWrite(RF_OK_PIN, HIGH); // turn off RF OK LED in the radio, alarm will sound } if(Receiver.getState() == READY || Receiver.getState() == FAILSAFE) { if(ChannelNum == 0 || ChannelNum == ChannelCnt) { // during sync pulse or in failsafe if(DSM2_Sent == 0) { // if DSM2 frame is not sent yet for (byte i=0; i<DSM2_CHANNELS; i++) { // get receiver data pulse = Receiver.getChannelData(ChanIndex[i]) - 1000; pulse = constrain(pulse, 0, 0x3FF); DSM2_Channel[i*2] = (byte)(i<<2) | highByte(pulse); DSM2_Channel[i*2+1] = lowByte(pulse); } sendDSM2(); // send frame DSM2_Sent = 1; // frame sent flag } else { if(Receiver.getState() == FAILSAFE) { delay(20); // in case of failsafe DSM2_Sent = 0; // reset flag after delay } } } else { if(ChannelNum == 1) // after first channel is received DSM2_Sent = 0; // reset flag for the next frame } } } #ifndef DEBUG void sendDSM2() { Serial.write(DSM2_Header, 2); Serial.write(DSM2_Channel, DSM2_CHANNELS*2); } #else void sendDSM2() { Serial.print(DSM2_Header[0], HEX); Serial.print(" "); Serial.print(DSM2_Header[1], HEX); Serial.print(" "); for(byte i=0; i < DSM2_CHANNELS; i++) { // print channels 1 to 6 in Hex and Dec serialPrintHex(DSM2_Channel[i*2]); Serial.print(" "); serialPrintHex(DSM2_Channel[i*2+1]); Serial.print(" ("); Serial.print((DSM2_Channel[i*2]&0x03)<<8 | DSM2_Channel[i*2+1], DEC); Serial.print(") "); } Serial.print(Receiver.getChannelData(7), DEC); // channel 7 Serial.print(" "); Serial.print(Receiver.getChannelData(8), DEC); // channel 8 Serial.print(" "); Serial.print(Receiver.getChannelData(0), DEC); // sync pulse length Serial.print(" "); Serial.println(" "); delay(200); } void serialPrintHex(byte b) { byte b1 = (b >> 4) & 0x0F; byte b2 = (b & 0x0F); char c1 = (b1 < 10) ? ('0' + b1) : 'A' + b1 - 10; char c2 = (b2 < 10) ? ('0' + b2) : 'A' + b2 - 10; Serial.print(c1); Serial.print(c2); } #endif


Gruß klaus
"Meine und Thorn's" Webseite:
[img

Modellfliegen in Südtirol
von klaus

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • dibub
  • dibub's Avatar Offline
  • Elite Mitglied
  • Elite Mitglied
  • Beiträge: 222
  • Dank erhalten: 33

dibub antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 28 März 2013 18:46 #22
Hallo Klaus,

einfach nach der Zeile

pinMode(BINDING_PIN, INPUT);

Gruß

Dirk
von dibub

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • Gammarex
  • Gammarex's Avatar Offline
  • Senior Mitglied
  • Senior Mitglied
  • Beiträge: 42
  • Dank erhalten: 6

Gammarex antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 28 März 2013 18:51 #23
Moin,

Klaus : der 10kohm Wiederstand muß nicht sein, den habe ich auch nicht eingelötet.

dibub : wenn das Heck stark am zucken ist, könnte sein das die Kreiselempfindlichkeit zu hoch eingestellt ist.
Für die Taummelscheibe kannst du keine Empfindlichkeit einstellen.

Habe das geänderte Programm mal rausgesucht.
Dort habe ich die Eingangskanäle von 8 auf 6 , und die Ausgangskanäle von 1-6 der Reihe nach geändert.
Der Nano braucht nur 6Kanäle zum steuern wenn jetzt 8K. von dem RSAT kommen, und nur 6 vom Spektrum Modul übertragen werden, kann es auch zum wilden zucken der Servos kommen, das war bei mir so.

Gruß Stefan
Last Edit:28 März 2013 18:55 von Gammarex

Anhänge:

Letzte Änderung: 28 März 2013 18:55 von Gammarex.
Folgende Benutzer bedankten sich: dibub

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • klaus
  • klaus's Avatar Offline Autor
  • Platinum Mitglied
  • Platinum Mitglied
  • Beiträge: 372
  • Dank erhalten: 226

klaus antwortete auf DX5-Modul aus Spectrum-Sender in DC16 nutzen?!?!

Posted 29 März 2013 08:42 #24
Hi Stefan,

habe gestern meinen Blade MCPX auf der DC16 prgrammiert - unter anderem den Schalter für den "Motor EIN-AUS".
Allerdings spicht der Schalter nur auf dem Geber Nr. 5 (bei der DC16 rechts aussen an der Seite) an. Wenn ich Pitch gebe läuft der Motor trotzdem an, auch wenn der Schalter auf AUS ist.

Hast du vieleicht eine Idee was ich falsch mache?

Und dann ist da noch ein Problem:
ich wollte den MCPX auch gleich in meiner Ersatzfernsteuerung - eine Grauper MC22S - programmieren.
Soweit lief ales gut, allerding schaffte ich es nicht, den Motor zu sarten.
Auch diverse Änderungen in der Zeile "static byte ChanIndex[] = {1,2,3,4,5,6}; //PPM to DSM2 Channel Mapping Table" brachten nicht den gewünschten Erfolg.
Diese Zeile ist mir sowieso ein Rätsel, denn was bedeutet eigentlich die Reihenfolge genau? Sage ich damit, welchen Kanal das Arduino als erstes und welchen als letztes auswerten soll?

BEISPIEL:
Der Motor am MCPX startet ja, wenn ich den Pitchknüppel nach vorne schiebe. Gleichzeitig gebe ich damit auch Pitch.
Wie muss also die Reihenfolge der Zeile "static byte ChanIndex[]" aussehen?

Mich wundert es eh, dass mein MCPX nun auf die DC16 horcht, obwohl ich eigentlich das alles nicht wirklich durchblicke :blush: :huh:

Gruß klaus
"Meine und Thorn's" Webseite:
[img

Modellfliegen in Südtirol
von klaus

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

Ladezeit der Seite: 1.065 Sekunden