SMALL - espritmodel.com SMALL - Telemetry SMALL - Radio
Reply
Thread Tools
Old Jun 19, 2012, 06:14 AM
Build to Fly? FLY to BUILD!
Legot's Avatar
United States, AZ, Gilbert
Joined Nov 2009
1,104 Posts
It is possible for it to fit in the original module position, mine doesn't simply because I wanted to mount it externaly and not have to take out the Hitec Module. My schematic is in the zip file above in Cadsoft Eagle format.

It is possible to make one in the footprint of the Futaba module using SMD components. If you can etch a board yourself, I would be happy to design a board that should be compatible with Futaba Radios using SMD components. I've gotten much better since I first designed the above board.
Legot is offline Find More Posts by Legot
Reply With Quote
Sign up now
to remove ads between posts
Old Jun 20, 2012, 04:26 AM
jxx
Registered User
Denmark, Region Syddanmark, Esbjerg
Joined Nov 2010
3 Posts
it will be great if you want to create a new layout for FUTABA module box, I want make a drawing of modul box with connectors and various spectrum modules, then we will see whether there can be common components or SMD,,, but has little busy these days, so it can take a little time
jxx is offline Find More Posts by jxx
Reply With Quote
Old Jun 21, 2012, 02:22 PM
Registered User
Joined Feb 2012
5 Posts
Hi,

is the full decoding of the all 16 header bits of the Spektrum protocol known in the meantime?
I have read somewhere that the second byte contains the model memory but for the first header byte I found only a description for some of the bits.
Rooby is offline Find More Posts by Rooby
Reply With Quote
Old Jun 21, 2012, 07:55 PM
I don't want to "Switch Now"
pmackenzie's Avatar
Toronto (Don Mills), Canada
Joined Dec 2002
17,093 Posts
Quote:
Originally Posted by Rooby View Post
Hi,

is the full decoding of the all 16 header bits of the Spektrum protocol known in the meantime?
I have read somewhere that the second byte contains the model memory but for the first header byte I found only a description for some of the bits.
The relevant ones are listed here:
http://www.rcgroups.com/forums/showp...&postcount=309

I played with the "unknowns" and did not find them to do anything at all.

Pat MacKenzie
pmackenzie is offline Find More Posts by pmackenzie
Reply With Quote
Old Jun 22, 2012, 05:15 PM
Registered User
Joined Feb 2012
5 Posts
Quote:
Originally Posted by pmackenzie View Post
The relevant ones are listed here:
http://www.rcgroups.com/forums/showp...&postcount=309

I played with the "unknowns" and did not find them to do anything at all.

Pat MacKenzie
In a german forum I found a statement that in the first header byte there is the RF power coded. But which bits and how was not stated. That's maybe the reason you may found no effect in the "unkowns".
Rooby is offline Find More Posts by Rooby
Reply With Quote
Old Jul 01, 2012, 11:40 PM
Build to Fly? FLY to BUILD!
Legot's Avatar
United States, AZ, Gilbert
Joined Nov 2009
1,104 Posts
Quote:
Originally Posted by jxx View Post
it will be great if you want to create a new layout for FUTABA module box, I want make a drawing of modul box with connectors and various spectrum modules, then we will see whether there can be common components or SMD,,, but has little busy these days, so it can take a little time
Here is an SMD version, I tried to use the smallest number of vias as possible, so it should be possible to make the board as either single sided or double sided.

Changes to the code (for pins) are listed on the board, and it's designed to be programmed through the ISP header to minimize parts/ hassle when bootloading. Idk if you plan to have any boards manufactured, but if you do, make an extra one for me please.

Here is the Bill of Materials: http://www.mouser.com/ProjectManager...sID=198fff7803
Legot is offline Find More Posts by Legot
Reply With Quote
Old Sep 11, 2012, 08:37 PM
Yes, "that" Karl...
karl k's Avatar
Canada, BC, Burnaby
Joined Mar 2007
1,681 Posts
Quote:
Originally Posted by Legot View Post
In case anyone cares.
Mine works flawlessly so far.
Runs on a 2s lipo, 3.3v regulator inside, based on an Atmega168p. If you can make your own boards, using the arduino mini
'is a fair waste of money, all I needed to put on was the Atmega, 2 resistors, the regulator, an 8mhz oscillator, a switch, and a peizo.

Dead simple, costs around $5 without the lipo or module. I'm still refining the board layout, but it definitely works.

I included the board layout if anyone wants to use it, along with the schematic (eagle) if anyone wants to re design the board layout or make it better.
the board included isn't physically the same as the one In my module, but it should be easier to etch. It's single sided, and that PDF is pre-reversed.
--pics later--
Would you mind sharing your code for this?
I have an A9 and have been struggling to get this working and really want to get rid of my DX6i
karl k is offline Find More Posts by karl k
Reply With Quote
Old Sep 12, 2012, 12:24 AM
Build to Fly? FLY to BUILD!
Legot's Avatar
United States, AZ, Gilbert
Joined Nov 2009
1,104 Posts
Quote:
Originally Posted by karl k View Post
Would you mind sharing your code for this?
I have an A9 and have been struggling to get this working and really want to get rid of my DX6i
That one kind of sucks, I just redid the board, I'm much happier with this one. The only thing that changes in the code are the pins and clock speed should be 8mhz. Do you need A BoM, or can you source the parts well enough yourself? Its kind of funny, because I did mine under the assumption that yours was successful

Updated things attached (with correct code). I also added an optional voltage divider for the supply voltage line on Analog_5 so if someone wants to, they can program it to sound the buzzer when the battery gets low.
Legot is offline Find More Posts by Legot
Last edited by Legot; Sep 12, 2012 at 07:49 PM.
Reply With Quote
Old Sep 12, 2012, 12:35 AM
Yes, "that" Karl...
karl k's Avatar
Canada, BC, Burnaby
Joined Mar 2007
1,681 Posts
Quote:
Originally Posted by Legot View Post
That one kind of sucks, I just redid the board, I'm much happier with this one. The only thing that changes in the code are the pins and clock speed should be 8mhz. Do you need A BoM, or can you source the parts well enough yourself? Its kind of funny, because I did mine under the assumption that yours was successful

Updated things attached (with correct code). I also added an optional voltage divider for the supply voltage line on Analog_5 so if someone wants to, they can program it to sound the buzzer when the battery gets low.
Thanks for the quick reply.
That is funny. Mine was working, but had some issues with the mCPx.

I'll play with this over the next day or so. I've got the chipset from an HP6DSM to use.
karl k is offline Find More Posts by karl k
Reply With Quote
Old Sep 13, 2012, 07:08 PM
Yes, "that" Karl...
karl k's Avatar
Canada, BC, Burnaby
Joined Mar 2007
1,681 Posts
Alright... I've got the A9 linking to a UMX plane, but the controls are weird....

DSM module trouble (2 min 17 sec)


This is the debug screen that I see after changing the code to #DEBUG from #NODEBUG

Code:
MIN_IN_PULSE:1000
MAX_IN_PULSE:2300
SYNC_GAP_LEN:4400
State = ACQUIRING
State = READY
Number of channels = 6
SetupEnd
1492>=4400
0   0   00 61 (97)  05 F4 (500)  09 ED (493)  0D EF (495)  11 EA (490)  15 ED (493)  0  0  0   
1493>=4400
1493>=4400
1493>=4400
1493>=4400
9880>=4400
1500>=4400
1493>=4400
1098>=4400
1098>=4400
1495>=4400
1491>=4400
0   0   00 62 (98)  05 F4 (500)  09 ED (493)  0D EF (495)  11 EB (491)  15 ED (493)  0  0  0   
1495>=4400
1490>=4400
1492>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
9873>=4400
1498>=4400
1493>=4400
1091>=4400
1494>=4400
1494>=4400
1491>=4400
0   0   00 5B (91)  05 F2 (498)  09 ED (493)  0D EE (494)  11 EB (491)  15 E5 (485)  0  0  0   
1494>=4400
1491>=4400
1493>=4400
1493>=4400
1493>=4400
1493>=4400
1490>=4400
1490>=4400
1490>=4400
1490>=4400
1490>=4400
1490>=4400
1490>=4400
1490>=4400
9873>=4400
9873>=4400
1500>=4400
1493>=4400
1098>=4400
1495>=4400
1495>=4400
1488>=4400
0   0   00 62 (98)  05 F4 (500)  09 ED (493)  0D EF (495)  11 E8 (488)  15 ED (493)  0  0  0
And here is the code I'm using. Legot seems to get it working, but I have issues.

Code:
#include <WProgram.h>
#include <avr/interrupt.h>
#include <Tone.h>

//#define NODEBUG                              // Change this to #define DEBUG if needed
#define DEBUG

typedef enum {
    NULL_ST = -1, NOT_SYNCHED, ACQUIRING, READY, FAILSAFE
} State_t;

#define PRESCALE           0x42             // if 8Mhz CPU set perscaler to 8 = 0x42, if 16Mhz CPU set prescaler to 64 = 0X43       
#define TICKS_PER_uS       1             // number of timer ticks per 1 microsecond (CPU Speed/Prescale) e.g. CPU at 8MHz/PRESCALE = 1MHz , if CPU at 16Mhz/PRESCALE = .25Mhz 
#define MAX_CHANNELS      6                 // maximum number of channels we can store, don't increase this above 8
#define MIN_IN_PULSE  (1000 * TICKS_PER_uS) // valid pulse must be at least 750us, JR 9X ~= 1050
#define MAX_IN_PULSE  (2300 * TICKS_PER_uS) // valid pulse must be less than 2250us, JR 9X ~= 2211
#define SYNC_GAP_LEN  (4400 * TICKS_PER_uS) // we assume a space at least 5000us is sync, JR 9X ~=4441
#define VALID_FRAMES     10                 // must have this many consecutive valid frames to transition to the ready state.
#define BIND_TIME        10000               // How long to run BindDSM2 8000= mCPx
#define BINDinterval     50
#define ERRORinterval    125

#define DSM2_CHANNELS      6                // Max number of DSM2 Channels transmitted

// Legot Labs Through Hole Board
#define BINDING_PIN        10               // Pin used to bind
#define BINDING_LED        9                // Pin used for Binding in process LED
#define FLASH_LED          13               // LED flash interval in ms
#define SPEAKER_PIN        5                //Pin used for speaker

// "UNO" pinout, used as test board
//#define BINDING_PIN        10               // Pin used to bind
//#define BINDING_LED        9                // Pin used for Binding in process LED
//#define FLASH_LED          11              // LED flash interval in ms
//#define SPEAKER_PIN        5                //Pin used for speaker


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
volatile long ICR1Cn;                       // Store interrupt timer for procising

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[] = {3,1,2,4,5,6};    //PPM to DSM2 Channel Mapping Table
static byte PPMwaitCount;
static int pulse;

long previousMillis = 0;       // will store last time LED was updated
long ERRORpreviousMillis = 0;
long interval = 500;          // interval at which to blink (milliseconds)
byte DisFlash = LOW;

int LEDbrightness = 100;    // how bright the LED is
int LEDfadeAmount = 5;    // how many points to fade the LED by

/* ---------- ---------- ---------- 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; 
    #ifdef DEBUG
    Serial.println("State = FAILSAFE");
    #endif
    }      
  }                                         
  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; 
      #ifdef DEBUG
      Serial.println("State = ACQUIRING");
      #endif      
    } 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
          #ifdef DEBUG
          Serial.println("State = READY");
          Serial.print("Number of channels = ");
          Serial.println(ChannelNum);
          #endif  
        }                                   
      } else                                
        if( State == FAILSAFE) {            
          if(ChannelNum == ChannelCnt)      // did we get good pulses on all channels?
          {
           State = READY;  
          #ifdef DEBUG
          Serial.println("State = READY");
          #endif 
          }          
        }                                   
    }                                       
  }                                         
  ChannelNum = 0;                           // reset the channel counter
}

/* ---------- ---------- ---------- Interrupt Handerling---------- ---------- ---------- */

ISR(TIMER1_OVF_vect) {                      // When an overflow of timer 1 happens set to fail safe mode. e.g PPM is disconnected
  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
  ICR1Cn = ICR1;                            // Move interrupt counter to a Var
  TCNT1 = 0X00;                             // Restet Timer 1 overflow 
  if(ICR1Cn >= 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((ICR1Cn >= MIN_IN_PULSE) && (ICR1Cn <= MAX_IN_PULSE))  // check for valid channel data
        Pulses[++ChannelNum] = ICR1Cn / 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
        }
    }
}

/* ---------- ---------- ---------- PPM Class ---------- ---------- ---------- */
class PPM_Decode {

public:
  PPM_Decode() {                            // Constructor
    // empty                                
  }                                         
                                            
  void begin() {                            // The following is to setup Interrupts / Timers                         
    pinMode(8, INPUT);                      // Timer1 interrupt handler uses pin 8 as input, do not change it
    ChannelNum = 0;                         
    State = NOT_SYNCHED; 
                                                                          // Timer 1 used to trigger on PPM edge
    TIMSK1 = 0x21;                                                        // enable input capture(ICIE1 is bit 5) and overflow (TOIE1 is bit 0) interrupts for timer 1, 0x20 = capture, 0x21 = capture and overflow    
    TCCR1A = 0x00;                                                        // Timer/Counter 1 to Normal Port operation                                          
    TCCR1B = PRESCALE; //(1<<ICES1) | (0<<CS12) | (1<<CS11) | (1<<CS10);        // (ICES1) = capture rising edge on pin ICP1(a.k.a Pin 8),  set prescaler to 64 for 16Mhz  = 0X43
//    TCCR1B = 0x03; //(0<<ICES1) | (0<<CS12) | (1<<CS11) | (1<<CS10);      // (ICES1) = capture falling edge on pin ICP1(a.k.a Pin 8),  set prescaler to 64 for 16Mhz
    
    for(byte ch = 1; ch <= MAX_CHANNELS; ch++) {
      Failsafe[ch] = Pulses[ch] = 1000;     // set midpoint as default values for pulses and failsafe default=1500, JR=1170
    }
    Failsafe[3] = Pulses[3] = 900;       // set channel 3 failsafe pulse width to min throttle default=1100, JR=1050
  }
  
  void stop() {                            // The following is reset Interrupts / Timers to default                        
    State   = NOT_SYNCHED; 
                                                                          // Timer 1 to deafult
    TIMSK1 = 0x00;                                                        // reset timer Triggers to default   
    TCCR1A = 0x00;                                                        // Timer/Counter 1 to Normal Port operation                                          
    TCCR1B = 0x00; 
  }


  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
  Serial.print("MIN_IN_PULSE:");
  Serial.println(MIN_IN_PULSE);  
  Serial.print("MAX_IN_PULSE:");
  Serial.println(MAX_IN_PULSE);     
  Serial.print("SYNC_GAP_LEN:");
  Serial.println(SYNC_GAP_LEN);
  #else
  Serial.begin(125000);                     // closest speed for DSM2 module, otherwise it won't work
  #endif
  pinMode(BINDING_PIN, INPUT);
  pinMode(BINDING_LED, OUTPUT);

  DSM2_Header[0] = 0;                     // Set header data for normal use
  DSM2_Header[1] = 0;                     // Set header data for normal use
  
  if(digitalRead(BINDING_PIN) == HIGH) {  // if bind button pressed at power up enter bind mode
  digitalWrite(BINDING_LED, HIGH);      
//  BindTone();                            //Play Bind Tone
  BindDSM2();                            // Bind Radio with reciver
  }else{
//  NormalTone();                          // Play tone to say setup is completed  
  }

  
  digitalWrite(BINDING_LED,LOW);            // turn off the binding LED
//  DSM2_Header[0] = 0;
  Receiver.begin();                         //Setup PPM interrupts
  PPMwaitCount = 30;
  while(Receiver.getState() != READY && PPMwaitCount-- > 0) // wait 3 sec or until PPM data is stable and ready
  delay(100);

  
      #ifdef DEBUG
      Serial.println("SetupEnd");
      #endif
}

void loop() {
  
    #ifdef DEBUG
    digitalWrite(BINDING_LED,HIGH);
    Serial.print(ICR1);
    Serial.print(">=");
    Serial.println(SYNC_GAP_LEN);
    #endif
    
  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
    }
  }
 
 if (State == READY){ // set LED if all PPM is all Good 
  digitalWrite(BINDING_LED,HIGH);  
 }else{              // Or display "error" 
    unsigned long currentMillis = millis();            
            if(currentMillis - ERRORpreviousMillis >= ERRORinterval)
            {
             ERRORpreviousMillis = millis();
                if (DisFlash == LOW)
                {
                digitalWrite(BINDING_LED,LOW);  // PPM TX LED
                DisFlash = HIGH;
                }
                else
                {
                digitalWrite(BINDING_LED,HIGH);  // PPM TX LED
                DisFlash = LOW;
                }
            }
 }
 
}

#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

void BindDSM2(){
  delay (250);                            // Give time for DSM2 TX to powerup
  DSM2_Header[0] = 0x90;                  //Set header data for Binding
   
     unsigned long currentMillis = BIND_TIME + millis(); 
       
          while(currentMillis > millis()){   //loop till bind time is reached
           unsigned long currentMillis = millis();            
            if(currentMillis - previousMillis > BINDinterval) // Flash LED while in Bind mode.
            {            
             previousMillis = currentMillis;                

                if (DisFlash == LOW)
                {
                digitalWrite(BINDING_LED,LOW);  
                DisFlash = HIGH;
                }
                else
                {
                digitalWrite(BINDING_LED,HIGH);  
                DisFlash = LOW;                
                }
            } 
            sendDSM2();
            delay(20);  // need time for serial read to TX
            }
  DSM2_Header[0] = 0;                      // Set header data for normal use
  digitalWrite(BINDING_LED, LOW);          // turn off the binding LED 
}
karl k is offline Find More Posts by karl k
Reply With Quote
Old Sep 13, 2012, 07:42 PM
I don't want to "Switch Now"
pmackenzie's Avatar
Toronto (Don Mills), Canada
Joined Dec 2002
17,093 Posts
That looks like it could be an issue with the frame rate being wrong, perhaps too long. I know the mcpx was fussy about that.
It looks like the code matches the DSM2 frame rate with the incoming PPM one. It really does need to be the correct 22msec one.

Most of the stand alone receivers are not so fussy, so if you can get an AR6100 and it works fine then it is likely the frame rate problem.

Pat MacKenzie
pmackenzie is offline Find More Posts by pmackenzie
Reply With Quote
Old Sep 13, 2012, 07:48 PM
ROFLCOPTER
Iron Savior's Avatar
United States, KY, Louisville
Joined Mar 2011
230 Posts
Quote:
Originally Posted by karl k View Post
Alright... I've got the A9 linking to a UMX plane, but the controls are weird....
I looked over your code and it doesn't seem to have any means of limiting the rate at which you transmit frames to the radio. It's been my experience that if you send frames too rapidly, things go wrong. I've never seen a servo respond properly if I sent frames more than 1 every 10 milliseconds. For values higher than that, it seems to vary from receiver to receiver. I think the nominal frame rate is supposed to be 1 every 20ms.

My advice would be to enforce a minimum transmission interval between 10ms and 20ms. Don't implement this by making calls to delay(). A better way is to record the current time [with millis(), iirc] every time you call Serial.write() so you can check that value with each loop. If less than your minimum interval has elapsed since the last time you called Serial.write(), then do nothing until the next loop.
Iron Savior is offline Find More Posts by Iron Savior
Reply With Quote
Old Sep 13, 2012, 07:51 PM
Registered User
United States, NH, Exeter
Joined Oct 2010
99 Posts
I just did some work with an A9 using the newest 1.08 firmware and put my oscilloscope on the PPM signal. The frame rate is 23ms. The minimum PPM pulse = 0.900ms and the maximum = 2.1ms. The default values when you create a new model is 1.2ms and 1.9ms
hammer22 is offline Find More Posts by hammer22
Reply With Quote
Old Sep 13, 2012, 08:20 PM
I don't want to "Switch Now"
pmackenzie's Avatar
Toronto (Don Mills), Canada
Joined Dec 2002
17,093 Posts
23 might be too long.
IIRC, the MCPx was unhappy above 22 (similar stuttering), but works fine right down to 11
(I tested a lot working on troubleshooting DSM2 for ER9X)

Pat MacKenzie
pmackenzie is offline Find More Posts by pmackenzie
Reply With Quote
Old Sep 13, 2012, 08:32 PM
RC beginner
New York
Joined Oct 2008
6,054 Posts
Quote:
Originally Posted by Iron Savior View Post
I've never seen a servo respond properly if I sent frames more than 1 every 10 milliseconds.
every one of the dozen or so different servos (vigor, towerpro, hk, 500, 900, etc) work fine down to around 3ms. i actually use 8m rate because 8mhz avr is not capable of proper 20ms period. it will do 2ms but that wont work for obvious reasons.
dave1993 is offline Find More Posts by dave1993
Reply With Quote
Reply


Thread Tools

Similar Threads
Category Thread Thread Starter Forum Replies Last Post
Anybody ever ask you "Why don't you build your own planes?" juantrinidad Electric Plane Talk 21 Feb 26, 2003 10:34 PM
FS: Build your Own Lithium Packs Cheap jcherry Aircraft - Electric - Airplanes (FS/W) 0 Dec 15, 2002 09:01 AM
What's A Good Program To Build Your Own Website For A Begginer? Joe Elston Life, The Universe, and Politics 12 Oct 16, 2002 05:29 AM
Sites on how to build your own batt ZAPPER Kevin Graehl Batteries and Chargers 28 Aug 29, 2002 02:53 AM
Build Your Own Defense Budget CoastalFlyer Life, The Universe, and Politics 6 Jun 02, 2002 04:12 AM